Skip to content

Commit 3620b64

Browse files
committed
wip2
1 parent 69c7964 commit 3620b64

3 files changed

Lines changed: 65 additions & 99 deletions

File tree

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

Lines changed: 40 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,6 @@ private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
2222

2323
class Type = T::Type;
2424

25-
private newtype TTypeArgumentPosition =
26-
// method type parameters are matched by position instead of by type
27-
// parameter entity, to avoid extra recursion through method call resolution
28-
TMethodTypeArgumentPosition(int pos) {
29-
exists(any(MethodCallExpr mce).getGenericArgList().getTypeArg(pos))
30-
} or
31-
TTypeParamTypeArgumentPosition(TypeParam tp) or
32-
TTypeQualifierArgumentPosition()
33-
3425
private module Input1 implements InputSig1<Location> {
3526
private import Type as T
3627
private import codeql.rust.elements.internal.generated.Raw
@@ -46,22 +37,7 @@ private module Input1 implements InputSig1<Location> {
4637

4738
class TypeAbstraction = TA::TypeAbstraction;
4839

49-
class TypeArgumentPosition extends TTypeArgumentPosition {
50-
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }
51-
52-
TypeParam asTypeParam() { this = TTypeParamTypeArgumentPosition(result) }
53-
54-
predicate isTypeQualifierArgumentPosition() { this = TTypeQualifierArgumentPosition() }
55-
56-
string toString() {
57-
result = this.asMethodTypeArgumentPosition().toString()
58-
or
59-
result = this.asTypeParam().toString()
60-
or
61-
this.isTypeQualifierArgumentPosition() and
62-
result = "type qualifier"
63-
}
64-
}
40+
class TypeArgumentPosition = int;
6541

6642
private newtype TTypeParameterPosition = TTypeParamTypeParameterPosition(TypeParameter tp)
6743

@@ -78,18 +54,7 @@ private module Input1 implements InputSig1<Location> {
7854
bindingset[apos]
7955
bindingset[ppos]
8056
predicate typeArgumentParameterPositionMatch(TypeArgumentPosition apos, TypeParameterPosition ppos) {
81-
TTypeParamTypeParameter(apos.asTypeParam()) = ppos.asTypeParameter()
82-
or
83-
apos.asMethodTypeArgumentPosition() = ppos.asTypeParam().getPosition()
84-
or
85-
// Type qualifiers can match against implicit `Self` type parameters and blanket
86-
// type parameters.
87-
apos.isTypeQualifierArgumentPosition() and
88-
(
89-
ppos.asTypeParameter() instanceof SelfTypeParameter
90-
or
91-
exists(ImplItemNode i | ppos.asTypeParam() = i.getBlanketImplementationTypeParam())
92-
)
57+
apos = ppos.asTypeParam().getPosition()
9358
}
9459

9560
int getTypeParameterId(TypeParameter tp) {
@@ -460,12 +425,24 @@ private module Input3 implements InputSig3 {
460425

461426
abstract TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp);
462427

428+
abstract TypeMention getDeclaringType();
429+
430+
// todo
431+
Type getDeclaringType(TypePath path) { result = this.getDeclaringType().getTypeAt(path) }
432+
463433
abstract Parameter getParameter(int i);
464434

465435
abstract TypeMention getType();
466436
}
467437

468438
class Callable extends ParameterizableImpl instanceof Rust::Callable {
439+
override TypeMention getDeclaringType() {
440+
exists(ImplOrTraitItemNode implOrTrait | this = implOrTrait.getAnAssocItem() |
441+
result = implOrTrait.(Impl).getSelfTy() or
442+
result = implOrTrait.(Trait)
443+
)
444+
}
445+
469446
override TypeParameter getTypeParameter(TypeParameterPosition ppos) {
470447
result = this.(FunctionDeclaration).getTypeParameter(ppos)
471448
}
@@ -492,6 +469,10 @@ private module Input3 implements InputSig3 {
492469
additional final class Constructor = ConstructorImpl;
493470

494471
abstract private class ConstructorImpl extends ParameterizableImpl {
472+
override TypeMention getDeclaringType() {
473+
result = this.getTypeItem() // todo?
474+
}
475+
495476
override TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp) { none() }
496477

497478
override TypeParameter getTypeParameter(TypeParameterPosition ppos) {
@@ -564,6 +545,8 @@ private module Input3 implements InputSig3 {
564545
final class Invocation = InvocationImpl;
565546

566547
abstract private class InvocationImpl extends Expr {
548+
abstract TypeMention getTypeQualifier();
549+
567550
abstract Type getTypeArgument(TypeArgumentPosition apos, TypePath path);
568551

569552
abstract AstNode getArgument(int i);
@@ -573,14 +556,12 @@ private module Input3 implements InputSig3 {
573556

574557
private class AssocFunctionCall extends InvocationImpl instanceof AssocFunctionResolution::AssocFunctionCall
575558
{
559+
override TypeMention getTypeQualifier() { result = getCallExprTypeArgument2(this) }
560+
576561
pragma[nomagic]
577562
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
578563
result =
579-
this.(MethodCallExpr)
580-
.getGenericArgList()
581-
.getTypeArg(apos.asMethodTypeArgumentPosition())
582-
.(TypeMention)
583-
.getTypeAt(path)
564+
this.(MethodCallExpr).getGenericArgList().getTypeArg(apos).(TypeMention).getTypeAt(path)
584565
or
585566
result = getCallExprTypeArgument(this, apos, path)
586567
}
@@ -622,6 +603,8 @@ private module Input3 implements InputSig3 {
622603
private class NonAssocFunctionCall extends InvocationImpl instanceof NonAssocCallExpr,
623604
CallExprImpl::CallExprCall
624605
{
606+
override TypeMention getTypeQualifier() { none() }
607+
625608
pragma[nomagic]
626609
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
627610
result = NonAssocCallExpr.super.getTypeArgument(apos, path)
@@ -658,6 +641,8 @@ private module Input3 implements InputSig3 {
658641
this instanceof CallExprImpl::TupleVariantExpr
659642
}
660643

644+
override TypeMention getTypeQualifier() { result = getCallExprTypeArgument2(this) }
645+
661646
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
662647
result = NonAssocCallExpr.super.getTypeArgument(apos, path)
663648
}
@@ -676,27 +661,16 @@ private module Input3 implements InputSig3 {
676661
pragma[nomagic]
677662
override Constructor getTarget() { result = resolvePath(super.getPath()) }
678663

679-
pragma[nomagic]
680-
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
664+
override TypeMention getTypeQualifier() {
681665
// Handle constructions that use `Self {...}` syntax
682-
exists(TypeMention tm, TypePath path0 |
683-
tm = super.getPath() and
684-
result = tm.getTypeAt(path0) and
685-
path0.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path)
686-
)
666+
result = super.getPath()
687667
}
668+
669+
pragma[nomagic]
670+
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
688671
}
689672

690673
private class StructExprConstruction extends StructConstruction, StructExpr {
691-
override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
692-
result = super.getTypeArgument(apos, path)
693-
or
694-
exists(TypePath suffix |
695-
suffix.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path) and
696-
result = inferTypeCertain(this, suffix)
697-
)
698-
}
699-
700674
override AstNode getArgument(int i) {
701675
result =
702676
this.getFieldExpr(pragma[only_bind_into](this.getNthStructField(i).getName().getText()))
@@ -1215,62 +1189,29 @@ private class AssocFunctionDeclaration extends FunctionDeclaration {
12151189
}
12161190

12171191
pragma[nomagic]
1218-
private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
1219-
exists(ImplItemNode impl |
1220-
tp = impl.getTypeParam(_) and
1221-
TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).getTypeAt(result)
1192+
private Type getCallExprTypeArgument(CallExpr ce, int pos, TypePath path) {
1193+
exists(Path p | p = CallExprImpl::getFunctionPath(ce) |
1194+
result = getPathTypeArgument(p, pos).getTypeAt(path)
12221195
)
12231196
}
12241197

12251198
pragma[nomagic]
1226-
private Type getCallExprTypeArgument(CallExpr ce, TypeArgumentPosition apos, TypePath path) {
1199+
private TypeMention getCallExprTypeArgument2(CallExpr ce) {
12271200
exists(Path p | p = CallExprImpl::getFunctionPath(ce) |
1228-
exists(ItemNode resolved, TypeParam tp |
1229-
resolved = resolvePath(p) and
1230-
apos.asTypeParam() = tp
1231-
|
1232-
// For type parameters of the function we must resolve their
1233-
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
1234-
// and the path `bar<i64>`, we must resolve `A` to `i64`.
1235-
exists(int i |
1236-
tp = resolved.getTypeParam(pragma[only_bind_into](i)) and
1237-
result = getPathTypeArgument(p, pragma[only_bind_into](i)).getTypeAt(path)
1238-
)
1239-
or
1240-
// For type parameters of the `impl` block we must resolve their
1241-
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
1242-
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
1243-
exists(ImplItemNode impl, TypePath pathToTp |
1244-
resolved = impl.getASuccessor(_) and
1245-
tp = impl.getTypeParam(_) and
1246-
pathToTp = getPathToImplSelfTypeParam(tp) and
1247-
result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(path))
1248-
)
1249-
)
1250-
or
1251-
exists(Path qualifier, TypeMention tm |
1201+
exists(Path qualifier |
12521202
qualifier = p.getQualifier() and
1253-
result = tm.getTypeAt(path) and
1254-
not tm.getType() instanceof TraitType and
1255-
apos.isTypeQualifierArgumentPosition()
1203+
not result.getType() instanceof TraitType
12561204
|
1257-
tm = qualifier
1205+
result = qualifier
12581206
or
12591207
// `<Foo as Bar>::baz()`; `Foo` is the type qualifier
12601208
exists(PathSegment segment |
12611209
segment = qualifier.getSegment() and
1262-
tm = segment.getTypeRepr() and
1210+
result = segment.getTypeRepr() and
12631211
segment.hasTraitTypeRepr()
12641212
)
12651213
)
12661214
)
1267-
or
1268-
// Handle constructions that use `Self(...)` syntax
1269-
exists(Path p, TypePath path0 |
1270-
p = CallExprImpl::getFunctionPath(ce) and
1271-
result = p.(TypeMention).getTypeAt(path0) and
1272-
path0.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path)
1273-
)
12741215
}
12751216

12761217
/**

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6109,12 +6109,14 @@ inferType
61096109
| dereference.rs:144:17:144:26 | key_to_key | K | {EXTERNAL LOCATION} | & |
61106110
| dereference.rs:144:17:144:26 | key_to_key | K.TRef | dereference.rs:122:5:123:21 | Key |
61116111
| dereference.rs:144:17:144:26 | key_to_key | S | {EXTERNAL LOCATION} | RandomState |
6112+
| dereference.rs:144:17:144:26 | key_to_key | V | dereference.rs:122:5:123:21 | Key |
61126113
| dereference.rs:144:17:144:26 | key_to_key | V | {EXTERNAL LOCATION} | & |
61136114
| dereference.rs:144:17:144:26 | key_to_key | V.TRef | dereference.rs:122:5:123:21 | Key |
61146115
| dereference.rs:144:30:144:54 | ...::new(...) | | {EXTERNAL LOCATION} | HashMap |
61156116
| dereference.rs:144:30:144:54 | ...::new(...) | K | {EXTERNAL LOCATION} | & |
61166117
| dereference.rs:144:30:144:54 | ...::new(...) | K.TRef | dereference.rs:122:5:123:21 | Key |
61176118
| dereference.rs:144:30:144:54 | ...::new(...) | S | {EXTERNAL LOCATION} | RandomState |
6119+
| dereference.rs:144:30:144:54 | ...::new(...) | V | dereference.rs:122:5:123:21 | Key |
61186120
| dereference.rs:144:30:144:54 | ...::new(...) | V | {EXTERNAL LOCATION} | & |
61196121
| dereference.rs:144:30:144:54 | ...::new(...) | V.TRef | dereference.rs:122:5:123:21 | Key |
61206122
| dereference.rs:145:17:145:19 | key | | {EXTERNAL LOCATION} | & |
@@ -6125,19 +6127,23 @@ inferType
61256127
| dereference.rs:146:9:149:9 | if ... {...} | | {EXTERNAL LOCATION} | () |
61266128
| dereference.rs:146:16:146:28 | Some(...) | | {EXTERNAL LOCATION} | Option |
61276129
| dereference.rs:146:16:146:28 | Some(...) | T | {EXTERNAL LOCATION} | & |
6130+
| dereference.rs:146:16:146:28 | Some(...) | T.TRef | dereference.rs:122:5:123:21 | Key |
61286131
| dereference.rs:146:16:146:28 | Some(...) | T.TRef | {EXTERNAL LOCATION} | & |
61296132
| dereference.rs:146:16:146:28 | Some(...) | T.TRef.TRef | dereference.rs:122:5:123:21 | Key |
61306133
| dereference.rs:146:21:146:27 | ref_key | | {EXTERNAL LOCATION} | & |
6134+
| dereference.rs:146:21:146:27 | ref_key | TRef | dereference.rs:122:5:123:21 | Key |
61316135
| dereference.rs:146:21:146:27 | ref_key | TRef | {EXTERNAL LOCATION} | & |
61326136
| dereference.rs:146:21:146:27 | ref_key | TRef.TRef | dereference.rs:122:5:123:21 | Key |
61336137
| dereference.rs:146:32:146:41 | key_to_key | | {EXTERNAL LOCATION} | HashMap |
61346138
| dereference.rs:146:32:146:41 | key_to_key | K | {EXTERNAL LOCATION} | & |
61356139
| dereference.rs:146:32:146:41 | key_to_key | K.TRef | dereference.rs:122:5:123:21 | Key |
61366140
| dereference.rs:146:32:146:41 | key_to_key | S | {EXTERNAL LOCATION} | RandomState |
6141+
| dereference.rs:146:32:146:41 | key_to_key | V | dereference.rs:122:5:123:21 | Key |
61376142
| dereference.rs:146:32:146:41 | key_to_key | V | {EXTERNAL LOCATION} | & |
61386143
| dereference.rs:146:32:146:41 | key_to_key | V.TRef | dereference.rs:122:5:123:21 | Key |
61396144
| dereference.rs:146:32:146:50 | key_to_key.get(...) | | {EXTERNAL LOCATION} | Option |
61406145
| dereference.rs:146:32:146:50 | key_to_key.get(...) | T | {EXTERNAL LOCATION} | & |
6146+
| dereference.rs:146:32:146:50 | key_to_key.get(...) | T.TRef | dereference.rs:122:5:123:21 | Key |
61416147
| dereference.rs:146:32:146:50 | key_to_key.get(...) | T.TRef | {EXTERNAL LOCATION} | & |
61426148
| dereference.rs:146:32:146:50 | key_to_key.get(...) | T.TRef.TRef | dereference.rs:122:5:123:21 | Key |
61436149
| dereference.rs:146:47:146:49 | key | | {EXTERNAL LOCATION} | & |
@@ -6149,15 +6155,18 @@ inferType
61496155
| dereference.rs:148:13:148:15 | key | TRef.TRef | dereference.rs:122:5:123:21 | Key |
61506156
| dereference.rs:148:13:148:25 | ... = ... | | {EXTERNAL LOCATION} | () |
61516157
| dereference.rs:148:19:148:25 | ref_key | | {EXTERNAL LOCATION} | & |
6158+
| dereference.rs:148:19:148:25 | ref_key | TRef | dereference.rs:122:5:123:21 | Key |
61526159
| dereference.rs:148:19:148:25 | ref_key | TRef | {EXTERNAL LOCATION} | & |
61536160
| dereference.rs:148:19:148:25 | ref_key | TRef.TRef | dereference.rs:122:5:123:21 | Key |
61546161
| dereference.rs:150:9:150:18 | key_to_key | | {EXTERNAL LOCATION} | HashMap |
61556162
| dereference.rs:150:9:150:18 | key_to_key | K | {EXTERNAL LOCATION} | & |
61566163
| dereference.rs:150:9:150:18 | key_to_key | K.TRef | dereference.rs:122:5:123:21 | Key |
61576164
| dereference.rs:150:9:150:18 | key_to_key | S | {EXTERNAL LOCATION} | RandomState |
6165+
| dereference.rs:150:9:150:18 | key_to_key | V | dereference.rs:122:5:123:21 | Key |
61586166
| dereference.rs:150:9:150:18 | key_to_key | V | {EXTERNAL LOCATION} | & |
61596167
| dereference.rs:150:9:150:18 | key_to_key | V.TRef | dereference.rs:122:5:123:21 | Key |
61606168
| dereference.rs:150:9:150:35 | key_to_key.insert(...) | | {EXTERNAL LOCATION} | Option |
6169+
| dereference.rs:150:9:150:35 | key_to_key.insert(...) | T | dereference.rs:122:5:123:21 | Key |
61616170
| dereference.rs:150:9:150:35 | key_to_key.insert(...) | T | {EXTERNAL LOCATION} | & |
61626171
| dereference.rs:150:9:150:35 | key_to_key.insert(...) | T.TRef | dereference.rs:122:5:123:21 | Key |
61636172
| dereference.rs:150:27:150:29 | key | | {EXTERNAL LOCATION} | & |
@@ -14309,6 +14318,7 @@ inferType
1430914318
| pattern_matching.rs:809:13:809:17 | stack | T | {EXTERNAL LOCATION} | i32 |
1431014319
| pattern_matching.rs:809:31:809:46 | MacroExpr | | {EXTERNAL LOCATION} | Vec |
1431114320
| pattern_matching.rs:809:31:809:46 | MacroExpr | A | {EXTERNAL LOCATION} | Global |
14321+
| pattern_matching.rs:809:31:809:46 | MacroExpr | T | {EXTERNAL LOCATION} | i32 |
1431214322
| pattern_matching.rs:809:36:809:39 | 1i32 | | {EXTERNAL LOCATION} | i32 |
1431314323
| pattern_matching.rs:809:42:809:42 | 2 | | {EXTERNAL LOCATION} | i32 |
1431414324
| pattern_matching.rs:809:45:809:45 | 3 | | {EXTERNAL LOCATION} | i32 |

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21162116

21172117
/** A parameterizable element, such as a function or variant constructor. */
21182118
class Parameterizable extends AstNode {
2119+
/** Gets the type at `path` of the entity that declares this member. */
2120+
Type getDeclaringType(TypePath path);
2121+
21192122
/**
21202123
* Gets the type parameter at position `ppos` of this element, if any.
21212124
*
@@ -2189,6 +2192,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21892192
*/
21902193
AstNode getArgument(int i);
21912194

2195+
TypeMention getTypeQualifier();
2196+
21922197
/** Gets the target of this invocation in the given resolution context. */
21932198
Parameterizable getTarget(ResolutionContext ctx);
21942199
}
@@ -2933,6 +2938,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
29332938
/** Gets the position used to represent the return type of a callable/type of a call. */
29342939
additional int getReturnPosition() { result = -1 }
29352940

2941+
/** Gets the position used to represent the declaring type of a callable/type qualifier of a call. */
2942+
additional int getDeclaringPosition() { result = -2 }
2943+
29362944
final private class ParameterizableFinal = Parameterizable;
29372945

29382946
class Declaration extends ParameterizableFinal {
@@ -2941,6 +2949,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
29412949
or
29422950
dpos = getReturnPosition() and
29432951
result = getParameterizableType(this, path)
2952+
or
2953+
dpos = getDeclaringPosition() and
2954+
result = this.getDeclaringType(path)
29442955
}
29452956
}
29462957

@@ -2969,6 +2980,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
29692980
or
29702981
result = this.getInferredResultType(apos, path) and
29712982
exists(e)
2983+
or
2984+
result = this.getTypeQualifier().getTypeAt(path) and
2985+
apos = getDeclaringPosition() and
2986+
exists(e)
29722987
}
29732988

29742989
Declaration getTarget(AccessEnvironment e) { result = super.getTarget(e) }

0 commit comments

Comments
 (0)