Skip to content

Commit aa9d299

Browse files
authored
Merge pull request #20348 from paldepind/rust/certain-shorthand-self
Rust: Infer certain type for shorthand `self`
2 parents 0752dbe + 26919a6 commit aa9d299

File tree

3 files changed

+65
-65
lines changed

3 files changed

+65
-65
lines changed

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

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,13 @@ module Consistency {
226226

227227
predicate nonUniqueCertainType(AstNode n, TypePath path, Type t) {
228228
strictcount(CertainTypeInference::inferCertainType(n, path)) > 1 and
229-
t = CertainTypeInference::inferCertainType(n, path)
229+
t = CertainTypeInference::inferCertainType(n, path) and
230+
// Suppress the inconsistency if `n` is a self parameter and the type
231+
// mention for the self type has multiple types for a path.
232+
not exists(ImplItemNode impl, TypePath selfTypePath |
233+
n = impl.getAnAssocItem().(Function).getParamList().getSelfParam() and
234+
strictcount(impl.(Impl).getSelfTy().(TypeMention).resolveTypeAt(selfTypePath)) > 1
235+
)
230236
}
231237
}
232238

@@ -250,10 +256,62 @@ private TypeMention getTypeAnnotation(AstNode n) {
250256
)
251257
}
252258

259+
/**
260+
* Gets the type of the implicitly typed `self` parameter, taking into account
261+
* whether the parameter is passed by value or by reference.
262+
*/
263+
bindingset[self, suffix, t]
264+
pragma[inline_late]
265+
private Type getRefAdjustShorthandSelfType(SelfParam self, TypePath suffix, Type t, TypePath path) {
266+
not self.hasTypeRepr() and
267+
(
268+
if self.isRef()
269+
then
270+
// `fn f(&self, ...)`
271+
path.isEmpty() and
272+
result = TRefType()
273+
or
274+
path = TypePath::cons(TRefTypeParameter(), suffix) and
275+
result = t
276+
else (
277+
// `fn f(self, ...)`
278+
path = suffix and
279+
result = t
280+
)
281+
)
282+
}
283+
284+
pragma[nomagic]
285+
private Type resolveImplSelfType(Impl i, TypePath path) {
286+
result = i.getSelfTy().(TypeMention).resolveTypeAt(path)
287+
}
288+
289+
/**
290+
* Gets the type at `path` of the parameter `self` which uses the [shorthand
291+
* syntax][1] which is sugar for an explicit annotation.
292+
*
293+
* [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html#r-associated.fn.method.self-pat-shorthands
294+
*/
295+
pragma[nomagic]
296+
private Type inferShorthandSelfType(SelfParam self, TypePath path) {
297+
exists(ImplOrTraitItemNode i, TypePath suffix, Type t |
298+
self = i.getAnAssocItem().(Function).getParamList().getSelfParam() and
299+
result = getRefAdjustShorthandSelfType(self, suffix, t, path)
300+
|
301+
t = resolveImplSelfType(i, suffix)
302+
or
303+
t = TSelfTypeParameter(i) and suffix.isEmpty()
304+
)
305+
}
306+
253307
/** Gets the type of `n`, which has an explicit type annotation. */
254308
pragma[nomagic]
255309
private Type inferAnnotatedType(AstNode n, TypePath path) {
256310
result = getTypeAnnotation(n).resolveTypeAt(path)
311+
or
312+
// The shorthand self syntax (i.e., a self parameter without a type
313+
// annotation) is sugar for a self parameter with an annotation.
314+
result = inferShorthandSelfType(n, path)
257315
}
258316

