Beispiel #1
0
        private NamedTypeSymbol DecodeNamedType(NamedTypeSymbol type)
        {
            // First decode the type arguments
            var typeArgs    = type.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;
            var decodedArgs = DecodeTypeArguments(typeArgs);

            NamedTypeSymbol decodedType = type;

            // Now check the container
            NamedTypeSymbol containingType = type.ContainingType;
            NamedTypeSymbol?decodedContainingType;

            if (containingType is object && containingType.IsGenericType)
            {
                decodedContainingType = DecodeNamedType(containingType);
                Debug.Assert(decodedContainingType.IsGenericType);
            }
            else
            {
                decodedContainingType = containingType;
            }

            // Replace the type if necessary
            var containerChanged = !ReferenceEquals(decodedContainingType, containingType);
            var typeArgsChanged  = typeArgs != decodedArgs;

            if (typeArgsChanged || containerChanged)
            {
                if (containerChanged)
                {
                    decodedType = decodedType.OriginalDefinition.AsMember(decodedContainingType);
                    // If the type is nested, e.g. Outer<T>.Inner<V>, then Inner is definitely
                    // not a tuple, since we know all tuple-compatible types (System.ValueTuple)
                    // are not nested types. Thus, it is safe to return without checking if
                    // Inner is a tuple.
                    return(decodedType.ConstructIfGeneric(decodedArgs));
                }

                decodedType = type.ConstructedFrom.Construct(decodedArgs, unbound: false);
            }

            // Now decode into a tuple, if it is one
            if (decodedType.IsTupleType)
            {
                int tupleCardinality = decodedType.TupleElementTypesWithAnnotations.Length;
                if (tupleCardinality > 0)
                {
                    var elementNames = EatElementNamesIfAvailable(tupleCardinality);

                    Debug.Assert(elementNames.IsDefault || elementNames.Length == tupleCardinality);

                    decodedType = NamedTypeSymbol.CreateTuple(decodedType, elementNames);
                }
            }

            return(decodedType);
        }
Beispiel #2
0
        private BoundTupleExpression DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax, ArrayBuilder <DeconstructionVariable> variables,
                                                                    DiagnosticBag diagnostics, bool ignoreDiagnosticsFromTuple)
        {
            int count         = variables.Count;
            var valuesBuilder = ArrayBuilder <BoundExpression> .GetInstance(count);

            var typesWithAnnotationsBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance(count);

            var locationsBuilder = ArrayBuilder <Location> .GetInstance(count);

            var namesBuilder = ArrayBuilder <string> .GetInstance(count);

            foreach (var variable in variables)
            {
                BoundExpression value;
                if (variable.HasNestedVariables)
                {
                    value = DeconstructionVariablesAsTuple(variable.Syntax, variable.NestedVariables, diagnostics, ignoreDiagnosticsFromTuple);
                    namesBuilder.Add(null);
                }
                else
                {
                    value = variable.Single;
                    namesBuilder.Add(ExtractDeconstructResultElementName(value));
                }
                valuesBuilder.Add(value);
                typesWithAnnotationsBuilder.Add(TypeWithAnnotations.Create(value.Type));
                locationsBuilder.Add(variable.Syntax.Location);
            }
            ImmutableArray <BoundExpression> arguments = valuesBuilder.ToImmutableAndFree();

            var uniqueFieldNames = PooledHashSet <string> .GetInstance();

            RemoveDuplicateInferredTupleNamesAndFreeIfEmptied(ref namesBuilder, uniqueFieldNames);
            uniqueFieldNames.Free();

            ImmutableArray <string> tupleNames = namesBuilder is null ? default : namesBuilder.ToImmutableAndFree();

                                                 ImmutableArray <bool> inferredPositions = tupleNames.IsDefault ? default : tupleNames.SelectAsArray(n => n != null);
                                                                                           bool disallowInferredNames = this.Compilation.LanguageVersion.DisallowInferredTupleElementNames();

                                                                                           var type = NamedTypeSymbol.CreateTuple(
                                                                                               syntax.Location,
                                                                                               typesWithAnnotationsBuilder.ToImmutableAndFree(), locationsBuilder.ToImmutableAndFree(),
                                                                                               tupleNames, this.Compilation,
                                                                                               shouldCheckConstraints: !ignoreDiagnosticsFromTuple,
                                                                                               includeNullability: false,
                                                                                               errorPositions: disallowInferredNames ? inferredPositions : default,
Beispiel #3
0
        /// <summary>
        /// For cases where the RHS of a deconstruction-declaration is a tuple literal, we merge type information from both the LHS and RHS.
        /// For cases where the RHS of a deconstruction-assignment is a tuple literal, the type information from the LHS determines the merged type, since all variables have a type.
        /// Returns null if a merged tuple type could not be fabricated.
        /// </summary>
        private static TypeSymbol MakeMergedTupleType(ArrayBuilder <DeconstructionVariable> lhsVariables, BoundTupleLiteral rhsLiteral, CSharpSyntaxNode syntax, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            int leftLength  = lhsVariables.Count;
            int rightLength = rhsLiteral.Arguments.Length;

            var typesWithAnnotationsBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance(leftLength);

            var locationsBuilder = ArrayBuilder <Location> .GetInstance(leftLength);

            for (int i = 0; i < rightLength; i++)
            {
                BoundExpression element    = rhsLiteral.Arguments[i];
                TypeSymbol      mergedType = element.Type;

                if (i < leftLength)
                {
                    var variable = lhsVariables[i];
                    if (variable.HasNestedVariables)
                    {
                        if (element.Kind == BoundKind.TupleLiteral)
                        {
                            // (variables) on the left and (elements) on the right
                            mergedType = MakeMergedTupleType(variable.NestedVariables, (BoundTupleLiteral)element, syntax, compilation, diagnostics);
                        }
                        else if ((object)mergedType == null)
                        {
                            // (variables) on the left and null on the right
                            Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax);
                        }
                    }
                    else
                    {
                        if ((object)variable.Single.Type != null)
                        {
                            // typed-variable on the left
                            mergedType = variable.Single.Type;
                        }
                    }
                }
                else
                {
                    if ((object)mergedType == null)
                    {
                        // a typeless element on the right, matching no variable on the left
                        Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax);
                    }
                }

                typesWithAnnotationsBuilder.Add(TypeWithAnnotations.Create(mergedType));
                locationsBuilder.Add(element.Syntax.Location);
            }

            if (typesWithAnnotationsBuilder.Any(t => !t.HasType))
            {
                typesWithAnnotationsBuilder.Free();
                locationsBuilder.Free();
                return(null);
            }

            // The tuple created here is not identical to the one created by
            // DeconstructionVariablesAsTuple. It represents a smaller
            // tree of types used for figuring out natural types in tuple literal.
            return(NamedTypeSymbol.CreateTuple(
                       locationOpt: null,
                       elementTypesWithAnnotations: typesWithAnnotationsBuilder.ToImmutableAndFree(),
                       elementLocations: locationsBuilder.ToImmutableAndFree(),
                       elementNames: default(ImmutableArray <string>),
                       compilation: compilation,
                       diagnostics: diagnostics,
                       shouldCheckConstraints: true,
                       includeNullability: false,
                       errorPositions: default(ImmutableArray <bool>),
                       syntax: syntax));
        }