Skip to content

Commit 3e997f2

Browse files
committed
Rust: Implement support for inference of type aliases
1 parent fb2b7e8 commit 3e997f2

3 files changed

Lines changed: 84 additions & 12 deletions

File tree

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

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,25 @@ class TypeReprMention extends TypeMention, TypeRepr {
7474
or
7575
result = this.(PathTypeRepr).getPath().(PathMention).resolveType()
7676
}
77+
78+
override Type resolveTypeAt(TypePath path) {
79+
result = this.(PathTypeRepr).getPath().(PathMention).resolveTypeAt(path)
80+
or
81+
not exists(this.(PathTypeRepr).getPath()) and
82+
result = super.resolveTypeAt(path)
83+
}
84+
}
85+
86+
/** Holds if `path` resolves the type alias `alias` with the definition `rhs`. */
87+
private predicate resolvePathAlias(Path path, TypeAlias alias, TypeReprMention rhs) {
88+
alias = resolvePath(path) and rhs = alias.getTypeRepr()
7789
}
7890

79-
class PathMention extends TypeMention, Path {
91+
abstract class PathMention extends TypeMention, Path { }
92+
93+
class NonAliasPathMention extends PathMention {
94+
NonAliasPathMention() { not resolvePathAlias(this, _, _) }
95+
8096
override TypeMention getTypeArgument(int i) {
8197
result = this.getPart().getGenericArgList().getTypeArg(i)
8298
or
@@ -114,6 +130,37 @@ class PathMention extends TypeMention, Path {
114130
}
115131
}
116132

133+
class AliasPathMention extends PathMention {
134+
TypeAlias alias;
135+
TypeReprMention rhs;
136+
137+
AliasPathMention() { resolvePathAlias(this, alias, rhs) }
138+
139+
override TypeMention getTypeArgument(int i) {
140+
result = this.getPart().getGenericArgList().getTypeArg(i)
141+
}
142+
143+
/** Get the `i`th type parameter of the alias itself. */
144+
private TypeParameter getTypeParameter(int i) {
145+
result = TTypeParamTypeParameter(alias.getGenericParamList().getTypeParam(i))
146+
}
147+
148+
override Type resolveType() { result = rhs.resolveType() }
149+
150+
override Type resolveTypeAt(TypePath path) {
151+
result = rhs.resolveTypeAt(path) and
152+
not result = this.getTypeParameter(_)
153+
or
154+
exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i |
155+
tp = rhs.resolveTypeAt(prefix) and
156+
tp = this.getTypeParameter(i) and
157+
arg = this.getTypeArgument(i) and
158+
result = arg.resolveTypeAt(suffix) and
159+
path = prefix.append(suffix)
160+
)
161+
}
162+
}
163+
117164
// Used to represent implicit `Self` type arguments in traits and `impl` blocks,
118165
// see `PathMention` for details.
119166
class TypeParamMention extends TypeMention, TypeParam {

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ mod type_aliases {
547547
type NestedAlias<A5> = AnotherPair<AliasToAlias<A5>>;
548548

549549
fn g(t: NestedAlias<S3>) {
550-
println!("{:?}", t.unwrapSnd().unwrapSnd()); // missing
550+
println!("{:?}", t.unwrapSnd().unwrapSnd());
551551
}
552552

553553
pub fn f() {
@@ -556,18 +556,18 @@ mod type_aliases {
556556
println!("{:?}", p1);
557557

558558
// Type can be only inferred from the type alias
559-
let p2: MyPair = PairOption::PairNone(); // types for `Fst` and `Snd` missing
559+
let p2: MyPair = PairOption::PairNone();
560560
println!("{:?}", p2);
561561

562562
// First type from alias, second from constructor
563-
let p3: AnotherPair<_> = PairOption::PairSnd(S3); // type for `Fst` missing
563+
let p3: AnotherPair<_> = PairOption::PairSnd(S3);
564564
println!("{:?}", p3);
565565

566566
// First type from alias definition, second from argument to alias
567-
let p3: AnotherPair<S3> = PairOption::PairNone(); // type for `Snd` missing, spurious `S3` for `Fst`
567+
let p3: AnotherPair<S3> = PairOption::PairNone();
568568
println!("{:?}", p3);
569569

570-
g(PairOption::PairSnd(PairOption::PairSnd(S3))); // missing
570+
g(PairOption::PairSnd(PairOption::PairSnd(S3)));
571571
}
572572
}
573573

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

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,19 @@ inferType
631631
| main.rs:523:41:523:43 | snd | | main.rs:517:15:517:17 | Snd |
632632
| main.rs:523:49:523:51 | snd | | main.rs:517:15:517:17 | Snd |
633633
| main.rs:549:10:549:10 | t | | main.rs:509:5:515:5 | enum PairOption |
634-
| main.rs:549:10:549:10 | t | Fst | main.rs:534:5:535:14 | struct S3 |
634+
| main.rs:549:10:549:10 | t | Fst | main.rs:531:5:532:14 | struct S2 |
635+
| main.rs:549:10:549:10 | t | Snd | main.rs:509:5:515:5 | enum PairOption |
636+
| main.rs:549:10:549:10 | t | Snd.Fst | main.rs:531:5:532:14 | struct S2 |
637+
| main.rs:549:10:549:10 | t | Snd.Snd | main.rs:534:5:535:14 | struct S3 |
635638
| main.rs:550:26:550:26 | t | | main.rs:509:5:515:5 | enum PairOption |
636-
| main.rs:550:26:550:26 | t | Fst | main.rs:534:5:535:14 | struct S3 |
639+
| main.rs:550:26:550:26 | t | Fst | main.rs:531:5:532:14 | struct S2 |
640+
| main.rs:550:26:550:26 | t | Snd | main.rs:509:5:515:5 | enum PairOption |
641+
| main.rs:550:26:550:26 | t | Snd.Fst | main.rs:531:5:532:14 | struct S2 |
642+
| main.rs:550:26:550:26 | t | Snd.Snd | main.rs:534:5:535:14 | struct S3 |
643+
| main.rs:550:26:550:38 | t.unwrapSnd(...) | | main.rs:509:5:515:5 | enum PairOption |
644+
| main.rs:550:26:550:38 | t.unwrapSnd(...) | Fst | main.rs:531:5:532:14 | struct S2 |
645+
| main.rs:550:26:550:38 | t.unwrapSnd(...) | Snd | main.rs:534:5:535:14 | struct S3 |
646+
| main.rs:550:26:550:50 | ... .unwrapSnd(...) | | main.rs:534:5:535:14 | struct S3 |
637647
| main.rs:555:13:555:14 | p1 | | main.rs:509:5:515:5 | enum PairOption |
638648
| main.rs:555:13:555:14 | p1 | Fst | main.rs:528:5:529:14 | struct S1 |
639649
| main.rs:555:13:555:14 | p1 | Snd | main.rs:531:5:532:14 | struct S2 |
@@ -646,26 +656,40 @@ inferType
646656
| main.rs:556:26:556:27 | p1 | Fst | main.rs:528:5:529:14 | struct S1 |
647657
| main.rs:556:26:556:27 | p1 | Snd | main.rs:531:5:532:14 | struct S2 |
648658
| main.rs:559:13:559:14 | p2 | | main.rs:509:5:515:5 | enum PairOption |
659+
| main.rs:559:13:559:14 | p2 | Fst | main.rs:528:5:529:14 | struct S1 |
660+
| main.rs:559:13:559:14 | p2 | Snd | main.rs:531:5:532:14 | struct S2 |
649661
| main.rs:559:26:559:47 | ...::PairNone(...) | | main.rs:509:5:515:5 | enum PairOption |
662+
| main.rs:559:26:559:47 | ...::PairNone(...) | Fst | main.rs:528:5:529:14 | struct S1 |
663+
| main.rs:559:26:559:47 | ...::PairNone(...) | Snd | main.rs:531:5:532:14 | struct S2 |
650664
| main.rs:560:26:560:27 | p2 | | main.rs:509:5:515:5 | enum PairOption |
665+
| main.rs:560:26:560:27 | p2 | Fst | main.rs:528:5:529:14 | struct S1 |
666+
| main.rs:560:26:560:27 | p2 | Snd | main.rs:531:5:532:14 | struct S2 |
651667
| main.rs:563:13:563:14 | p3 | | main.rs:509:5:515:5 | enum PairOption |
668+
| main.rs:563:13:563:14 | p3 | Fst | main.rs:531:5:532:14 | struct S2 |
652669
| main.rs:563:13:563:14 | p3 | Snd | main.rs:534:5:535:14 | struct S3 |
653670
| main.rs:563:34:563:56 | ...::PairSnd(...) | | main.rs:509:5:515:5 | enum PairOption |
671+
| main.rs:563:34:563:56 | ...::PairSnd(...) | Fst | main.rs:531:5:532:14 | struct S2 |
654672
| main.rs:563:34:563:56 | ...::PairSnd(...) | Snd | main.rs:534:5:535:14 | struct S3 |
655673
| main.rs:563:54:563:55 | S3 | | main.rs:534:5:535:14 | struct S3 |
656674
| main.rs:564:26:564:27 | p3 | | main.rs:509:5:515:5 | enum PairOption |
675+
| main.rs:564:26:564:27 | p3 | Fst | main.rs:531:5:532:14 | struct S2 |
657676
| main.rs:564:26:564:27 | p3 | Snd | main.rs:534:5:535:14 | struct S3 |
658677
| main.rs:567:13:567:14 | p3 | | main.rs:509:5:515:5 | enum PairOption |
659-
| main.rs:567:13:567:14 | p3 | Fst | main.rs:534:5:535:14 | struct S3 |
678+
| main.rs:567:13:567:14 | p3 | Fst | main.rs:531:5:532:14 | struct S2 |
679+
| main.rs:567:13:567:14 | p3 | Snd | main.rs:534:5:535:14 | struct S3 |
660680
| main.rs:567:35:567:56 | ...::PairNone(...) | | main.rs:509:5:515:5 | enum PairOption |
661-
| main.rs:567:35:567:56 | ...::PairNone(...) | Fst | main.rs:534:5:535:14 | struct S3 |
681+
| main.rs:567:35:567:56 | ...::PairNone(...) | Fst | main.rs:531:5:532:14 | struct S2 |
682+
| main.rs:567:35:567:56 | ...::PairNone(...) | Snd | main.rs:534:5:535:14 | struct S3 |
662683
| main.rs:568:26:568:27 | p3 | | main.rs:509:5:515:5 | enum PairOption |
663-
| main.rs:568:26:568:27 | p3 | Fst | main.rs:534:5:535:14 | struct S3 |
684+
| main.rs:568:26:568:27 | p3 | Fst | main.rs:531:5:532:14 | struct S2 |
685+
| main.rs:568:26:568:27 | p3 | Snd | main.rs:534:5:535:14 | struct S3 |
664686
| main.rs:570:11:570:54 | ...::PairSnd(...) | | main.rs:509:5:515:5 | enum PairOption |
665-
| main.rs:570:11:570:54 | ...::PairSnd(...) | Fst | main.rs:534:5:535:14 | struct S3 |
687+
| main.rs:570:11:570:54 | ...::PairSnd(...) | Fst | main.rs:531:5:532:14 | struct S2 |
666688
| main.rs:570:11:570:54 | ...::PairSnd(...) | Snd | main.rs:509:5:515:5 | enum PairOption |
689+
| main.rs:570:11:570:54 | ...::PairSnd(...) | Snd.Fst | main.rs:531:5:532:14 | struct S2 |
667690
| main.rs:570:11:570:54 | ...::PairSnd(...) | Snd.Snd | main.rs:534:5:535:14 | struct S3 |
668691
| main.rs:570:31:570:53 | ...::PairSnd(...) | | main.rs:509:5:515:5 | enum PairOption |
692+
| main.rs:570:31:570:53 | ...::PairSnd(...) | Fst | main.rs:531:5:532:14 | struct S2 |
669693
| main.rs:570:31:570:53 | ...::PairSnd(...) | Snd | main.rs:534:5:535:14 | struct S3 |
670694
| main.rs:570:51:570:52 | S3 | | main.rs:534:5:535:14 | struct S3 |
671695
| main.rs:582:16:582:24 | SelfParam | | file://:0:0:0:0 | & |
@@ -1060,6 +1084,7 @@ resolveMethodCallExpr
10601084
| main.rs:454:26:454:31 | x.m3(...) | main.rs:408:9:417:9 | fn m3 |
10611085
| main.rs:455:26:455:31 | y.m3(...) | main.rs:408:9:417:9 | fn m3 |
10621086
| main.rs:550:26:550:38 | t.unwrapSnd(...) | main.rs:518:9:525:9 | fn unwrapSnd |
1087+
| main.rs:550:26:550:50 | ... .unwrapSnd(...) | main.rs:518:9:525:9 | fn unwrapSnd |
10631088
| main.rs:585:13:585:27 | self.set(...) | main.rs:582:9:582:36 | fn set |
10641089
| main.rs:616:9:616:17 | x2.set(...) | main.rs:590:9:590:38 | fn set |
10651090
| main.rs:620:9:620:22 | x3.call_set(...) | main.rs:584:9:586:9 | fn call_set |

0 commit comments

Comments
 (0)