mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Rust: Address PR feedback
This commit is contained in:
@@ -335,7 +335,16 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
|
||||
override Location getLocation() { result = trait.getLocation() }
|
||||
}
|
||||
|
||||
/** A type abstraction. */
|
||||
/**
|
||||
* A type abstraction. I.e., a place in the program where type variables are
|
||||
* introduced.
|
||||
*
|
||||
* Example:
|
||||
* ```rust
|
||||
* impl<A, B> Foo<A, B> { }
|
||||
* // ^^^^^^ a type abstraction
|
||||
* ```
|
||||
*/
|
||||
abstract class TypeAbstraction extends AstNode {
|
||||
abstract TypeParameter getATypeParameter();
|
||||
}
|
||||
|
||||
@@ -19,16 +19,6 @@ private module Input1 implements InputSig1<Location> {
|
||||
|
||||
class TypeParameter = T::TypeParameter;
|
||||
|
||||
/**
|
||||
* A type abstraction. I.e., a place in the program where type variables are
|
||||
* introduced.
|
||||
*
|
||||
* Example:
|
||||
* ```rust
|
||||
* impl<A, B> Foo<A, B> { }
|
||||
* // ^^^^^^ a type abstraction
|
||||
* ```
|
||||
*/
|
||||
class TypeAbstraction = T::TypeAbstraction;
|
||||
|
||||
private newtype TTypeArgumentPosition =
|
||||
@@ -156,7 +146,7 @@ private module Input2 implements InputSig2 {
|
||||
exists(TypeParam param |
|
||||
abs = param.getTypeBoundList().getABound() and
|
||||
condition = param and
|
||||
constraint = param.getTypeBoundList().getABound().getTypeRepr()
|
||||
constraint = abs.(TypeBound).getTypeRepr()
|
||||
)
|
||||
or
|
||||
// the implicit `Self` type parameter satisfies the trait
|
||||
@@ -968,22 +958,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type receiverRootType(Expr e) {
|
||||
any(MethodCallExpr mce).getReceiver() = e and
|
||||
result = inferType(e)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferReceiverType(Expr e, TypePath path) {
|
||||
exists(Type root | root = receiverRootType(e) |
|
||||
// for reference types, lookup members in the type being referenced
|
||||
if root = TRefType()
|
||||
then result = inferType(e, TypePath::cons(TRefTypeParameter(), path))
|
||||
else result = inferType(e, path)
|
||||
)
|
||||
}
|
||||
|
||||
private class ReceiverExpr extends Expr {
|
||||
MethodCallExpr mce;
|
||||
|
||||
@@ -993,13 +967,22 @@ private module Cached {
|
||||
|
||||
int getNumberOfArgs() { result = mce.getArgList().getNumberOfArgs() }
|
||||
|
||||
Type resolveTypeAt(TypePath path) { result = inferReceiverType(this, path) }
|
||||
pragma[nomagic]
|
||||
Type getTypeAt(TypePath path) {
|
||||
exists(TypePath path0 | result = inferType(this, path0) |
|
||||
path0 = TypePath::cons(TRefTypeParameter(), path)
|
||||
or
|
||||
not path0.isCons(TRefTypeParameter(), _) and
|
||||
not (path0.isEmpty() and result = TRefType()) and
|
||||
path = path0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if a method for `type` with the name `name` and the arity `arity` exists in `impl`. */
|
||||
pragma[nomagic]
|
||||
private predicate methodCandidate(Type type, string name, int arity, Impl impl) {
|
||||
type = impl.(ImplTypeAbstraction).getSelfTy().(TypeReprMention).resolveType() and
|
||||
type = impl.getSelfTy().(TypeReprMention).resolveType() and
|
||||
exists(Function f |
|
||||
f = impl.(ImplItemNode).getASuccessor(name) and
|
||||
f.getParamList().hasSelfParam() and
|
||||
@@ -1009,17 +992,16 @@ private module Cached {
|
||||
|
||||
private module IsInstantiationOfInput implements IsInstantiationOfInputSig<ReceiverExpr> {
|
||||
pragma[nomagic]
|
||||
predicate potentialInstantiationOf(ReceiverExpr receiver, TypeAbstraction impl, TypeMention sub) {
|
||||
methodCandidate(receiver.resolveTypeAt(TypePath::nil()), receiver.getField(),
|
||||
predicate potentialInstantiationOf(
|
||||
ReceiverExpr receiver, TypeAbstraction impl, TypeMention constraint
|
||||
) {
|
||||
methodCandidate(receiver.getTypeAt(TypePath::nil()), receiver.getField(),
|
||||
receiver.getNumberOfArgs(), impl) and
|
||||
sub = impl.(ImplTypeAbstraction).getSelfTy()
|
||||
constraint = impl.(ImplTypeAbstraction).getSelfTy()
|
||||
}
|
||||
|
||||
predicate relevantTypeMention(TypeMention sub) {
|
||||
exists(TypeAbstraction impl |
|
||||
methodCandidate(_, _, _, impl) and
|
||||
sub = impl.(ImplTypeAbstraction).getSelfTy()
|
||||
)
|
||||
predicate relevantTypeMention(TypeMention constraint) {
|
||||
exists(Impl impl | methodCandidate(_, _, _, impl) and constraint = impl.getSelfTy())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,8 +1026,7 @@ private module Cached {
|
||||
*/
|
||||
private Function getMethodFromImpl(ReceiverExpr receiver) {
|
||||
exists(Impl impl |
|
||||
IsInstantiationOf<ReceiverExpr, IsInstantiationOfInput>::isInstantiationOf(receiver, impl,
|
||||
impl.(ImplTypeAbstraction).getSelfTy().(TypeReprMention)) and
|
||||
IsInstantiationOf<ReceiverExpr, IsInstantiationOfInput>::isInstantiationOf(receiver, impl, _) and
|
||||
result = getMethodSuccessor(impl, receiver.getField())
|
||||
)
|
||||
}
|
||||
@@ -1059,19 +1040,17 @@ private module Cached {
|
||||
or
|
||||
// The type of `receiver` is a type parameter and the method comes from a
|
||||
// trait bound on the type parameter.
|
||||
result = getTypeParameterMethod(receiver.resolveTypeAt(TypePath::nil()), receiver.getField())
|
||||
result = getTypeParameterMethod(receiver.getTypeAt(TypePath::nil()), receiver.getField())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private Type inferRootTypeDeref(AstNode n) {
|
||||
exists(Type t |
|
||||
t = inferType(n) and
|
||||
// for reference types, lookup members in the type being referenced
|
||||
if t = TRefType()
|
||||
then result = inferType(n, TypePath::singleton(TRefTypeParameter()))
|
||||
else result = t
|
||||
)
|
||||
result = inferType(n) and
|
||||
result != TRefType()
|
||||
or
|
||||
// for reference types, lookup members in the type being referenced
|
||||
result = inferType(n, TypePath::singleton(TRefTypeParameter()))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
testFailures
|
||||
| main.rs:793:25:793:75 | //... | Missing result: type=a:A.S1 |
|
||||
| main.rs:793:25:793:75 | //... | Missing result: type=a:MyThing |
|
||||
inferType
|
||||
| loop/main.rs:7:12:7:15 | SelfParam | | loop/main.rs:6:1:8:1 | Self [trait T1] |
|
||||
| loop/main.rs:11:12:11:15 | SelfParam | | loop/main.rs:10:1:14:1 | Self [trait T2] |
|
||||
@@ -798,10 +796,13 @@ inferType
|
||||
| main.rs:788:9:788:9 | x | | main.rs:787:26:787:41 | T2 |
|
||||
| main.rs:788:9:788:14 | x.m1() | | main.rs:787:22:787:23 | T1 |
|
||||
| main.rs:791:56:791:56 | x | | main.rs:791:39:791:53 | T |
|
||||
| main.rs:793:13:793:13 | a | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:793:13:793:13 | a | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:793:13:793:13 | a | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:793:17:793:17 | x | | main.rs:791:39:791:53 | T |
|
||||
| main.rs:793:17:793:22 | x.m1() | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:794:26:794:26 | a | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:793:17:793:22 | x.m1() | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:793:17:793:22 | x.m1() | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:794:26:794:26 | a | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:794:26:794:26 | a | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:798:13:798:13 | x | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:798:13:798:13 | x | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:798:17:798:33 | MyThing {...} | | main.rs:721:5:724:5 | MyThing |
|
||||
@@ -856,9 +857,7 @@ inferType
|
||||
| main.rs:816:17:816:33 | MyThing {...} | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:816:30:816:31 | S1 | | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:817:13:817:13 | s | | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:817:13:817:13 | s | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:817:17:817:32 | call_trait_m1(...) | | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:817:17:817:32 | call_trait_m1(...) | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:817:31:817:31 | x | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:817:31:817:31 | x | A | main.rs:731:5:732:14 | S1 |
|
||||
| main.rs:819:13:819:13 | x | | main.rs:726:5:729:5 | MyThing2 |
|
||||
@@ -867,10 +866,8 @@ inferType
|
||||
| main.rs:819:17:819:34 | MyThing2 {...} | A | main.rs:733:5:734:14 | S2 |
|
||||
| main.rs:819:31:819:32 | S2 | | main.rs:733:5:734:14 | S2 |
|
||||
| main.rs:820:13:820:13 | s | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:820:13:820:13 | s | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:820:13:820:13 | s | A | main.rs:733:5:734:14 | S2 |
|
||||
| main.rs:820:17:820:32 | call_trait_m1(...) | | main.rs:721:5:724:5 | MyThing |
|
||||
| main.rs:820:17:820:32 | call_trait_m1(...) | | main.rs:741:20:741:22 | Tr2 |
|
||||
| main.rs:820:17:820:32 | call_trait_m1(...) | A | main.rs:733:5:734:14 | S2 |
|
||||
| main.rs:820:31:820:31 | x | | main.rs:726:5:729:5 | MyThing2 |
|
||||
| main.rs:820:31:820:31 | x | A | main.rs:733:5:734:14 | S2 |
|
||||
|
||||
@@ -237,14 +237,20 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
TypePath cons(TypeParameter tp, TypePath suffix) { result = singleton(tp).append(suffix) }
|
||||
}
|
||||
|
||||
/** A class that represents a type tree. */
|
||||
private signature class TypeTreeSig {
|
||||
Type resolveTypeAt(TypePath path);
|
||||
/**
|
||||
* A class that has a type tree associated with it.
|
||||
*
|
||||
* The type tree is represented by the `getTypeAt` predicate, which for every
|
||||
* path into the tree gives the type at that path.
|
||||
*/
|
||||
signature class HasTypeTreeSig {
|
||||
/** Gets the type at `path` in the type tree. */
|
||||
Type getTypeAt(TypePath path);
|
||||
|
||||
/** Gets a textual representation of this type abstraction. */
|
||||
/** Gets a textual representation of this type. */
|
||||
string toString();
|
||||
|
||||
/** Gets the location of this type abstraction. */
|
||||
/** Gets the location of this type. */
|
||||
Location getLocation();
|
||||
}
|
||||
|
||||
@@ -309,8 +315,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* Holds if
|
||||
* - `abs` is a type abstraction that introduces type variables that are
|
||||
* free in `condition` and `constraint`,
|
||||
* - and for every instantiation of the type parameters the resulting
|
||||
* `condition` satisifies the constraint given by `constraint`.
|
||||
* - and for every instantiation of the type parameters from `abs` the
|
||||
* resulting `condition` satisifies the constraint given by `constraint`.
|
||||
*
|
||||
* Example in C#:
|
||||
* ```csharp
|
||||
@@ -322,12 +328,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
*
|
||||
* Example in Rust:
|
||||
* ```rust
|
||||
* impl<A> Trait<i64, B> for Type<String, A> { }
|
||||
* impl<A> Trait<i64, A> for Type<String, A> { }
|
||||
* // ^^^ `abs` ^^^^^^^^^^^^^^^ `condition`
|
||||
* // ^^^^^^^^^^^^^ `constraint`
|
||||
* ```
|
||||
*
|
||||
* To see how `abs` change the meaning of the type parameters that occur in
|
||||
* To see how `abs` changes the meaning of the type parameters that occur in
|
||||
* `condition`, consider the following examples in Rust:
|
||||
* ```rust
|
||||
* impl<T> Trait for T { }
|
||||
@@ -362,10 +368,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
result = tm.resolveTypeAt(TypePath::nil())
|
||||
}
|
||||
|
||||
signature module IsInstantiationOfInputSig<TypeTreeSig App> {
|
||||
/** Provides the input to `IsInstantiationOf`. */
|
||||
signature module IsInstantiationOfInputSig<HasTypeTreeSig App> {
|
||||
/**
|
||||
* Holds if `abs` is a type abstraction, `tm` occurs under `abs`, and
|
||||
* `app` is potentially an application/instantiation of `abs`.
|
||||
* Holds if `abs` is a type abstraction, `tm` occurs in the scope of
|
||||
* `abs`, and `app` is potentially an application/instantiation of `abs`.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
@@ -378,8 +385,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* foo.bar();
|
||||
* // ^^^ `app`
|
||||
* ```
|
||||
* Here `abs` introduces the type parameter `A` and `tm` occurs under
|
||||
* `abs` (i.e., `A` is bound in `tm` by `abs`). On the last line,
|
||||
* Here `abs` introduces the type parameter `A` and `tm` occurs in the
|
||||
* scope of `abs` (i.e., `A` is bound in `tm` by `abs`). On the last line,
|
||||
* accessing the `bar` method of `foo` potentially instantiates the `impl`
|
||||
* block with a type argument for `A`.
|
||||
*/
|
||||
@@ -397,7 +404,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* Provides functionality for determining if a type is a possible
|
||||
* instantiation of a type mention containing type parameters.
|
||||
*/
|
||||
module IsInstantiationOf<TypeTreeSig App, IsInstantiationOfInputSig<App> Input> {
|
||||
module IsInstantiationOf<HasTypeTreeSig App, IsInstantiationOfInputSig<App> Input> {
|
||||
private import Input
|
||||
|
||||
/** Gets the `i`th path in `tm` per some arbitrary order. */
|
||||
@@ -422,7 +429,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
) {
|
||||
exists(Type t |
|
||||
tm.resolveTypeAt(path) = t and
|
||||
if t = abs.getATypeParameter() then any() else app.resolveTypeAt(path) = t
|
||||
if t = abs.getATypeParameter() then any() else app.getTypeAt(path) = t
|
||||
)
|
||||
}
|
||||
|
||||
@@ -436,6 +443,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
if i = 0 then any() else satisfiesConcreteTypesFromIndex(app, abs, tm, i - 1)
|
||||
}
|
||||
|
||||
/** Holds if all the concrete types in `tm` also occur in `app`. */
|
||||
pragma[nomagic]
|
||||
private predicate satisfiesConcreteTypes(App app, TypeAbstraction abs, TypeMention tm) {
|
||||
satisfiesConcreteTypesFromIndex(app, abs, tm, max(int i | exists(getNthPath(tm, i))))
|
||||
@@ -463,18 +471,22 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
private predicate typeParametersEqualFromIndex(
|
||||
App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp, Type t, int i
|
||||
) {
|
||||
potentialInstantiationOf(app, abs, tm) and
|
||||
satisfiesConcreteTypes(app, abs, tm) and
|
||||
exists(TypePath path |
|
||||
path = getNthTypeParameterPath(tm, tp, i) and
|
||||
t = app.resolveTypeAt(path) and
|
||||
if i = 0 then any() else typeParametersEqualFromIndex(app, abs, tm, tp, t, i - 1)
|
||||
t = app.getTypeAt(path) and
|
||||
if i = 0
|
||||
then
|
||||
// no need to compute this predicate if there is only one path
|
||||
exists(getNthTypeParameterPath(tm, tp, 1))
|
||||
else typeParametersEqualFromIndex(app, abs, tm, tp, t, i - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate typeParametersEqual(
|
||||
App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp
|
||||
) {
|
||||
potentialInstantiationOf(app, abs, tm) and
|
||||
satisfiesConcreteTypes(app, abs, tm) and
|
||||
tp = getNthTypeParameter(abs, _) and
|
||||
(
|
||||
not exists(getNthTypeParameterPath(tm, tp, _))
|
||||
@@ -487,7 +499,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if all the concrete types in `tm` also occur in `app`. */
|
||||
private predicate typeParametersHaveEqualInstantiationFromIndex(
|
||||
App app, TypeAbstraction abs, TypeMention tm, int i
|
||||
) {
|
||||
@@ -499,12 +510,20 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
)
|
||||
}
|
||||
|
||||
/** All the places where the same type parameter occurs in `tm` are equal in `app. */
|
||||
pragma[inline]
|
||||
/**
|
||||
* Holds if all the places where the same type parameter occurs in `tm`
|
||||
* are equal in `app`.
|
||||
*
|
||||
* TODO: As of now this only checks equality at the root of the types
|
||||
* instantiated for type parameters. So, for instance, `Pair<Vec<i64>, Vec<bool>>`
|
||||
* is mistakenly considered an instantiation of `Pair<A, A>`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate typeParametersHaveEqualInstantiation(
|
||||
App app, TypeAbstraction abs, TypeMention tm
|
||||
) {
|
||||
potentialInstantiationOf(app, abs, tm) and
|
||||
// We only need to check equality if the concrete types are satisfied.
|
||||
satisfiesConcreteTypes(app, abs, tm) and
|
||||
(
|
||||
not exists(getNthTypeParameter(abs, _))
|
||||
or
|
||||
@@ -527,7 +546,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* - `Pair<int, string>` is _not_ an instantiation of `Pair<string, string>`
|
||||
*/
|
||||
predicate isInstantiationOf(App app, TypeAbstraction abs, TypeMention tm) {
|
||||
satisfiesConcreteTypes(app, abs, tm) and
|
||||
// `typeParametersHaveEqualInstantiation` suffices as it implies `satisfiesConcreteTypes`.
|
||||
typeParametersHaveEqualInstantiation(app, abs, tm)
|
||||
}
|
||||
}
|
||||
@@ -536,14 +555,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
private module BaseTypes {
|
||||
/**
|
||||
* Holds if, when `tm1` is considered an instantiation of `tm2`, then at
|
||||
* the type parameter `tp` is has the type `t` at `path`.
|
||||
* the type parameter `tp` it has the type `t` at `path`.
|
||||
*
|
||||
* For instance, if the type `Map<int, List<int>>` is considered an
|
||||
* instantion of `Map<K, V>` then it has the type `int` at `K` and the
|
||||
* type `List<int>` at `V`.
|
||||
*/
|
||||
bindingset[tm1, tm2]
|
||||
predicate instantiatesWith(
|
||||
private predicate instantiatesWith(
|
||||
TypeMention tm1, TypeMention tm2, TypeParameter tp, TypePath path, Type t
|
||||
) {
|
||||
exists(TypePath prefix |
|
||||
@@ -551,19 +570,27 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
)
|
||||
}
|
||||
|
||||
module IsInstantiationOfInput implements IsInstantiationOfInputSig<TypeMention> {
|
||||
final private class FinalTypeMention = TypeMention;
|
||||
|
||||
final private class TypeMentionTypeTree extends FinalTypeMention {
|
||||
Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) }
|
||||
}
|
||||
|
||||
private module IsInstantiationOfInput implements
|
||||
IsInstantiationOfInputSig<TypeMentionTypeTree>
|
||||
{
|
||||
pragma[nomagic]
|
||||
private predicate typeCondition(Type type, TypeAbstraction abs, TypeMention lhs) {
|
||||
private predicate typeCondition(Type type, TypeAbstraction abs, TypeMentionTypeTree lhs) {
|
||||
conditionSatisfiesConstraint(abs, lhs, _) and type = resolveTypeMentionRoot(lhs)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate typeConstraint(Type type, TypeMention rhs) {
|
||||
private predicate typeConstraint(Type type, TypeMentionTypeTree rhs) {
|
||||
conditionSatisfiesConstraint(_, _, rhs) and type = resolveTypeMentionRoot(rhs)
|
||||
}
|
||||
|
||||
predicate potentialInstantiationOf(
|
||||
TypeMention condition, TypeAbstraction abs, TypeMention constraint
|
||||
TypeMentionTypeTree condition, TypeAbstraction abs, TypeMention constraint
|
||||
) {
|
||||
exists(Type type |
|
||||
typeConstraint(type, condition) and typeCondition(type, abs, constraint)
|
||||
@@ -571,7 +598,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
}
|
||||
}
|
||||
|
||||
// The type mention `condition` satisfies `constraint` with the type `t` at the path `path`.
|
||||
/**
|
||||
* The type mention `condition` satisfies `constraint` with the type `t`
|
||||
* at the path `path`.
|
||||
*/
|
||||
predicate conditionSatisfiesConstraintTypeAt(
|
||||
TypeAbstraction abs, TypeMention condition, TypeMention constraint, TypePath path, Type t
|
||||
) {
|
||||
@@ -584,18 +614,17 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
conditionSatisfiesConstraint(abs, condition, midSup) and
|
||||
// NOTE: `midAbs` describe the free type variables in `midSub`, hence
|
||||
// we use that for instantiation check.
|
||||
IsInstantiationOf<TypeMention, IsInstantiationOfInput>::isInstantiationOf(midSup, midAbs,
|
||||
midSub) and
|
||||
(
|
||||
conditionSatisfiesConstraintTypeAt(midAbs, midSub, constraint, path, t) and
|
||||
not t = abs.getATypeParameter()
|
||||
or
|
||||
exists(TypePath prefix, TypePath suffix, TypeParameter tp |
|
||||
tp = abs.getATypeParameter() and
|
||||
conditionSatisfiesConstraintTypeAt(midAbs, midSub, constraint, prefix, tp) and
|
||||
instantiatesWith(midSup, midSub, tp, suffix, t) and
|
||||
path = prefix.append(suffix)
|
||||
)
|
||||
IsInstantiationOf<TypeMentionTypeTree, IsInstantiationOfInput>::isInstantiationOf(midSup,
|
||||
midAbs, midSub)
|
||||
|
|
||||
conditionSatisfiesConstraintTypeAt(midAbs, midSub, constraint, path, t) and
|
||||
not t = midAbs.getATypeParameter()
|
||||
or
|
||||
exists(TypePath prefix, TypePath suffix, TypeParameter tp |
|
||||
tp = midAbs.getATypeParameter() and
|
||||
conditionSatisfiesConstraintTypeAt(midAbs, midSub, constraint, prefix, tp) and
|
||||
instantiatesWith(midSup, midSub, tp, suffix, t) and
|
||||
path = prefix.append(suffix)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -954,35 +983,37 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
}
|
||||
|
||||
private module AccessConstraint {
|
||||
private newtype TTRelevantAccess =
|
||||
TRelevantAccess(Access a, AccessPosition apos, TypePath path, Type constraint) {
|
||||
exists(DeclarationPosition dpos |
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
typeParameterConstraintHasTypeParameter(a.getTarget(), dpos, path, _, constraint, _, _)
|
||||
)
|
||||
predicate relevantAccessConstraint(
|
||||
Access a, AccessPosition apos, TypePath path, Type constraint
|
||||
) {
|
||||
exists(DeclarationPosition dpos |
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
typeParameterConstraintHasTypeParameter(a.getTarget(), dpos, path, _, constraint, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TRelevantAccess =
|
||||
MkRelevantAccess(Access a, AccessPosition apos, TypePath path) {
|
||||
relevantAccessConstraint(a, apos, path, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* If the access `a` for `apos` and `path` has the inferred root type
|
||||
* `type` and type inference requires it to satisfy the constraint
|
||||
* `constraint`.
|
||||
* If the access `a` for `apos` and `path` has an inferred type which
|
||||
* type inference requires to satisfy some constraint.
|
||||
*/
|
||||
private class RelevantAccess extends TTRelevantAccess {
|
||||
private class RelevantAccess extends MkRelevantAccess {
|
||||
Access a;
|
||||
AccessPosition apos;
|
||||
TypePath path;
|
||||
Type constraint0;
|
||||
|
||||
RelevantAccess() { this = TRelevantAccess(a, apos, path, constraint0) }
|
||||
RelevantAccess() { this = MkRelevantAccess(a, apos, path) }
|
||||
|
||||
Type resolveTypeAt(TypePath suffix) {
|
||||
a.getInferredType(apos, path.append(suffix)) = result
|
||||
}
|
||||
Type getTypeAt(TypePath suffix) { a.getInferredType(apos, path.append(suffix)) = result }
|
||||
|
||||
/** Holds if this relevant access has the type `type` and should satisfy `constraint`. */
|
||||
predicate hasTypeConstraint(Type type, Type constraint) {
|
||||
type = a.getInferredType(apos, path) and
|
||||
constraint = constraint0
|
||||
relevantAccessConstraint(a, apos, path, constraint)
|
||||
}
|
||||
|
||||
string toString() {
|
||||
@@ -1013,9 +1044,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* Holds if `at` satisfies `constraint` through `abs`, `sub`, and `constraintMention`.
|
||||
*/
|
||||
private predicate hasConstraintMention(
|
||||
RelevantAccess at, TypeAbstraction abs, TypeMention sub, TypeMention constraintMention
|
||||
RelevantAccess at, TypeAbstraction abs, TypeMention sub, Type constraint,
|
||||
TypeMention constraintMention
|
||||
) {
|
||||
exists(Type type, Type constraint | at.hasTypeConstraint(type, constraint) |
|
||||
exists(Type type | at.hasTypeConstraint(type, constraint) |
|
||||
not exists(countConstraintImplementations(type, constraint)) and
|
||||
conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, _, _) and
|
||||
resolveTypeMentionRoot(sub) = abs.getATypeParameter() and
|
||||
@@ -1046,18 +1078,17 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
RelevantAccess at, TypeAbstraction abs, TypeMention sub, Type t0, TypePath prefix0,
|
||||
TypeMention constraintMention
|
||||
|
|
||||
at = TRelevantAccess(a, apos, prefix, constraint) and
|
||||
hasConstraintMention(at, abs, sub, constraintMention) and
|
||||
conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, prefix0, t0) and
|
||||
(
|
||||
not t0 = abs.getATypeParameter() and t = t0 and path = prefix0
|
||||
or
|
||||
t0 = abs.getATypeParameter() and
|
||||
exists(TypePath path3, TypePath suffix |
|
||||
sub.resolveTypeAt(path3) = t0 and
|
||||
at.resolveTypeAt(path3.append(suffix)) = t and
|
||||
path = prefix0.append(suffix)
|
||||
)
|
||||
at = MkRelevantAccess(a, apos, prefix) and
|
||||
hasConstraintMention(at, abs, sub, constraint, constraintMention) and
|
||||
conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, prefix0, t0)
|
||||
|
|
||||
not t0 = abs.getATypeParameter() and t = t0 and path = prefix0
|
||||
or
|
||||
t0 = abs.getATypeParameter() and
|
||||
exists(TypePath path3, TypePath suffix |
|
||||
sub.resolveTypeAt(path3) = t0 and
|
||||
at.getTypeAt(path3.append(suffix)) = t and
|
||||
path = prefix0.append(suffix)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user