mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
C#: Teach unification library about nested types
This commit is contained in:
@@ -10,9 +10,69 @@ private import Caching
|
||||
* equal modulo identity conversions and type parameters.
|
||||
*/
|
||||
module Gvn {
|
||||
/** Gets the qualified name of type `t`. */
|
||||
string getQualifiedName(Type t) {
|
||||
if not t instanceof NestedType or t.(NestedType).getDeclaringType() instanceof GenericType
|
||||
then result = t.getName()
|
||||
else result = getQualifiedName(t.(NestedType).getDeclaringType()) + "." + t.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
* A generic type. This is either a type with a type parameter, a type with
|
||||
* a type argument, or a nested type with a generic enclosing type.
|
||||
*/
|
||||
class GenericType extends Type {
|
||||
GenericType() {
|
||||
exists(this.getChild(0))
|
||||
or
|
||||
this.(NestedType).getDeclaringType() instanceof GenericType
|
||||
}
|
||||
|
||||
/** Gets the generic containing type, if any. */
|
||||
GenericType getQualifier() { result = this.(NestedType).getDeclaringType() }
|
||||
|
||||
/**
|
||||
* Gets the number of children of the generic containing type, or 0 if there
|
||||
* is no generic containing type.
|
||||
*/
|
||||
int getNumberOfQualifierChildrenExt() {
|
||||
result = this.getQualifier().getNumberOfChildrenExt()
|
||||
or
|
||||
not exists(this.getQualifier()) and result = 0
|
||||
}
|
||||
|
||||
/** Gets the number of children of this type, not taking nested types into account. */
|
||||
int getNumberOfChildrenSelf() { result = count(int i | exists(this.getChild(i)) and i >= 0) }
|
||||
|
||||
/** Gets the number of children of this type, taking nested types into account. */
|
||||
int getNumberOfChildrenExt() {
|
||||
result = this.getNumberOfQualifierChildrenExt() + this.getNumberOfChildrenSelf()
|
||||
}
|
||||
|
||||
/** Gets the `i`th child of this type, taking nested types into account. */
|
||||
Type getChildExt(int i) {
|
||||
result = this.getQualifier().getChildExt(i)
|
||||
or
|
||||
exists(int offset |
|
||||
offset = this.getNumberOfQualifierChildrenExt() and
|
||||
result = this.getChild(i - offset) and
|
||||
i >= offset
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this type, taking nested types into account. */
|
||||
string toStringExt() {
|
||||
exists(string name | name = getQualifiedName(this) |
|
||||
result = this.getQualifier().toStringExt() + "." + name
|
||||
or
|
||||
not exists(this.getQualifier()) and result = name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class LeafType extends Type {
|
||||
LeafType() {
|
||||
not exists(this.getAChild()) and
|
||||
not this instanceof GenericType and
|
||||
not this instanceof TypeParameter and
|
||||
not this instanceof DynamicType
|
||||
}
|
||||
@@ -28,14 +88,22 @@ module Gvn {
|
||||
or
|
||||
this = TArrayTypeKind(_, _) and result = 1
|
||||
or
|
||||
exists(UnboundGenericType ugt | this = TConstructedType(ugt) |
|
||||
result = ugt.getNumberOfTypeParameters()
|
||||
exists(GenericType t | this = TConstructedType(t.getSourceDeclaration()) |
|
||||
result = t.getNumberOfChildrenExt()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this kind when applied to arguments `args`. */
|
||||
/** Gets the source declaration type that this kind corresponds to, if any. */
|
||||
GenericType getConstructedSourceDeclaration() { this = TConstructedType(result) }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this kind when applied to arguments `args`.
|
||||
*
|
||||
* This predicate is restricted to built-in generics (pointers, nullables, and
|
||||
* arrays).
|
||||
*/
|
||||
bindingset[args]
|
||||
string toString(string args) {
|
||||
string toStringBuiltin(string args) {
|
||||
this = TPointerTypeKind() and result = args + "*"
|
||||
or
|
||||
this = TNullableTypeKind() and result = args + "?"
|
||||
@@ -43,14 +111,14 @@ module Gvn {
|
||||
exists(int rnk | this = TArrayTypeKind(_, rnk) |
|
||||
result = args + "[" + concat(int i | i in [0 .. rnk - 2] | ",") + "]"
|
||||
)
|
||||
or
|
||||
exists(UnboundGenericType ugt | this = TConstructedType(ugt) |
|
||||
result = ugt.getNameWithoutBrackets() + "<" + args + ">"
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this kind. */
|
||||
string toString() { result = toString("") }
|
||||
string toString() {
|
||||
result = this.toStringBuiltin("")
|
||||
or
|
||||
result = this.getConstructedSourceDeclaration().toStringExt()
|
||||
}
|
||||
|
||||
/** Gets the location of this kind. */
|
||||
Location getLocation() { result instanceof EmptyLocation }
|
||||
@@ -64,11 +132,9 @@ module Gvn {
|
||||
or
|
||||
t = any(ArrayType at | result = TArrayTypeKind(at.getDimension(), at.getRank()))
|
||||
or
|
||||
result = TConstructedType(t.(ConstructedType).getUnboundGeneric())
|
||||
result = TConstructedType(t.getSourceDeclaration())
|
||||
or
|
||||
result = TConstructedType(t.(TupleType).getUnderlyingType().getUnboundGeneric())
|
||||
or
|
||||
result = TConstructedType(t)
|
||||
result = TConstructedType(t.(TupleType).getUnderlyingType().getSourceDeclaration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +173,7 @@ module Gvn {
|
||||
override CompoundTypeKind getKind() { result = l.getKind() }
|
||||
}
|
||||
|
||||
private ConstructedGvnTypeList gvnConstructed(Type t, CompoundTypeKind k, int i) {
|
||||
private ConstructedGvnTypeList gvnConstructed(GenericType t, CompoundTypeKind k, int i) {
|
||||
result = TConstructedGvnTypeNil(k) and
|
||||
i = -1 and
|
||||
k = getTypeKind(t)
|
||||
@@ -118,14 +184,16 @@ module Gvn {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private GvnType gvnTypeChild(Type t, int i) { result = getGlobalValueNumber(t.getChild(i)) }
|
||||
private GvnType gvnTypeChildExt(GenericType t, int i) {
|
||||
result = getGlobalValueNumber(t.getChildExt(i))
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate gvnConstructedCons(
|
||||
Type t, CompoundTypeKind k, int i, GvnType head, ConstructedGvnTypeList tail
|
||||
GenericType t, CompoundTypeKind k, int i, GvnType head, ConstructedGvnTypeList tail
|
||||
) {
|
||||
tail = gvnConstructed(t, k, i - 1) and
|
||||
head = gvnTypeChild(t, i)
|
||||
head = gvnTypeChildExt(t, i)
|
||||
}
|
||||
|
||||
private class ConstructedGvnTypeList extends TConstructedGvnTypeList {
|
||||
@@ -150,17 +218,47 @@ module Gvn {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this constructed type, restricted
|
||||
* to the prefix `t` of the underlying source declaration type.
|
||||
*
|
||||
* The `toString()` calculation needs to be split up into prefixes, in
|
||||
* order to apply the type arguments correctly. For example, a source
|
||||
* declaration type `A<>.B.C<,>` applied to types `int, string, bool`
|
||||
* needs to be printed as `A<int>.B.C<string,bool>`.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
private string toStringConstructed(GenericType t) {
|
||||
t = this.getKind().getConstructedSourceDeclaration().getQualifier*() and
|
||||
exists(int offset, int children, string name, string nameArgs |
|
||||
offset = t.getNumberOfQualifierChildrenExt() and
|
||||
children = t.getNumberOfChildrenSelf() and
|
||||
name = getQualifiedName(t) and
|
||||
if children = 0
|
||||
then nameArgs = name
|
||||
else
|
||||
exists(string offsetArgs |
|
||||
offsetArgs =
|
||||
concat(int i |
|
||||
i in [offset .. offset + children - 1]
|
||||
|
|
||||
this.getArg(i).toString(), "," order by i
|
||||
) and
|
||||
nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">"
|
||||
)
|
||||
|
|
||||
offset = 0 and result = nameArgs
|
||||
or
|
||||
result = this.toStringConstructed(t.getQualifier()) + "." + nameArgs
|
||||
)
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
string toString() {
|
||||
exists(CompoundTypeKind k, string args |
|
||||
k = this.getKind() and
|
||||
args =
|
||||
concat(int i |
|
||||
i in [0 .. k.getNumberOfTypeParameters() - 1]
|
||||
|
|
||||
this.getArg(i).toString(), "," order by i
|
||||
) and
|
||||
result = k.toString(args)
|
||||
exists(CompoundTypeKind k | k = this.getKind() |
|
||||
result = k.toStringBuiltin(this.getArg(0).toString())
|
||||
or
|
||||
result = this.toStringConstructed(k.getConstructedSourceDeclaration())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,7 +464,12 @@ module Gvn {
|
||||
TArrayTypeKind(int dim, int rnk) {
|
||||
exists(ArrayType at | dim = at.getDimension() and rnk = at.getRank())
|
||||
} or
|
||||
TConstructedType(UnboundGenericType ugt) { exists(ugt.getATypeParameter()) }
|
||||
TConstructedType(GenericType sourceDecl) {
|
||||
sourceDecl = any(GenericType t).getSourceDeclaration() and
|
||||
not sourceDecl instanceof PointerType and
|
||||
not sourceDecl instanceof NullableType and
|
||||
not sourceDecl instanceof ArrayType
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TGvnType =
|
||||
|
||||
@@ -32,17 +32,17 @@ edges
|
||||
| Types.cs:74:9:74:9 | access to local variable d : D | Types.cs:16:30:16:30 | this : D |
|
||||
| Types.cs:77:22:77:22 | a : C | Types.cs:79:18:79:25 | SSA def(b) : C |
|
||||
| Types.cs:79:18:79:25 | SSA def(b) : C | Types.cs:80:18:80:18 | access to local variable b |
|
||||
| Types.cs:90:22:90:22 | e : E2 | Types.cs:92:26:92:26 | access to parameter e : E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [Field] : E2 | Types.cs:93:13:93:16 | this access [Field] : E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : E2 | Types.cs:92:13:92:16 | [post] this access [Field] : E2 |
|
||||
| Types.cs:93:13:93:16 | this access [Field] : E2 | Types.cs:113:34:113:34 | this [Field] : E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:90:22:90:22 | e : E2 |
|
||||
| Types.cs:113:34:113:34 | this [Field] : E2 | Types.cs:115:22:115:25 | this access [Field] : E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : E2 | Types.cs:115:22:115:31 | access to field Field |
|
||||
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 | Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 | Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:90:22:90:22 | e : Types.E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 | Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:30:122:30 | access to local variable a : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:30:123:31 | access to local variable e2 : E2 |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:122:22:122:31 | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | Types.cs:123:22:123:32 | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through |
|
||||
nodes
|
||||
| Types.cs:7:21:7:25 | this : D | semmle.label | this : D |
|
||||
| Types.cs:7:32:7:35 | this access : D | semmle.label | this access : D |
|
||||
@@ -86,20 +86,20 @@ nodes
|
||||
| Types.cs:77:22:77:22 | a : C | semmle.label | a : C |
|
||||
| Types.cs:79:18:79:25 | SSA def(b) : C | semmle.label | SSA def(b) : C |
|
||||
| Types.cs:80:18:80:18 | access to local variable b | semmle.label | access to local variable b |
|
||||
| Types.cs:90:22:90:22 | e : E2 | semmle.label | e : E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [Field] : E2 | semmle.label | [post] this access [Field] : E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : E2 | semmle.label | access to parameter e : E2 |
|
||||
| Types.cs:93:13:93:16 | this access [Field] : E2 | semmle.label | this access [Field] : E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | semmle.label | object creation of type E2 : E2 |
|
||||
| Types.cs:113:34:113:34 | this [Field] : E2 | semmle.label | this [Field] : E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : E2 | semmle.label | this access [Field] : E2 |
|
||||
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | semmle.label | e : Types.E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 | semmle.label | [post] this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | semmle.label | access to parameter e : Types.E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 | semmle.label | this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 | semmle.label | this [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 | semmle.label | this access [Field] : Types.E<D>.E2 |
|
||||
| Types.cs:115:22:115:31 | access to field Field | semmle.label | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | semmle.label | object creation of type A : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | semmle.label | object creation of type E2 : E2 |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
|
||||
| Types.cs:122:22:122:31 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | semmle.label | access to local variable a : A |
|
||||
| Types.cs:123:22:123:32 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | semmle.label | access to local variable e2 : E2 |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | semmle.label | access to local variable e2 : Types.E<D>.E2 |
|
||||
#select
|
||||
| Types.cs:23:12:23:18 | object creation of type C : C | Types.cs:50:18:50:18 | access to local variable c | Types.cs:50:18:50:18 | access to local variable c | $@ | Types.cs:50:18:50:18 | access to local variable c | access to local variable c |
|
||||
| Types.cs:25:12:25:18 | object creation of type C : C | Types.cs:63:33:63:36 | (...) ... | Types.cs:63:33:63:36 | (...) ... | $@ | Types.cs:63:33:63:36 | (...) ... | (...) ... |
|
||||
@@ -115,6 +115,6 @@ nodes
|
||||
| Types.cs:39:12:39:18 | object creation of type D : D | Types.cs:69:52:69:52 | access to parameter x | Types.cs:69:52:69:52 | access to parameter x | $@ | Types.cs:69:52:69:52 | access to parameter x | access to parameter x |
|
||||
| Types.cs:40:12:40:18 | object creation of type D : D | Types.cs:16:42:16:45 | this access | Types.cs:16:42:16:45 | this access | $@ | Types.cs:16:42:16:45 | this access | this access |
|
||||
| Types.cs:43:20:43:23 | null : null | Types.cs:44:14:44:14 | access to local variable o | Types.cs:44:14:44:14 | access to local variable o | $@ | Types.cs:44:14:44:14 | access to local variable o | access to local variable o |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:115:22:115:31 | access to field Field | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:22:122:31 | call to method Through | Types.cs:122:22:122:31 | call to method Through | $@ | Types.cs:122:22:122:31 | call to method Through | call to method Through |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:22:123:32 | call to method Through | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
|
||||
|
||||
@@ -296,13 +296,26 @@ subsumes
|
||||
| Unification.cs:36:7:36:17 | Nested<T10> | Unification.cs:36:7:36:17 | Nested<String> |
|
||||
| Unification.cs:36:7:36:17 | Nested<T10> | Unification.cs:36:7:36:17 | Nested<T10> |
|
||||
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
|
||||
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
|
||||
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
|
||||
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
|
||||
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
|
||||
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
|
||||
| Unification.cs:39:11:39:17 | Nested<Int32>.NestedB | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
|
||||
| Unification.cs:39:11:39:17 | Nested<String>.NestedB | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
|
||||
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
|
||||
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
|
||||
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
|
||||
@@ -349,7 +362,17 @@ unifiable
|
||||
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:33:12:33:23 | (T8, T9) |
|
||||
| Unification.cs:36:7:36:17 | Nested<Int32> | Unification.cs:36:7:36:17 | Nested<T10> |
|
||||
| Unification.cs:36:7:36:17 | Nested<String> | Unification.cs:36:7:36:17 | Nested<T10> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
|
||||
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
|
||||
| Unification.cs:39:11:39:17 | Nested<Int32>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
|
||||
| Unification.cs:39:11:39:17 | Nested<String>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
|
||||
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
|
||||
|
||||
Reference in New Issue
Block a user