259317
/** Module for inferring certain type information. */
@@ -369,10 +427,7 @@ module CertainTypeInference {
369427
*/
370428
pragma[nomagic]
371429
Type inferCertainType(AstNode n, TypePath path) {
372-
exists(TypeMention tm |
373-
tm = getTypeAnnotation(n) and
374-
result = tm.resolveTypeAt(path)
375-
)
430+
result = inferAnnotatedType(n, path)
376431
or
377432
result = inferCertainCallExprType(n, path)
378433
or
@@ -602,50 +657,6 @@ private Type inferTypeEquality(AstNode n, TypePath path) {
602657
)
603658
}
604659

605-
/**
606-
* Gets the type of the implicitly typed `self` parameter, taking into account
607-
* whether the parameter is passed by value or by reference.
608-
*/
609-
bindingset[self, suffix, t]
610-
pragma[inline_late]
611-
private Type getRefAdjustImplicitSelfType(SelfParam self, TypePath suffix, Type t, TypePath path) {
612-
not self.hasTypeRepr() and
613-
(
614-
if self.isRef()
615-
then
616-
// `fn f(&self, ...)`
617-
path.isEmpty() and
618-
result = TRefType()
619-
or
620-
path = TypePath::cons(TRefTypeParameter(), suffix) and
621-
result = t
622-
else (
623-
// `fn f(self, ...)`
624-
path = suffix and
625-
result = t
626-
)
627-
)
628-
}
629-
630-
pragma[nomagic]
631-
private Type resolveImplSelfType(Impl i, TypePath path) {
632-
result = i.getSelfTy().(TypeMention).resolveTypeAt(path)
633-
}
634-
635-
/** Gets the type at `path` of the implicitly typed `self` parameter. */
636-
pragma[nomagic]
637-
private Type inferImplicitSelfType(SelfParam self, TypePath path) {
638-
exists(ImplOrTraitItemNode i, Function f, TypePath suffix, Type t |
639-
f = i.getAnAssocItem() and
640-
self = f.getParamList().getSelfParam() and
641-
result = getRefAdjustImplicitSelfType(self, suffix, t, path)
642-
|
643-
t = resolveImplSelfType(i, suffix)
644-
or
645-
t = TSelfTypeParameter(i) and suffix.isEmpty()
646-
)
647-
}
648-
649660
/**
650661
* A matching configuration for resolving types of struct expressions
651662
* like `Foo { bar = baz }`.
@@ -926,11 +937,8 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
926937
or
927938
exists(SelfParam self |
928939
self = pragma[only_bind_into](this.getParamList().getSelfParam()) and
929-
dpos.isSelf()
930-
|
940+
dpos.isSelf() and
931941
result = inferAnnotatedType(self, path) // `self` parameter with type annotation
932-
or
933-
result = inferImplicitSelfType(self, path) // `self` parameter without type annotation
934942
)
935943
or
936944
// For associated functions, we may also need to match type arguments against
@@ -2420,14 +2428,10 @@ private module Cached {
24202428
else any()
24212429
) and
24222430
(
2423-
result = inferAnnotatedType(n, path)
2424-
or
24252431
result = inferAssignmentOperationType(n, path)
24262432
or
24272433
result = inferTypeEquality(n, path)
24282434
or
2429-
result = inferImplicitSelfType(n, path)
2430-
or
24312435
result = inferStructExprType(n, path)
24322436
or
24332437
result = inferPathExprType(n, path)
@@ -2491,9 +2495,9 @@ private module Debug {
24912495
Input2::conditionSatisfiesConstraint(abs, condition, constraint)
24922496
}
24932497

2494-
predicate debugInferImplicitSelfType(SelfParam self, TypePath path, Type t) {
2498+
predicate debugInferShorthandSelfType(SelfParam self, TypePath path, Type t) {
24952499
self = getRelevantLocatable() and
2496-
t = inferImplicitSelfType(self, path)
2500+
t = inferShorthandSelfType(self, path)
24972501
}
24982502

24992503
predicate debugInferCallExprBaseType(AstNode n, TypePath path, Type t) {

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ mod method_impl {
7373

7474
impl Foo {
7575
pub fn m1(self) -> Self {
76-
self
76+
self // $ certainType=self:Foo
7777
}
7878

7979
pub fn m2(self) -> Foo {
@@ -108,7 +108,7 @@ mod trait_impl {
108108
impl MyTrait<bool> for MyThing {
109109
// MyThing::trait_method
110110
fn trait_method(self) -> bool {
111-
self.field // $ fieldof=MyThing
111+
self.field // $ certainType=self:MyThing fieldof=MyThing
112112
}
113113
}
114114

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,7 +2467,6 @@ inferType
24672467
| main.rs:1328:33:1328:36 | SelfParam | | main.rs:1326:5:1329:5 | Self [trait ATrait] |
24682468
| main.rs:1334:29:1334:33 | SelfParam | | file://:0:0:0:0 | & |
24692469
| main.rs:1334:29:1334:33 | SelfParam | &T | file://:0:0:0:0 | & |
2470-
| main.rs:1334:29:1334:33 | SelfParam | &T | main.rs:1307:5:1310:5 | MyInt |
24712470
| main.rs:1334:29:1334:33 | SelfParam | &T.&T | main.rs:1307:5:1310:5 | MyInt |
24722471
| main.rs:1334:43:1336:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
24732472
| main.rs:1335:13:1335:22 | (...) | | main.rs:1307:5:1310:5 | MyInt |
@@ -2481,7 +2480,6 @@ inferType
24812480
| main.rs:1335:16:1335:20 | * ... | &T | main.rs:1307:5:1310:5 | MyInt |
24822481
| main.rs:1335:17:1335:20 | self | | file://:0:0:0:0 | & |
24832482
| main.rs:1335:17:1335:20 | self | &T | file://:0:0:0:0 | & |
2484-
| main.rs:1335:17:1335:20 | self | &T | main.rs:1307:5:1310:5 | MyInt |
24852483
| main.rs:1335:17:1335:20 | self | &T.&T | main.rs:1307:5:1310:5 | MyInt |
24862484
| main.rs:1339:33:1339:36 | SelfParam | | file://:0:0:0:0 | & |
24872485
| main.rs:1339:33:1339:36 | SelfParam | &T | main.rs:1307:5:1310:5 | MyInt |
@@ -3798,7 +3796,6 @@ inferType
37983796
| main.rs:2030:31:2032:9 | { ... } | | main.rs:2002:5:2002:14 | S2 |
37993797
| main.rs:2031:13:2031:14 | S2 | | main.rs:2002:5:2002:14 | S2 |
38003798
| main.rs:2036:18:2036:22 | SelfParam | | file://:0:0:0:0 | & |
3801-
| main.rs:2036:18:2036:22 | SelfParam | | main.rs:2003:5:2003:22 | S3 |
38023799
| main.rs:2036:18:2036:22 | SelfParam | &T | main.rs:2003:5:2003:22 | S3 |
38033800
| main.rs:2036:18:2036:22 | SelfParam | &T.T3 | main.rs:2035:10:2035:17 | T |
38043801
| main.rs:2036:30:2039:9 | { ... } | | main.rs:2035:10:2035:17 | T |
@@ -3807,7 +3804,6 @@ inferType
38073804
| main.rs:2037:17:2037:21 | S3(...) | &T | main.rs:2003:5:2003:22 | S3 |
38083805
| main.rs:2037:17:2037:21 | S3(...) | &T.T3 | main.rs:2035:10:2035:17 | T |
38093806
| main.rs:2037:25:2037:28 | self | | file://:0:0:0:0 | & |
3810-
| main.rs:2037:25:2037:28 | self | | main.rs:2003:5:2003:22 | S3 |
38113807
| main.rs:2037:25:2037:28 | self | &T | main.rs:2003:5:2003:22 | S3 |
38123808
| main.rs:2037:25:2037:28 | self | &T.T3 | main.rs:2035:10:2035:17 | T |
38133809
| main.rs:2038:13:2038:21 | t.clone() | | main.rs:2035:10:2035:17 | T |

0 commit comments

Comments
 (0)