Skip to content

Commit 254eabf

Browse files
authored
Merge pull request #19557 from paldepind/rust/type-mention-consistency
Rust: Only include relevant AST nodes in TypeMention
2 parents b071a46 + 5228062 commit 254eabf

File tree

8 files changed

+125
-89
lines changed

8 files changed

+125
-89
lines changed

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ private Type getRefAdjustImplicitSelfType(SelfParam self, TypePath suffix, Type
312312

313313
pragma[nomagic]
314314
private Type resolveImplSelfType(Impl i, TypePath path) {
315-
result = i.getSelfTy().(TypeReprMention).resolveTypeAt(path)
315+
result = i.getSelfTy().(TypeMention).resolveTypeAt(path)
316316
}
317317

318318
/** Gets the type at `path` of the implicitly typed `self` parameter. */
@@ -375,7 +375,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
375375

376376
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
377377
// type of a field
378-
exists(TypeReprMention tp |
378+
exists(TypeMention tp |
379379
tp = this.getField(dpos.asFieldPos()).getTypeRepr() and
380380
result = tp.resolveTypeAt(path)
381381
)
@@ -535,7 +535,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
535535

536536
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
537537
exists(int pos |
538-
result = this.getTupleField(pos).getTypeRepr().(TypeReprMention).resolveTypeAt(path) and
538+
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
539539
dpos = TPositionalDeclarationPosition(pos, false)
540540
)
541541
}
@@ -558,7 +558,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
558558

559559
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
560560
exists(int p |
561-
result = this.getTupleField(p).getTypeRepr().(TypeReprMention).resolveTypeAt(path) and
561+
result = this.getTupleField(p).getTypeRepr().(TypeMention).resolveTypeAt(path) and
562562
dpos = TPositionalDeclarationPosition(p, false)
563563
)
564564
}
@@ -606,7 +606,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
606606
}
607607

608608
override Type getReturnType(TypePath path) {
609-
result = this.getRetType().getTypeRepr().(TypeReprMention).resolveTypeAt(path)
609+
result = this.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
610610
}
611611
}
612612

@@ -644,7 +644,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
644644
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
645645

646646
class Access extends CallExprBase {
647-
private TypeReprMention getMethodTypeArg(int i) {
647+
private TypeMention getMethodTypeArg(int i) {
648648
result = this.(MethodCallExpr).getGenericArgList().getTypeArg(i)
649649
}
650650

@@ -829,7 +829,7 @@ private module FieldExprMatchingInput implements MatchingInputSig {
829829
)
830830
or
831831
dpos.isField() and
832-
result = this.getTypeRepr().(TypeReprMention).resolveTypeAt(path)
832+
result = this.getTypeRepr().(TypeMention).resolveTypeAt(path)
833833
}
834834
}
835835

rust/ql/lib/codeql/rust/internal/TypeInferenceConsistency.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,28 @@
22
* Provides classes for recognizing type inference inconsistencies.
33
*/
44

5+
private import Type
6+
private import TypeMention
7+
private import TypeInference::Consistency as Consistency
58
import TypeInference::Consistency
9+
10+
query predicate illFormedTypeMention(TypeMention tm) {
11+
Consistency::illFormedTypeMention(tm) and
12+
// Only include inconsistencies in the source, as we otherwise get
13+
// inconsistencies from library code in every project.
14+
tm.fromSource()
15+
}
16+
17+
int getTypeInferenceInconsistencyCounts(string type) {
18+
type = "Missing type parameter ID" and
19+
result = count(TypeParameter tp | missingTypeParameterId(tp) | tp)
20+
or
21+
type = "Non-functional type parameter ID" and
22+
result = count(TypeParameter tp | nonFunctionalTypeParameterId(tp) | tp)
23+
or
24+
type = "Non-injective type parameter ID" and
25+
result = count(TypeParameter tp | nonInjectiveTypeParameterId(tp, _) | tp)
26+
or
27+
type = "Ill-formed type mention" and
28+
result = count(TypeMention tm | illFormedTypeMention(tm) | tm)
29+
}

rust/ql/lib/codeql/rust/internal/TypeMention.qll

Lines changed: 68 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -31,53 +31,33 @@ abstract class TypeMention extends AstNode {
3131
Type resolveTypeAt(TypePath path) { result = this.getMentionAt(path).resolveType() }
3232
}
3333

