mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
C#: Improve unification logic to handle ref structs.
This commit is contained in:
@@ -522,16 +522,21 @@ module Gvn {
|
||||
|
||||
/** Provides definitions related to type unification. */
|
||||
module Unification {
|
||||
/** A type parameter that is compatible with any type. */
|
||||
/** A type parameter that is compatible with any type except `ref struct`. */
|
||||
class UnconstrainedTypeParameter extends TypeParameter {
|
||||
UnconstrainedTypeParameter() { not exists(getATypeConstraint(this)) }
|
||||
UnconstrainedTypeParameter() {
|
||||
not exists(getATypeConstraint(this)) and not exists(getANegativeTypeConstraint(this))
|
||||
}
|
||||
}
|
||||
|
||||
/** A type parameter that is constrained. */
|
||||
class ConstrainedTypeParameter extends TypeParameter {
|
||||
int constraintCount;
|
||||
|
||||
ConstrainedTypeParameter() { constraintCount = strictcount(getATypeConstraint(this)) }
|
||||
ConstrainedTypeParameter() {
|
||||
constraintCount = count(getATypeConstraint(this)) + count(getANegativeTypeConstraint(this)) and
|
||||
constraintCount > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type parameter is unifiable with type `t`.
|
||||
@@ -559,7 +564,7 @@ module Unification {
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
override predicate unifiable(Type t) {
|
||||
exists(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) |
|
||||
forall(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) |
|
||||
ttc = TRefTypeConstraint() and
|
||||
t.isRefType()
|
||||
or
|
||||
@@ -567,13 +572,14 @@ module Unification {
|
||||
t.isValueType()
|
||||
or
|
||||
typeConstraintUnifiable(ttc, t)
|
||||
)
|
||||
) and
|
||||
(t.isRefLikeType() implies getANegativeTypeConstraint(this) = TAllowRefTypeConstraint())
|
||||
}
|
||||
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
override predicate subsumes(Type t) {
|
||||
exists(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) |
|
||||
forall(TTypeParameterConstraint ttc | ttc = getATypeConstraint(this) |
|
||||
ttc = TRefTypeConstraint() and
|
||||
t.isRefType()
|
||||
or
|
||||
@@ -581,7 +587,8 @@ module Unification {
|
||||
t.isValueType()
|
||||
or
|
||||
typeConstraintSubsumes(ttc, t)
|
||||
)
|
||||
) and
|
||||
(t.isRefLikeType() implies getANegativeTypeConstraint(this) = TAllowRefTypeConstraint())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,7 +610,8 @@ module Unification {
|
||||
t.isValueType()
|
||||
or
|
||||
typeConstraintUnifiable(ttc, t)
|
||||
)
|
||||
) and
|
||||
(t.isRefLikeType() implies getANegativeTypeConstraint(this) = TAllowRefTypeConstraint())
|
||||
}
|
||||
|
||||
bindingset[this]
|
||||
@@ -617,7 +625,8 @@ module Unification {
|
||||
t.isValueType()
|
||||
or
|
||||
typeConstraintSubsumes(ttc, t)
|
||||
)
|
||||
) and
|
||||
(t.isRefLikeType() implies getANegativeTypeConstraint(this) = TAllowRefTypeConstraint())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,6 +641,9 @@ module Unification {
|
||||
not t instanceof TypeParameter
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TTypeParameterNegativeConstraint = TAllowRefTypeConstraint()
|
||||
|
||||
cached
|
||||
TTypeParameterConstraint getATypeConstraint(TypeParameter tp) {
|
||||
exists(TypeParameterConstraints tpc | tpc = tp.getConstraints() |
|
||||
@@ -650,6 +662,14 @@ module Unification {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
TTypeParameterNegativeConstraint getANegativeTypeConstraint(TypeParameter tp) {
|
||||
exists(TypeParameterConstraints tpc | tpc = tp.getConstraints() |
|
||||
tpc.hasAllowRefLikeTypeConstraint() and
|
||||
result = TAllowRefTypeConstraint()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate typeConstraintUnifiable(TTypeConstraint ttc, Type t) {
|
||||
exists(Type t0 | ttc = TTypeConstraint(t0) | implicitConversionRestricted(t, t0))
|
||||
|
||||
Reference in New Issue
Block a user