コード例 #1
0
ファイル: TupleTypeDecoder.cs プロジェクト: stark-lang/stark
        private ImmutableArray <TypeSymbolWithAnnotations> DecodeTypeArguments(ImmutableArray <TypeSymbolWithAnnotations> typeArgs)
        {
            if (typeArgs.IsEmpty)
            {
                return(typeArgs);
            }

            var decodedArgs = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(typeArgs.Length);

            var anyDecoded = false;

            // Visit the type arguments in reverse
            for (int i = typeArgs.Length - 1; i >= 0; i--)
            {
                TypeSymbolWithAnnotations typeArg = typeArgs[i];
                TypeSymbolWithAnnotations decoded = DecodeTypeInternal(typeArg);
                anyDecoded |= !decoded.IsSameAs(typeArg);
                decodedArgs.Add(decoded);
            }

            if (!anyDecoded)
            {
                decodedArgs.Free();
                return(typeArgs);
            }

            decodedArgs.ReverseContents();
            return(decodedArgs.ToImmutableAndFree());
        }
コード例 #2
0
ファイル: TupleTypeDecoder.cs プロジェクト: xiankang/roslyn
        private ArrayTypeSymbol DecodeArrayType(ArrayTypeSymbol type)
        {
            TypeSymbolWithAnnotations elementType        = type.ElementType;
            TypeSymbolWithAnnotations decodedElementType = DecodeTypeInternal(elementType);

            return(decodedElementType.IsSameAs(elementType)
                ? type
                : type.WithElementType(decodedElementType));
        }
コード例 #3
0
ファイル: TypeUnification.cs プロジェクト: stark-lang/stark
        private static TypeSymbolWithAnnotations SubstituteAllTypeParameters(AbstractTypeMap substitution, TypeSymbolWithAnnotations type)
        {
            if (substitution != null)
            {
                TypeSymbolWithAnnotations previous;
                do
                {
                    previous = type;
                    type     = type.SubstituteType(substitution);
                } while (!type.IsSameAs(previous));
            }

            return(type);
        }
コード例 #4
0
        private ArrayTypeSymbol SubstituteArrayType(ArrayTypeSymbol t)
        {
            var oldElement = t.ElementType;
            TypeSymbolWithAnnotations element = oldElement.SubstituteTypeWithTupleUnification(this);

            if (element.IsSameAs(oldElement))
            {
                return(t);
            }

            if (t.IsSZArray)
            {
                ImmutableArray <NamedTypeSymbol> interfaces = t.InterfacesNoUseSiteDiagnostics();
                Debug.Assert(0 <= interfaces.Length && interfaces.Length <= 2);

                if (interfaces.Length == 1)
                {
                    Debug.Assert(interfaces[0] is NamedTypeSymbol); // IList<T>
                    interfaces = ImmutableArray.Create <NamedTypeSymbol>(SubstituteNamedType(interfaces[0]));
                }
                else if (interfaces.Length == 2)
                {
                    Debug.Assert(interfaces[0] is NamedTypeSymbol); // IList<T>
                    interfaces = ImmutableArray.Create <NamedTypeSymbol>(SubstituteNamedType(interfaces[0]), SubstituteNamedType(interfaces[1]));
                }
                else if (interfaces.Length != 0)
                {
                    throw ExceptionUtilities.Unreachable;
                }

                return(ArrayTypeSymbol.CreateSZArray(
                           element,
                           t.BaseTypeNoUseSiteDiagnostics,
                           interfaces));
            }

            return(ArrayTypeSymbol.CreateMDArray(
                       element,
                       t.Rank,
                       t.Sizes,
                       t.LowerBounds,
                       t.BaseTypeNoUseSiteDiagnostics));
        }
