Skip to content

Commit 17b773e

Browse files
committed
wip2
1 parent ee9d4fe commit 17b773e

2 files changed

Lines changed: 273 additions & 243 deletions

File tree

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

Lines changed: 85 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,14 @@ private module Input3 implements InputSig3 {
278278

279279
class ParenExpr = Rust::ParenExpr;
280280

281+
final class Declaration = DeclarationImpl;
282+
283+
abstract private class DeclarationImpl extends AstNode {
284+
abstract Type getDeclaringType(TypePath path);
285+
286+
abstract TypeMention getType();
287+
}
288+
281289
private newtype TLocalVariable =
282290
TVariableVariable(Rust::Variable v) or
283291
TConstVariable(Const c) or
@@ -316,14 +324,14 @@ private module Input3 implements InputSig3 {
316324
Location getLocation() { result = this.getDefiningNode().getLocation() }
317325
}
318326

319-
abstract class LocalVariableDeclaration extends AstNode {
327+
abstract class LocalVariableDeclaration extends DeclarationImpl {
320328
abstract predicate isCoercionSite();
321329

322-
abstract TypeMention getType();
323-
324330
abstract AstNode getPattern();
325331

326332
abstract AstNode getInitializer();
333+
334+
override Type getDeclaringType(TypePath path) { none() }
327335
}
328336

329337
private class LetExprDeclaration extends LocalVariableDeclaration instanceof LetExpr {
@@ -354,6 +362,71 @@ private module Input3 implements InputSig3 {
354362
override AstNode getInitializer() { result = LetStmt.super.getInitializer() }
355363
}
356364

365+
abstract class Field extends DeclarationImpl {
366+
// no case for variants as those can only be destructured using pattern matching
367+
abstract Struct getStruct();
368+
369+
override Type getDeclaringType(TypePath path) {
370+
exists(Struct s | s = this.getStruct() |
371+
result = TDataType(s) and
372+
path.isEmpty()
373+
or
374+
result = TTypeParamTypeParameter(s.getGenericParamList().getATypeParam()) and
375+
path = TypePath::singleton(result)
376+
)
377+
}
378+
}
379+
380+
private class StructFieldDecl extends Field instanceof StructField {
381+
override Struct getStruct() { this = result.getAStructField() }
382+
383+
override TypeMention getType() { result = StructField.super.getTypeRepr() }
384+
}
385+
386+
private class TupleFieldDecl extends Field instanceof TupleField {
387+
override Struct getStruct() { this = result.getATupleField() }
388+
389+
override TypeMention getType() { result = TupleField.super.getTypeRepr() }
390+
}
391+
392+
class FieldAccess extends FieldExpr {
393+
Expr getReceiver() { result = this.getContainer() }
394+
395+
Field getField() {
396+
// mutual recursion; resolving fields requires resolving types and vice versa
397+
result =
398+
[
399+
resolveStructFieldExpr(this, _).(AstNode),
400+
resolveTupleFieldExpr(this, _)
401+
]
402+
}
403+
}
404+
405+
Type inferFieldAccessReceiverType(FieldAccess fa, TypePath path) {
406+
exists(TypePath path0 | result = inferType(fa.getReceiver(), path0) |
407+
// adjust for implicit deref
408+
path0.isCons(getRefTypeParameter(_), path)
409+
or
410+
not path0.isCons(getRefTypeParameter(_), _) and
411+
not (result instanceof RefType and path0.isEmpty()) and
412+
path = path0
413+
)
414+
}
415+
416+
Type inferFieldAccessReceiverTypeContextual(Expr receiver, TypePath path) {
417+
exists(TypePath path0, Type receiverType |
418+
result = M3::inferFieldAccessReceiverTypeContextualDefault(_, receiver, path0) and
419+
receiverType = inferType(receiver) and
420+
not path0.isEmpty()
421+
|
422+
// adjust for implicit deref
423+
path = TypePath::cons(receiverType.(RefType).getPositionalTypeParameter(0), path0)
424+
or
425+
not receiverType instanceof RefType and
426+
path = path0
427+
)
428+
}
429+
357430
final class Parameter = ParameterImpl;
358431

359432
/** A parameter, including enum/struct constructor fields. */
@@ -389,19 +462,18 @@ private module Input3 implements InputSig3 {
389462

390463
final class Parameterizable = ParameterizableImpl;
391464

392-
abstract private class ParameterizableImpl extends AstNode {
465+
abstract private class ParameterizableImpl extends DeclarationImpl {
393466
abstract TypeParameter getTypeParameter(int pos);
394467

395468
abstract TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp);
396469

397470
abstract TypeMention getDeclaringType();
398471

399-
// todo
400-
Type getDeclaringType(TypePath path) { result = this.getDeclaringType().getTypeAt(path) }
472+
final override Type getDeclaringType(TypePath path) {
473+
result = this.getDeclaringType().getTypeAt(path)
474+
}
401475

402476
abstract Parameter getParameter(int i);
403-
404-
abstract TypeMention getType();
405477
}
406478

407479
class Callable extends ParameterizableImpl instanceof Rust::Callable {
@@ -470,19 +542,17 @@ private module Input3 implements InputSig3 {
470542
}
471543
}
472544

473-
Type getParameterizableType(Parameterizable p, TypePath path) {
474-
result = p.(Constructor).getType().getTypeAt(path)
475-
or
476-
if p.(Function).isAsync() or p.(ClosureExpr).isAsync()
545+
Type getCallableReturnType(Callable c, TypePath path) {
546+
if c.(Function).isAsync() or c.(ClosureExpr).isAsync()
477547
then
478548
path.isEmpty() and
479549
result = getFutureTraitType()
480550
or
481551
exists(TypePath suffix |
482-
result = getReturnTypeMention(p).getTypeAt(suffix) and
552+
result = getReturnTypeMention(c).getTypeAt(suffix) and
483553
path = TypePath::cons(getDynFutureOutputTypeParameter(), suffix)
484554
)
485-
else result = getReturnTypeMention(p).getTypeAt(path)
555+
else result = getReturnTypeMention(c).getTypeAt(path)
486556
}
487557

488558
class ResolutionContext = string;
@@ -793,67 +863,6 @@ private module Input3 implements InputSig3 {
793863
)
794864
}
795865

796-
abstract class Member extends AstNode {
797-
Type getDeclaringType(TypePath path) {
798-
// no case for variants as those can only be destructured using pattern matching
799-
exists(Struct s | this = [s.getStructField(_).(AstNode), s.getTupleField(_)] |
800-
result = TDataType(s) and
801-
path.isEmpty()
802-
or
803-
result = TTypeParamTypeParameter(s.getGenericParamList().getATypeParam()) and
804-
path = TypePath::singleton(result)
805-
)
806-
}
807-
808-
abstract TypeMention getType();
809-
}
810-
811-
private class StructFieldDecl extends Member instanceof StructField {
812-
override TypeMention getType() { result = StructField.super.getTypeRepr() }
813-
}
814-
815-
private class TupleFieldDecl extends Member instanceof TupleField {
816-
override TypeMention getType() { result = TupleField.super.getTypeRepr() }
817-
}
818-
819-
class MemberAccess extends FieldExpr {
820-
AstNode getReceiver() { result = this.getContainer() }
821-
822-
Member getMember() {
823-
// mutual recursion; resolving fields requires resolving types and vice versa
824-
result =
825-
[
826-
resolveStructFieldExpr(this, _).(AstNode),
827-
resolveTupleFieldExpr(this, _)
828-
]
829-
}
830-
}
831-
832-
Type inferMemberAccessReceiverType(MemberAccess ma, TypePath path) {
833-
exists(TypePath path0 | result = inferType(ma.getReceiver(), path0) |
834-
// adjust for implicit deref
835-
path0.isCons(getRefTypeParameter(_), path)
836-
or
837-
not path0.isCons(getRefTypeParameter(_), _) and
838-
not (result instanceof RefType and path0.isEmpty()) and
839-
path = path0
840-
)
841-
}
842-
843-
Type inferMemberAccessReceiverTypeContextual(AstNode n, TypePath path) {
844-
exists(TypePath path0, Type receiverType |
845-
result = M3::inferMemberAccessReceiverTypeContextualDefault(_, n, path0) and
846-
receiverType = inferType(n) and
847-
not path0.isEmpty()
848-
|
849-
// adjust for implicit deref
850-
path = TypePath::cons(receiverType.(RefType).getPositionalTypeParameter(0), path0)
851-
or
852-
not receiverType instanceof RefType and
853-
path = path0
854-
)
855-
}
856-
857866
class Closure extends Expr, Callable instanceof Rust::ClosureExpr { }
858867

859868
class ClosureParameterPseudoType = T::ClosureParameterPseudoType;
@@ -3001,7 +3010,7 @@ private module DeconstructionPatMatchingInput implements MatchingInputSig {
30013010
result = this.getParameter(pos.asPosition()).getType().getTypeAt(path)
30023011
or
30033012
pos.isReturn() and
3004-
result = Input3::getParameterizableType(this, path)
3013+
result = this.getType().getTypeAt(path)
30053014
}
30063015
}
30073016

0 commit comments

Comments
 (0)