Skip to content

Commit e212af1

Browse files
committed
Rust: Implement support for inference of type aliases
1 parent 6f21df8 commit e212af1

File tree

3 files changed

+85
-13
lines changed

3 files changed

+85
-13
lines changed

Diff for: rust/ql/lib/codeql/rust/internal/TypeMention.qll

+48-1
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.getSegment().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.getSegment().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 {

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,11 @@ mod type_aliases {
559559
// Alias to another alias
560560
type AliasToAlias<A4> = AnotherPair<A4>;
561561

562-
// Alias that appears nested withing another alias
562+
// Alias that appears nested within another alias
563563
type NestedAlias<A5> = AnotherPair<AliasToAlias<A5>>;
564564

565565
fn g(t: NestedAlias<S3>) {
566-
println!("{:?}", t.unwrapSnd().unwrapSnd()); // missing
566+
println!("{:?}", t.unwrapSnd().unwrapSnd());
567567
}
568568

569569
pub fn f() {
@@ -572,18 +572,18 @@ mod type_aliases {
572572
println!("{:?}", p1);
573573

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

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

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

586-
g(PairOption::PairSnd(PairOption::PairSnd(S3))); // missing
586+
g(PairOption::PairSnd(PairOption::PairSnd(S3)));
587587
}
588588
}
589589

Diff for: rust/ql/test/library-tests/type-inference/type-inference.expected

+31-6
Original file line numberDiff line numberDiff line change
@@ -672,9 +672,19 @@ inferType
672672
| main.rs:539:41:539:43 | snd | | main.rs:533:15:533:17 | Snd |
673673
| main.rs:539:49:539:51 | snd | | main.rs:533:15:533:17 | Snd |
674674
| main.rs:565:10:565:10 | t | | main.rs:525:5:531:5 | enum PairOption |
675-
| main.rs:565:10:565:10 | t | Fst | main.rs:550:5:551:14 | struct S3 |
675+
| main.rs:565:10:565:10 | t | Fst | main.rs:547:5:548:14 | struct S2 |
676+
| main.rs:565:10:565:10 | t | Snd | main.rs:525:5:531:5 | enum PairOption |
677+
| main.rs:565:10:565:10 | t | Snd.Fst | main.rs:547:5:548:14 | struct S2 |
678+
| main.rs:565:10:565:10 | t | Snd.Snd | main.rs:550:5:551:14 | struct S3 |
676679
| main.rs:566:26:566:26 | t | | main.rs:525:5:531:5 | enum PairOption |
677-
| main.rs:566:26:566:26 | t | Fst | main.rs:550:5:551:14 | struct S3 |
680+
| main.rs:566:26:566:26 | t | Fst | main.rs:547:5:548:14 | struct S2 |
681+
| main.rs:566:26:566:26 | t | Snd | main.rs:525:5:531:5 | enum PairOption |
682+
| main.rs:566:26:566:26 | t | Snd.Fst | main.rs:547:5:548:14 | struct S2 |
683+
| main.rs:566:26:566:26 | t | Snd.Snd | main.rs:550:5:551:14 | struct S3 |
684+
| main.rs:566:26:566:38 | t.unwrapSnd(...) | | main.rs:525:5:531:5 | enum PairOption |
685+
| main.rs:566:26:566:38 | t.unwrapSnd(...) | Fst | main.rs:547:5:548:14 | struct S2 |
686+
| main.rs:566:26:566:38 | t.unwrapSnd(...) | Snd | main.rs:550:5:551:14 | struct S3 |
687+
| main.rs:566:26:566:50 | ... .unwrapSnd(...) | | main.rs:550:5:551:14 | struct S3 |
678688
| main.rs:571:13:571:14 | p1 | | main.rs:525:5:531:5 | enum PairOption |
679689
| main.rs:571:13:571:14 | p1 | Fst | main.rs:544:5:545:14 | struct S1 |
680690
| main.rs:571:13:571:14 | p1 | Snd | main.rs:547:5:548:14 | struct S2 |
@@ -687,26 +697,40 @@ inferType
687697
| main.rs:572:26:572:27 | p1 | Fst | main.rs:544:5:545:14 | struct S1 |
688698
| main.rs:572:26:572:27 | p1 | Snd | main.rs:547:5:548:14 | struct S2 |
689699
| main.rs:575:13:575:14 | p2 | | main.rs:525:5:531:5 | enum PairOption |
700+
| main.rs:575:13:575:14 | p2 | Fst | main.rs:544:5:545:14 | struct S1 |
701+
| main.rs:575:13:575:14 | p2 | Snd | main.rs:547:5:548:14 | struct S2 |
690702
| main.rs:575:26:575:47 | ...::PairNone(...) | | main.rs:525:5:531:5 | enum PairOption |
703+
| main.rs:575:26:575:47 | ...::PairNone(...) | Fst | main.rs:544:5:545:14 | struct S1 |
704+
| main.rs:575:26:575:47 | ...::PairNone(...) | Snd | main.rs:547:5:548:14 | struct S2 |
691705
| main.rs:576:26:576:27 | p2 | | main.rs:525:5:531:5 | enum PairOption |
706+
| main.rs:576:26:576:27 | p2 | Fst | main.rs:544:5:545:14 | struct S1 |
707+
| main.rs:576:26:576:27 | p2 | Snd | main.rs:547:5:548:14 | struct S2 |
692708
| main.rs:579:13:579:14 | p3 | | main.rs:525:5:531:5 | enum PairOption |
709+
| main.rs:579:13:579:14 | p3 | Fst | main.rs:547:5:548:14 | struct S2 |
693710
| main.rs:579:13:579:14 | p3 | Snd | main.rs:550:5:551:14 | struct S3 |
694711
| main.rs:579:34:579:56 | ...::PairSnd(...) | | main.rs:525:5:531:5 | enum PairOption |
712+
| main.rs:579:34:579:56 | ...::PairSnd(...) | Fst | main.rs:547:5:548:14 | struct S2 |
695713
| main.rs:579:34:579:56 | ...::PairSnd(...) | Snd | main.rs:550:5:551:14 | struct S3 |
696714
| main.rs:579:54:579:55 | S3 | | main.rs:550:5:551:14 | struct S3 |
697715
| main.rs:580:26:580:27 | p3 | | main.rs:525:5:531:5 | enum PairOption |
716+
| main.rs:580:26:580:27 | p3 | Fst | main.rs:547:5:548:14 | struct S2 |
698717
| main.rs:580:26:580:27 | p3 | Snd | main.rs:550:5:551:14 | struct S3 |
699718
| main.rs:583:13:583:14 | p3 | | main.rs:525:5:531:5 | enum PairOption |
700-
| main.rs:583:13:583:14 | p3 | Fst | main.rs:550:5:551:14 | struct S3 |
719+
| main.rs:583:13:583:14 | p3 | Fst | main.rs:547:5:548:14 | struct S2 |
720+
| main.rs:583:13:583:14 | p3 | Snd | main.rs:550:5:551:14 | struct S3 |
701721
| main.rs:583:35:583:56 | ...::PairNone(...) | | main.rs:525:5:531:5 | enum PairOption |
702-
| main.rs:583:35:583:56 | ...::PairNone(...) | Fst | main.rs:550:5:551:14 | struct S3 |
722+
| main.rs:583:35:583:56 | ...::PairNone(...) | Fst | main.rs:547:5:548:14 | struct S2 |
723+
| main.rs:583:35:583:56 | ...::PairNone(...) | Snd | main.rs:550:5:551:14 | struct S3 |
703724
| main.rs:584:26:584:27 | p3 | | main.rs:525:5:531:5 | enum PairOption |
704-
| main.rs:584:26:584:27 | p3 | Fst | main.rs:550:5:551:14 | struct S3 |
725+
| main.rs:584:26:584:27 | p3 | Fst | main.rs:547:5:548:14 | struct S2 |
726+
| main.rs:584:26:584:27 | p3 | Snd | main.rs:550:5:551:14 | struct S3 |
705727
| main.rs:586:11:586:54 | ...::PairSnd(...) | | main.rs:525:5:531:5 | enum PairOption |
706-
| main.rs:586:11:586:54 | ...::PairSnd(...) | Fst | main.rs:550:5:551:14 | struct S3 |
728+
| main.rs:586:11:586:54 | ...::PairSnd(...) | Fst | main.rs:547:5:548:14 | struct S2 |
707729
| main.rs:586:11:586:54 | ...::PairSnd(...) | Snd | main.rs:525:5:531:5 | enum PairOption |
730+
| main.rs:586:11:586:54 | ...::PairSnd(...) | Snd.Fst | main.rs:547:5:548:14 | struct S2 |
708731
| main.rs:586:11:586:54 | ...::PairSnd(...) | Snd.Snd | main.rs:550:5:551:14 | struct S3 |
709732
| main.rs:586:31:586:53 | ...::PairSnd(...) | | main.rs:525:5:531:5 | enum PairOption |
733+
| main.rs:586:31:586:53 | ...::PairSnd(...) | Fst | main.rs:547:5:548:14 | struct S2 |
710734
| main.rs:586:31:586:53 | ...::PairSnd(...) | Snd | main.rs:550:5:551:14 | struct S3 |
711735
| main.rs:586:51:586:52 | S3 | | main.rs:550:5:551:14 | struct S3 |
712736
| main.rs:598:16:598:24 | SelfParam | | file://:0:0:0:0 | & |
@@ -1102,6 +1126,7 @@ resolveMethodCallExpr
11021126
| main.rs:470:26:470:31 | x.m3(...) | main.rs:424:9:433:9 | fn m3 |
11031127
| main.rs:471:26:471:31 | y.m3(...) | main.rs:424:9:433:9 | fn m3 |
11041128
| main.rs:566:26:566:38 | t.unwrapSnd(...) | main.rs:534:9:541:9 | fn unwrapSnd |
1129+
| main.rs:566:26:566:50 | ... .unwrapSnd(...) | main.rs:534:9:541:9 | fn unwrapSnd |
11051130
| main.rs:601:13:601:27 | self.set(...) | main.rs:598:9:598:36 | fn set |
11061131
| main.rs:632:9:632:17 | x2.set(...) | main.rs:606:9:606:38 | fn set |
11071132
| main.rs:636:9:636:22 | x3.call_set(...) | main.rs:600:9:602:9 | fn call_set |

0 commit comments

Comments
 (0)