34-
class TypeReprMention extends TypeMention, TypeRepr {
35-
TypeReprMention() { not this instanceof InferTypeRepr }
34+
class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
35+
override TypeMention getTypeArgument(int i) { result = super.getElementTypeRepr() and i = 0 }
3636

37-
override TypeReprMention getTypeArgument(int i) {
38-
result = this.(ArrayTypeRepr).getElementTypeRepr() and
39-
i = 0
40-
or
41-
result = this.(RefTypeRepr).getTypeRepr() and
42-
i = 0
43-
or
44-
result = this.(PathTypeRepr).getPath().(PathMention).getTypeArgument(i)
45-
}
37+
override Type resolveType() { result = TArrayType() }
38+
}
4639

47-
override Type resolveType() {
48-
this instanceof ArrayTypeRepr and
49-
result = TArrayType()
50-
or
51-
this instanceof RefTypeRepr and
52-
result = TRefType()
53-
or
54-
result = this.(PathTypeRepr).getPath().(PathMention).resolveType()
55-
}
40+
class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
41+
override TypeMention getTypeArgument(int i) { result = super.getTypeRepr() and i = 0 }
5642

57-
override Type resolveTypeAt(TypePath path) {
58-
result = this.(PathTypeRepr).getPath().(PathMention).resolveTypeAt(path)
59-
or
60-
not exists(this.(PathTypeRepr).getPath()) and
61-
result = super.resolveTypeAt(path)
62-
}
43+
override Type resolveType() { result = TRefType() }
6344
}
6445

