@@ -28,6 +28,7 @@ private module Cached {
2828 *
2929 * - Identity conversions
3030 * - Implicit numeric conversions
31+ * - Implicit span conversions
3132 * - Implicit nullable conversions
3233 * - Implicit reference conversions
3334 * - Boxing conversions
@@ -38,6 +39,8 @@ private module Cached {
3839 or
3940 convNumeric ( fromType , toType )
4041 or
42+ convSpan ( fromType , toType )
43+ or
4144 convNullableType ( fromType , toType )
4245 or
4346 convRefTypeNonNull ( fromType , toType )
@@ -81,6 +84,7 @@ private predicate implicitConversionNonNull(Type fromType, Type toType) {
8184 *
8285 * - Identity conversions
8386 * - Implicit numeric conversions
87+ * - Implicit span conversions
8488 * - Implicit nullable conversions
8589 * - Implicit reference conversions
8690 * - Boxing conversions
@@ -491,6 +495,53 @@ private predicate convNumericChar(SimpleType toType) {
491495
492496private predicate convNumericFloat ( SimpleType toType ) { toType instanceof DoubleType }
493497
498+ private class SpanType extends GenericType {
499+ SpanType ( ) { this .getUnboundGeneric ( ) instanceof SystemSpanStruct }
500+
501+ Type getElementType ( ) { result = this .getTypeArgument ( 0 ) }
502+ }
503+
504+ private class ReadOnlySpanType extends GenericType {
505+ ReadOnlySpanType ( ) { this .getUnboundGeneric ( ) instanceof SystemReadOnlySpanStruct }
506+
507+ Type getElementType ( ) { result = this .getTypeArgument ( 0 ) }
508+ }
509+
510+ private class SimpleArrayType extends ArrayType {
511+ SimpleArrayType ( ) {
512+ this .getRank ( ) = 1 and
513+ this .getDimension ( ) = 1
514+ }
515+ }
516+
517+ /**
518+ * INTERNAL: Do not use.
519+ *
520+ * Holds if there is an implicit span conversion from `fromType` to `toType`.
521+ *
522+ * 10.2.1: Implicit span conversions (added in C# 14).
523+ * [Documentation](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-14.0/first-class-span-types#span-conversions)
524+ */
525+ predicate convSpan ( Type fromType , Type toType ) {
526+ fromType .( SimpleArrayType ) .getElementType ( ) = toType .( SpanType ) .getElementType ( )
527+ or
528+ exists ( Type fromElementType , Type toElementType |
529+ (
530+ fromElementType = fromType .( SimpleArrayType ) .getElementType ( ) or
531+ fromElementType = fromType .( SpanType ) .getElementType ( ) or
532+ fromElementType = fromType .( ReadOnlySpanType ) .getElementType ( )
533+ ) and
534+ toElementType = toType .( ReadOnlySpanType ) .getElementType ( )
535+ |
536+ convIdentity ( fromElementType , toElementType )
537+ or
538+ convCovariance ( fromElementType , toElementType )
539+ )
540+ or
541+ fromType instanceof SystemStringClass and
542+ toType .( ReadOnlySpanType ) .getElementType ( ) instanceof CharType
543+ }
544+
494545/**
495546 * INTERNAL: Do not use.
496547 *
@@ -784,8 +835,7 @@ predicate convConversionOperator(Type fromType, Type toType) {
784835 )
785836}
786837
787- /** 13.1.3.2: Variance conversion. */
788- private predicate convVariance ( GenericType fromType , GenericType toType ) {
838+ private predicate convVarianceAux ( UnboundGenericType ugt , GenericType fromType , GenericType toType ) {
789839 // Semantically equivalent with
790840 // ```ql
791841 // ugt = fromType.getUnboundGeneric()
@@ -805,10 +855,23 @@ private predicate convVariance(GenericType fromType, GenericType toType) {
805855 // ```
806856 // but performance is improved by explicitly evaluating the `i`th argument
807857 // only when all preceding arguments are convertible.
808- Variance:: convVarianceSingle ( _ , fromType , toType )
858+ Variance:: convVarianceSingle ( ugt , fromType , toType )
809859 or
860+ Variance:: convVarianceMultiple ( ugt , fromType , toType , ugt .getNumberOfTypeParameters ( ) - 1 )
861+ }
862+
863+ /** 13.1.3.2: Variance conversion. */
864+ private predicate convVariance ( GenericType fromType , GenericType toType ) {
865+ convVarianceAux ( _, fromType , toType )
866+ }
867+
868+ /**
869+ * Holds, if `fromType` is covariance convertible to `toType`.
870+ */
871+ private predicate convCovariance ( GenericType fromType , GenericType toType ) {
810872 exists ( UnboundGenericType ugt |
811- Variance:: convVarianceMultiple ( ugt , fromType , toType , ugt .getNumberOfTypeParameters ( ) - 1 )
873+ convVarianceAux ( ugt , fromType , toType ) and
874+ forall ( TypeParameter tp | tp = ugt .getATypeParameter ( ) | tp .isOut ( ) )
812875 )
813876}
814877
0 commit comments