コード例 #5
0
ファイル: TypeUnification.cs プロジェクト: stark-lang/stark
        /// <summary>
        /// Determine whether there is any substitution of type parameters that will
        /// make two types identical.
        /// </summary>
        /// <param name="t1">LHS</param>
        /// <param name="t2">RHS</param>
        /// <param name="substitution">
        /// Substitutions performed so far (or null for none).
        /// Keys are type parameters, values are types (possibly type parameters).
        /// Will be updated with new substitutions by the callee.
        /// Should be ignored when false is returned.
        /// </param>
        /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns>
        /// <remarks>
        /// Derived from Dev10's BSYMMGR::UnifyTypes.
        /// Two types will not unify if they have different custom modifiers.
        /// </remarks>
        private static bool CanUnifyHelper(TypeSymbolWithAnnotations t1, TypeSymbolWithAnnotations t2, ref MutableTypeMap substitution)
        {
            if (t1.IsNull || t2.IsNull)
            {
                return(t1.IsSameAs(t2));
            }

            if (TypeSymbol.Equals(t1.TypeSymbol, t2.TypeSymbol, TypeCompareKind.ConsiderEverything2) && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers))
            {
                return(true);
            }

            if (substitution != null)
            {
                t1 = t1.SubstituteType(substitution);
                t2 = t2.SubstituteType(substitution);
            }

            // If one of the types is a type parameter, then the substitution could make them equal.
            if (TypeSymbol.Equals(t1.TypeSymbol, t2.TypeSymbol, TypeCompareKind.ConsiderEverything2) && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers))
            {
                return(true);
            }

            // We can avoid a lot of redundant checks if we ensure that we only have to check
            // for type parameters on the LHS
            if (!t1.TypeSymbol.IsTypeParameter() && t2.TypeSymbol.IsTypeParameter())
            {
                TypeSymbolWithAnnotations tmp = t1;
                t1 = t2;
                t2 = tmp;
            }

            // If t1 is not a type parameter, then neither is t2
            Debug.Assert(t1.TypeSymbol.IsTypeParameter() || !t2.TypeSymbol.IsTypeParameter());

            switch (t1.Kind)
            {
            case SymbolKind.ArrayType:
            {
                if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1.TypeSymbol;
                ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2.TypeSymbol;

                return(CanUnifyHelper(at1.ElementType, at2.ElementType, ref substitution));
            }

            case SymbolKind.PointerType:
            {
                if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                PointerTypeSymbol pt1 = (PointerTypeSymbol)t1.TypeSymbol;
                PointerTypeSymbol pt2 = (PointerTypeSymbol)t2.TypeSymbol;

                return(CanUnifyHelper(pt1.PointedAtType, pt2.PointedAtType, ref substitution));
            }

            case SymbolKind.NamedType:
            case SymbolKind.ErrorType:
            {
                if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                NamedTypeSymbol nt1 = (NamedTypeSymbol)t1.TypeSymbol;
                NamedTypeSymbol nt2 = (NamedTypeSymbol)t2.TypeSymbol;

                if (nt1.IsTupleType)
                {
                    if (!nt2.IsTupleType)
                    {
                        return(false);
                    }

                    return(CanUnifyHelper(nt1.TupleUnderlyingType, nt2.TupleUnderlyingType, ref substitution));
                }

                if (!nt1.IsGenericType)
                {
                    return(!nt2.IsGenericType && TypeSymbol.Equals(nt1, nt2, TypeCompareKind.ConsiderEverything2));
                }
                else if (!nt2.IsGenericType)
                {
                    return(false);
                }

                int arity = nt1.Arity;

                if (nt2.Arity != arity || !TypeSymbol.Equals(nt2.OriginalDefinition, nt1.OriginalDefinition, TypeCompareKind.ConsiderEverything2))
                {
                    return(false);
                }

                var nt1Arguments = nt1.TypeArgumentsNoUseSiteDiagnostics;
                var nt2Arguments = nt2.TypeArgumentsNoUseSiteDiagnostics;

                for (int i = 0; i < arity; i++)
                {
                    if (!CanUnifyHelper(nt1Arguments[i],
                                        nt2Arguments[i],
                                        ref substitution))
                    {
                        return(false);
                    }
                }

                // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types
                // TODO: Calling CanUnifyHelper for the containing type is an overkill, we simply need to go through type arguments for all containers.
                return((object)nt1.ContainingType == null || CanUnifyHelper(nt1.ContainingType, nt2.ContainingType, ref substitution));
            }

            case SymbolKind.TypeParameter:
            {
                // These substitutions are not allowed in C#
                if (t2.TypeKind == TypeKind.Pointer || t2.SpecialType == SpecialType.System_Void)
                {
                    return(false);
                }

                TypeParameterSymbol tp1 = (TypeParameterSymbol)t1.TypeSymbol;

                // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types
                // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above
                if (Contains(t2.TypeSymbol, tp1))
                {
                    return(false);
                }

                if (t1.CustomModifiers.IsDefaultOrEmpty)
                {
                    AddSubstitution(ref substitution, tp1, t2);
                    return(true);
                }

                if (t1.CustomModifiers.SequenceEqual(t2.CustomModifiers))
                {
                    AddSubstitution(ref substitution, tp1, TypeSymbolWithAnnotations.Create(t2.TypeSymbol));
                    return(true);
                }

                if (t1.CustomModifiers.Length < t2.CustomModifiers.Length &&
                    t1.CustomModifiers.SequenceEqual(t2.CustomModifiers.Take(t1.CustomModifiers.Length)))
                {
                    AddSubstitution(ref substitution, tp1,
                                    TypeSymbolWithAnnotations.Create(t2.TypeSymbol,
                                                                     customModifiers: ImmutableArray.Create(t2.CustomModifiers, t1.CustomModifiers.Length, t2.CustomModifiers.Length - t1.CustomModifiers.Length)));
                    return(true);
                }

                if (t2.TypeSymbol.IsTypeParameter())
                {
                    var tp2 = (TypeParameterSymbol)t2.TypeSymbol;

                    if (t2.CustomModifiers.IsDefaultOrEmpty)
                    {
                        AddSubstitution(ref substitution, tp2, t1);
                        return(true);
                    }

                    if (t2.CustomModifiers.Length < t1.CustomModifiers.Length &&
                        t2.CustomModifiers.SequenceEqual(t1.CustomModifiers.Take(t2.CustomModifiers.Length)))
                    {
                        AddSubstitution(ref substitution, tp2,
                                        TypeSymbolWithAnnotations.Create(t1.TypeSymbol,
                                                                         customModifiers: ImmutableArray.Create(t1.CustomModifiers, t2.CustomModifiers.Length, t1.CustomModifiers.Length - t2.CustomModifiers.Length)));
                        return(true);
                    }
                }

                return(false);
            }

            default:
            {
                return(false);
            }
            }
        }