65-
/** Holds if `path` resolves to the type alias `alias` with the definition `rhs`. */
66-
private predicate resolvePathAlias(Path path, TypeAlias alias, TypeReprMention rhs) {
67-
alias = resolvePath(path) and rhs = alias.getTypeRepr()
68-
}
46+
class PathTypeReprMention extends TypeMention instanceof PathTypeRepr {
47+
Path path;
48+
ItemNode resolved;
6949

70-
abstract class PathMention extends TypeMention, Path {
71-
override TypeMention getTypeArgument(int i) {
72-
result = this.getSegment().getGenericArgList().getTypeArg(i)
50+
PathTypeReprMention() {
51+
path = super.getPath() and
52+
// NOTE: This excludes unresolvable paths which is intentional as these
53+
// don't add value to the type inference anyway.
54+
resolved = resolvePath(path)
7355
}
74-
}
7556

76-
class NonAliasPathMention extends PathMention {
77-
NonAliasPathMention() { not resolvePathAlias(this, _, _) }
57+
ItemNode getResolved() { result = resolved }
7858

7959
override TypeMention getTypeArgument(int i) {
80-
result = super.getTypeArgument(i)
60+
result = path.getSegment().getGenericArgList().getTypeArg(i)
8161
or
8262
// `Self` paths inside `impl` blocks have implicit type arguments that are
8363
// the type parameters of the `impl` block. For example, in
@@ -92,106 +72,112 @@ class NonAliasPathMention extends PathMention {
9272
//
9373
// the `Self` return type is shorthand for `Foo<T>`.
9474
exists(ImplItemNode node |
95-
this = node.getASelfPath() and
75+
path = node.getASelfPath() and
9676
result = node.(ImplItemNode).getSelfPath().getSegment().getGenericArgList().getTypeArg(i)
9777
)
9878
or
99-
// If `this` is the trait of an `impl` block then any associated types
79+
// If `path` is the trait of an `impl` block then any associated types
10080
// defined in the `impl` block are type arguments to the trait.
10181
//
10282
// For instance, for a trait implementation like this
10383
// ```rust
10484
// impl MyTrait for MyType {
105-
// ^^^^^^^ this
85+
// ^^^^^^^ path
10686
// type AssociatedType = i64
10787
// ^^^ result
10888
// // ...
10989
// }
11090
// ```
11191
// the rhs. of the type alias is a type argument to the trait.
11292
exists(ImplItemNode impl, AssociatedTypeTypeParameter param, TypeAlias alias |
113-
this = impl.getTraitPath() and
114-
param.getTrait() = resolvePath(this) and
93+
path = impl.getTraitPath() and
94+
param.getTrait() = resolved and
11595
alias = impl.getASuccessor(param.getTypeAlias().getName().getText()) and
11696
result = alias.getTypeRepr() and
11797
param.getIndex() = i
11898
)
11999
}
120100

101+
/**
102+
* Holds if this path resolved to a type alias with a rhs. that has the
103+
* resulting type at `typePath`.
104+
*/
105+
Type aliasResolveTypeAt(TypePath typePath) {
106+
exists(TypeAlias alias, TypeMention rhs | alias = resolved and rhs = alias.getTypeRepr() |
107+
result = rhs.resolveTypeAt(typePath) and
108+
not result = pathGetTypeParameter(alias, _)
109+
or
110+
exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i |
111+
tp = rhs.resolveTypeAt(prefix) and
112+
tp = pathGetTypeParameter(alias, i) and
113+
arg = path.getSegment().getGenericArgList().getTypeArg(i) and
114+
result = arg.resolveTypeAt(suffix) and
115+
typePath = prefix.append(suffix)
116+
)
117+
)
118+
}
119+
121120
override Type resolveType() {
122-
exists(ItemNode i | i = resolvePath(this) |
123-
result = TStruct(i)
121+
result = this.aliasResolveTypeAt(TypePath::nil())
122+
or
123+
not exists(resolved.(TypeAlias).getTypeRepr()) and
124+
(
125+
result = TStruct(resolved)
124126
or
125-
result = TEnum(i)
127+
result = TEnum(resolved)
126128
or
127-
exists(TraitItemNode trait | trait = i |
129+
exists(TraitItemNode trait | trait = resolved |
128130
// If this is a `Self` path, then it resolves to the implicit `Self`
129131
// type parameter, otherwise it is a trait bound.
130-
if this = trait.getASelfPath()
132+
if super.getPath() = trait.getASelfPath()
131133
then result = TSelfTypeParameter(trait)
132134
else result = TTrait(trait)
133135
)
134136
or
135-
result = TTypeParamTypeParameter(i)
137+
result = TTypeParamTypeParameter(resolved)
136138
or
137-
exists(TypeAlias alias | alias = i |
139+
exists(TypeAlias alias | alias = resolved |
138140
result.(AssociatedTypeTypeParameter).getTypeAlias() = alias
139141
or
140-
result = alias.getTypeRepr().(TypeReprMention).resolveType()
142+
result = alias.getTypeRepr().(TypeMention).resolveType()
141143
)
142144
)
143145
}
144-
}
145-
146-
class AliasPathMention extends PathMention {
147-
TypeAlias alias;
148-
TypeReprMention rhs;
149-
150-
AliasPathMention() { resolvePathAlias(this, alias, rhs) }
151-
152-
/** Get the `i`th type parameter of the alias itself. */
153-
private TypeParameter getTypeParameter(int i) {
154-
result = TTypeParamTypeParameter(alias.getGenericParamList().getTypeParam(i))
155-
}
156-
157-
override Type resolveType() { result = rhs.resolveType() }
158146

159-
override Type resolveTypeAt(TypePath path) {
160-
result = rhs.resolveTypeAt(path) and
161-
not result = this.getTypeParameter(_)
147+
override Type resolveTypeAt(TypePath typePath) {
148+
result = this.aliasResolveTypeAt(typePath)
162149
or
163-
exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i |
164-
tp = rhs.resolveTypeAt(prefix) and
165-
tp = this.getTypeParameter(i) and
166-
arg = this.getTypeArgument(i) and
167-
result = arg.resolveTypeAt(suffix) and
168-
path = prefix.append(suffix)
169-
)
150+
not exists(resolved.(TypeAlias).getTypeRepr()) and
151+
result = super.resolveTypeAt(typePath)
170152
}
171153
}
172154

155+
private TypeParameter pathGetTypeParameter(TypeAlias alias, int i) {
156+
result = TTypeParamTypeParameter(alias.getGenericParamList().getTypeParam(i))
157+
}
158+
173159
// Used to represent implicit `Self` type arguments in traits and `impl` blocks,
174160
// see `PathMention` for details.
175-
class TypeParamMention extends TypeMention, TypeParam {
176-
override TypeReprMention getTypeArgument(int i) { none() }
161+
class TypeParamMention extends TypeMention instanceof TypeParam {
162+
override TypeMention getTypeArgument(int i) { none() }
177163

178164
override Type resolveType() { result = TTypeParamTypeParameter(this) }
179165
}
180166

181167
// Used to represent implicit type arguments for associated types in traits.
182-
class TypeAliasMention extends TypeMention, TypeAlias {
168+
class TypeAliasMention extends TypeMention instanceof TypeAlias {
183169
private Type t;
184170

185171
TypeAliasMention() { t = TAssociatedTypeTypeParameter(this) }
186172

187-
override TypeReprMention getTypeArgument(int i) { none() }
173+
override TypeMention getTypeArgument(int i) { none() }
188174

189175
override Type resolveType() { result = t }
190176
}
191177

192-
class TraitMention extends TypeMention, TraitItemNode {
178+
class TraitMention extends TypeMention instanceof TraitItemNode {
193179
override TypeMention getTypeArgument(int i) {
194-
result = this.getTypeParam(i)
180+
result = super.getTypeParam(i)
195181
or
196182
traitAliasIndex(this, i, result)
197183
}
@@ -203,7 +189,7 @@ class TraitMention extends TypeMention, TraitItemNode {
203189
// appears in the AST, we (somewhat arbitrarily) choose the name of a trait as a
204190
// type mention. This works because there is a one-to-one correspondence between
205191
// a trait and its name.
206-
class SelfTypeParameterMention extends TypeMention, Name {
192+
class SelfTypeParameterMention extends TypeMention instanceof Name {
207193
Trait trait;
208194

209195
SelfTypeParameterMention() { trait.getName() = this }
@@ -212,5 +198,5 @@ class SelfTypeParameterMention extends TypeMention, Name {
212198

213199
override Type resolveType() { result = TSelfTypeParameter(trait) }
214200

215-
override TypeReprMention getTypeArgument(int i) { none() }
201+
override TypeMention getTypeArgument(int i) { none() }
216202
}

rust/ql/src/queries/summary/Stats.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import codeql.rust.dataflow.internal.DataFlowImpl
88
private import codeql.rust.dataflow.internal.TaintTrackingImpl
99
private import codeql.rust.internal.AstConsistency as AstConsistency
1010
private import codeql.rust.internal.PathResolutionConsistency as PathResolutionConsistency
11+
private import codeql.rust.internal.TypeInferenceConsistency as TypeInferenceConsistency
1112
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
1213
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
1314
private import codeql.rust.dataflow.internal.SsaImpl::Consistency as SsaConsistency
@@ -52,6 +53,13 @@ int getTotalPathResolutionInconsistencies() {
5253
sum(string type | | PathResolutionConsistency::getPathResolutionInconsistencyCounts(type))
5354
}
5455

56+
/**
57+
* Gets a count of the total number of type inference inconsistencies in the database.
58+
*/
59+
int getTotalTypeInferenceInconsistencies() {
60+
result = sum(string type | | TypeInferenceConsistency::getTypeInferenceInconsistencyCounts(type))
61+
}
62+
5563
/**
5664
* Gets a count of the total number of control flow graph inconsistencies in the database.
5765
*/
@@ -159,6 +167,13 @@ predicate inconsistencyStats(string key, int value) {
159167
key = "Inconsistencies - data flow" and value = getTotalDataFlowInconsistencies()
160168
}
161169

170+
/**
171+
* Gets summary statistics about inconsistencies related to type inference.
172+
*/
173+
predicate typeInferenceInconsistencyStats(string key, int value) {
174+
key = "Inconsistencies - Type inference" and value = getTotalTypeInferenceInconsistencies()
175+
}
176+
162177
/**
163178
* Gets summary statistics about taint.
164179
*/

rust/ql/src/queries/summary/SummaryStats.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ where
1717
or
1818
inconsistencyStats(key, value)
1919
or
20+
typeInferenceInconsistencyStats(key, value)
21+
or
2022
taintStats(key, value)
2123
select key, value order by key
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
illFormedTypeMention
2+
| sqlx.rs:158:13:158:81 | ...::BoxDynError |
3+
| sqlx.rs:160:17:160:86 | ...::BoxDynError |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
illFormedTypeMention
2+
| main.rs:403:18:403:24 | FuncPtr |

shared/typeinference/codeql/typeinference/internal/TypeInference.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13141314
getTypeParameterId(tp1) = getTypeParameterId(tp2) and
13151315
tp1 != tp2
13161316
}
1317+
1318+
query predicate illFormedTypeMention(TypeMention tm) {
1319+
not exists(tm.resolveTypeAt(TypePath::nil())) and exists(tm.getLocation())
1320+
}
13171321
}
13181322
}
13191323
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy