예제 #1
0
        public TupleMethodSymbol(TupleTypeSymbol container, MethodSymbol underlyingMethod)
        {
            Debug.Assert(underlyingMethod.ConstructedFrom == (object)underlyingMethod);
            _containingType = container;

            TypeMap.Empty.WithAlphaRename(underlyingMethod, this, out _typeParameters);
            _underlyingMethod = underlyingMethod.ConstructIfGeneric(TypeArguments);
        }
예제 #2
0
        public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleElementIndex)
            : base(underlyingField)
        {
            Debug.Assert(container.UnderlyingNamedType.Equals(underlyingField.ContainingType, TypeCompareKind.IgnoreDynamicAndTupleNames) || this is TupleVirtualElementFieldSymbol,
                                            "virtual fields should be represented by " + nameof(TupleVirtualElementFieldSymbol));

            _containingTuple = container;
            _tupleElementIndex = tupleElementIndex;
        }
예제 #3
0
        /// <summary>
        /// Converts access to a tuple instance into access into the underlying ValueTuple(s).
        ///
        /// For instance, tuple.Item8
        /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple))
        /// </summary>
        private BoundExpression MakeTupleFieldAccess(
            CSharpSyntaxNode syntax,
            FieldSymbol tupleField,
            BoundExpression rewrittenReceiver,
            ConstantValue constantValueOpt,
            LookupResultKind resultKind)
        {
            var tupleType = tupleField.ContainingType;

            NamedTypeSymbol currentLinkType = tupleType.TupleUnderlyingType;
            FieldSymbol     underlyingField = tupleField.TupleUnderlyingField;

            if ((object)underlyingField == null)
            {
                // Use-site error must have been reported elsewhere.
                return(_factory.BadExpression(tupleField.Type));
            }

            if (underlyingField.ContainingType != currentLinkType)
            {
                WellKnownMember wellKnownTupleRest = TupleTypeSymbol.GetTupleTypeMember(TupleTypeSymbol.RestPosition, TupleTypeSymbol.RestPosition);
                var             tupleRestField     = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax);

                if ((object)tupleRestField == null)
                {
                    // error tolerance for cases when Rest is missing
                    return(_factory.BadExpression(tupleField.Type));
                }

                // make nested field accesses to Rest
                do
                {
                    FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType);
                    rewrittenReceiver = _factory.Field(rewrittenReceiver, nestedFieldSymbol);

                    currentLinkType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType;
                }while (underlyingField.ContainingType != currentLinkType);
            }

            // make a field access for the most local access
            return(_factory.Field(rewrittenReceiver, underlyingField));
        }
예제 #4
0
        protected override bool HasImplicitTupleConversion(BoundExpression source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            if (source.Kind != BoundKind.TupleLiteral)
            {
                // source must be a tuple literal with no conversions
                return(false);
            }

            var tupleExpression = (BoundTupleLiteral)source;
            var arguments       = tupleExpression.Arguments;

            // check if the type is actually compatible type for a tuple of given cardinality
            if (!destination.IsTupleOrCompatibleWithTupleOfCardinality(arguments.Length))
            {
                return(false);
            }

            var targetElementTypes = ArrayBuilder <TypeSymbol> .GetInstance(arguments.Length);

            TupleTypeSymbol.AddElementTypes((NamedTypeSymbol)destination, targetElementTypes);
            Debug.Assert(arguments.Length == targetElementTypes.Count);

            try
            {
                // check arguments against flattened list of target element types
                for (int i = 0; i < arguments.Length; i++)
                {
                    var argument = arguments[i];
                    var result   = ClassifyImplicitConversionFromExpression(argument, targetElementTypes[i], ref useSiteDiagnostics);
                    if (!result.Exists)
                    {
                        return(false);
                    }
                }

                return(true);
            }
            finally
            {
                targetElementTypes.Free();
            }
        }
예제 #5
0
        private BoundDeconstructionConstructionStep MakeDeconstructionConstructionStep(CSharpSyntaxNode node, DiagnosticBag diagnostics,
                                                                                       ImmutableArray <BoundDeconstructValuePlaceholder> constructionInputs)
        {
            var tuple = TupleTypeSymbol.Create(locationOpt: null,
                                               elementTypes: constructionInputs.SelectAsArray(e => e.Type),
                                               elementLocations: default(ImmutableArray <Location>),
                                               elementNames: default(ImmutableArray <string>),
                                               compilation: Compilation,
                                               diagnostics: diagnostics,
                                               syntax: node);

            var outputPlaceholder = new BoundDeconstructValuePlaceholder(node, tuple)
            {
                WasCompilerGenerated = true
            };

            BoundExpression construction = new BoundTupleLiteral(node, default(ImmutableArray <string>), constructionInputs.CastArray <BoundExpression>(), tuple);

            return(new BoundDeconstructionConstructionStep(node, construction, outputPlaceholder));
        }
예제 #6
0
        public static ImmutableArray <TypeSymbol> GetElementTypesOfTupleOrCompatible(this TypeSymbol type)
        {
            if (type.IsTupleType)
            {
                return(((TupleTypeSymbol)type).TupleElementTypes);
            }

            // The following codepath should be very uncommon since it would be rare
            // to see a tuple underlying type not represented as a tuple.
            // It still might happen since tuple underlying types are creatable via public APIs
            // and it is also possible that they would be passed in.

            Debug.Assert(type.IsTupleCompatible());

            // PERF: if allocations here become nuisance, consider caching the results
            //       in the type symbols that can actually be tuple compatible
            var elementTypesBuilder = ArrayBuilder <TypeSymbol> .GetInstance();

            TupleTypeSymbol.AddElementTypes((NamedTypeSymbol)type, elementTypesBuilder);

            return(elementTypesBuilder.ToImmutableAndFree());
        }
예제 #7
0
        private PEParameterSymbol(
            PEModuleSymbol moduleSymbol,
            Symbol containingSymbol,
            int ordinal,
            bool isByRef,
            TypeSymbolWithAnnotations type,
            ImmutableArray <bool> extraAnnotations,
            ParameterHandle handle,
            int countOfCustomModifiers,
            out bool isBad)
        {
            Debug.Assert((object)moduleSymbol != null);
            Debug.Assert((object)containingSymbol != null);
            Debug.Assert(ordinal >= 0);
            Debug.Assert(!type.IsNull);

            isBad             = false;
            _moduleSymbol     = moduleSymbol;
            _containingSymbol = containingSymbol;
            _ordinal          = (ushort)ordinal;

            _handle = handle;

            RefKind refKind = RefKind.None;

            if (handle.IsNil)
            {
                refKind = isByRef ? RefKind.Ref : RefKind.None;

                type = TupleTypeSymbol.TryTransformToTuple(type.TypeSymbol, out TupleTypeSymbol tuple) ?
                       TypeSymbolWithAnnotations.Create(tuple) :
                       type;
                if (!extraAnnotations.IsDefault)
                {
                    // https://github.com/dotnet/roslyn/issues/29821 any external annotation is taken to imply a `[NonNullTypes(true)]` context
                    type = NullableTypeDecoder.TransformType(type, extraAnnotations, nonNullTypesContext: NonNullTypesTrueContext.Instance);
                }

                _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyDefaultValue     = ConstantValue.NotAvailable;
                _lazyIsParams         = ThreeState.False;
            }
            else
            {
                try
                {
                    moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags);
                }
                catch (BadImageFormatException)
                {
                    isBad = true;
                }

                if (isByRef)
                {
                    ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In);

                    if (inOutFlags == ParameterAttributes.Out)
                    {
                        refKind = RefKind.Out;
                    }
                    else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle))
                    {
                        refKind = RefKind.In;
                    }
                    else
                    {
                        refKind = RefKind.Ref;
                    }
                }

                // CONSIDER: Can we make parameter type computation lazy?
                var typeSymbol = DynamicTypeDecoder.TransformType(type.TypeSymbol, countOfCustomModifiers, handle, moduleSymbol, refKind);
                type = type.WithTypeAndModifiers(typeSymbol, type.CustomModifiers);
                // Decode nullable before tuple types to avoid converting between
                // NamedTypeSymbol and TupleTypeSymbol unnecessarily.
                type = NullableTypeDecoder.TransformType(type, handle, moduleSymbol, nonNullTypesContext: this, extraAnnotations);
                type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol);
            }

            _type = type;

            bool hasNameInMetadata = !string.IsNullOrEmpty(_name);

            if (!hasNameInMetadata)
            {
                // As was done historically, if the parameter doesn't have a name, we give it the name "value".
                _name = "value";
            }

            _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata);

            Debug.Assert(refKind == this.RefKind);
            Debug.Assert(hasNameInMetadata == this.HasNameInMetadata);
        }
예제 #8
0
 public TupleRenamedElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, string name, int tupleElementOrdinal, Location location)
     : base(container, underlyingField, tupleElementOrdinal, location)
 {
     Debug.Assert(name != null);
     Debug.Assert(name != underlyingField.Name);
     _name = name;
 }
예제 #9
0
 public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId)
     : base(underlyingField)
 {
     _containingTuple = container;
     _tupleFieldId = tupleFieldId;
 }
예제 #10
0
 public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent)
     : base(underlyingEvent)
 {
     _containingType = container;
 }
예제 #11
0
 public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId, Location location)
     : base(container, underlyingField, tupleFieldId)
 {
     _locations = location == null ? ImmutableArray<Location>.Empty : ImmutableArray.Create(location);
 }
        private BoundExpression MakeTupleCreationExpression(SyntaxNode syntax, NamedTypeSymbol type, ImmutableArray <BoundExpression> rewrittenArguments)
        {
            NamedTypeSymbol underlyingTupleType = type.TupleUnderlyingType ?? type;

            Debug.Assert(underlyingTupleType.IsTupleCompatible());

            ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain);

            try
            {
                // make a creation expression for the smallest type
                NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop();
                ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1),
                                                                                               smallestType.Arity);
                var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition,
                                                                                          TupleTypeSymbol.GetTupleCtor(smallestType.Arity),
                                                                                          _diagnostics,
                                                                                          syntax);
                if ((object)smallestCtor == null)
                {
                    return(_factory.BadExpression(type));
                }

                MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType);
                BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(syntax, smallestConstructor, null, smallestCtorArguments);

                if (underlyingTupleTypeChain.Count > 0)
                {
                    NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek();
                    var             tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition,
                                                                                                        TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition),
                                                                                                        _diagnostics,
                                                                                                        syntax);
                    if ((object)tuple8Ctor == null)
                    {
                        return(_factory.BadExpression(type));
                    }

                    // make successively larger creation expressions containing the previous one
                    do
                    {
                        ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1),
                                                                                               TupleTypeSymbol.RestPosition - 1)
                                                                         .Add(currentCreation);

                        MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop());
                        currentCreation = new BoundObjectCreationExpression(syntax, constructor, null, ctorArguments);
                    }while (underlyingTupleTypeChain.Count > 0);
                }

                currentCreation = currentCreation.Update(
                    currentCreation.Constructor,
                    currentCreation.Arguments,
                    currentCreation.ArgumentNamesOpt,
                    currentCreation.ArgumentRefKindsOpt,
                    currentCreation.Expanded,
                    currentCreation.ArgsToParamsOpt,
                    currentCreation.ConstantValue,
                    currentCreation.InitializerExpressionOpt,
                    currentCreation.BinderOpt,
                    type);

                return(currentCreation);
            }
            finally
            {
                underlyingTupleTypeChain.Free();
            }
        }
예제 #13
0
 public TuplePropertySymbol(TupleTypeSymbol container, PropertySymbol underlyingProperty)
     : base(underlyingProperty)
 {
     _containingType = container;
 }
예제 #14
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 typesBuilder = ArrayBuilder <TypeSymbol> .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)
                        {
                            // typeless-variable on the left and typeless-element on the right
                            Error(diagnostics, ErrorCode.ERR_DeconstructCouldNotInferMergedType, syntax, variable.Syntax, element.Syntax);
                        }
                    }
                }
                else
                {
                    if ((object)mergedType == null)
                    {
                        // a typeless element on the right, matching no variable on the left
                        Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax);
                    }
                }

                typesBuilder.Add(mergedType);
            }

            if (typesBuilder.Any(t => t == null))
            {
                typesBuilder.Free();
                return(null);
            }

            return(TupleTypeSymbol.Create(locationOpt: null, elementTypes: typesBuilder.ToImmutableAndFree(), elementLocations: default(ImmutableArray <Location>), elementNames: default(ImmutableArray <string>), compilation: compilation, diagnostics: diagnostics));
        }
예제 #15
0
        private PEParameterSymbol(
            PEModuleSymbol moduleSymbol,
            Symbol containingSymbol,
            int ordinal,
            bool isByRef,
            TypeSymbol type,
            ParameterHandle handle,
            int countOfCustomModifiers,
            out bool isBad)
        {
            Debug.Assert((object)moduleSymbol != null);
            Debug.Assert((object)containingSymbol != null);
            Debug.Assert(ordinal >= 0);
            Debug.Assert((object)type != null);

            isBad             = false;
            _moduleSymbol     = moduleSymbol;
            _containingSymbol = containingSymbol;
            _ordinal          = (ushort)ordinal;

            _handle = handle;

            RefKind refKind = RefKind.None;

            if (handle.IsNil)
            {
                refKind = isByRef ? RefKind.Ref : RefKind.None;

                type  = TupleTypeSymbol.TransformToTupleIfCompatible(type);
                _type = type;

                _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyDefaultValue     = ConstantValue.NotAvailable;
                _lazyIsParams         = ThreeState.False;
            }
            else
            {
                try
                {
                    moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags);
                }
                catch (BadImageFormatException)
                {
                    isBad = true;
                }

                if (isByRef)
                {
                    ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In);

                    if (inOutFlags == ParameterAttributes.Out)
                    {
                        refKind = RefKind.Out;
                    }
                    else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle))
                    {
                        refKind = RefKind.In;
                    }
                    else
                    {
                        refKind = RefKind.Ref;
                    }
                }

                // CONSIDER: Can we make parameter type computation lazy?
                type = DynamicTypeDecoder.TransformType(type, countOfCustomModifiers, handle, moduleSymbol, refKind);

                _type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol);
            }

            bool hasNameInMetadata = !string.IsNullOrEmpty(_name);

            if (!hasNameInMetadata)
            {
                // As was done historically, if the parameter doesn't have a name, we give it the name "value".
                _name = "value";
            }

            _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata);

            Debug.Assert(refKind == this.RefKind);
            Debug.Assert(hasNameInMetadata == this.HasNameInMetadata);
        }
예제 #16
0
        public TupleVirtualElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, string name, int tupleElementOrdinal, Location location)
            : base(container, underlyingField, tupleElementOrdinal, location)
        {
            Debug.Assert(name != null);
            Debug.Assert(name != underlyingField.Name || !container.UnderlyingNamedType.Equals(underlyingField.ContainingType, TypeCompareKind.IgnoreDynamicAndTupleNames),
                                "fields that map directly to underlying should not be represented by " + nameof(TupleVirtualElementFieldSymbol));

            _name = name;
        }
예제 #17
0
        public TupleVirtualElementFieldSymbol(
            TupleTypeSymbol container, 
            FieldSymbol underlyingField, 
            string name, 
            int tupleElementIndex, 
            Location location, 
            bool isImplicitlyDeclared, 
            TupleElementFieldSymbol correspondingDefaultFieldOpt)

            : base(container, underlyingField, tupleElementIndex, location, isImplicitlyDeclared, correspondingDefaultFieldOpt)
        {
            Debug.Assert(name != null);
            Debug.Assert(name != underlyingField.Name || !container.UnderlyingNamedType.Equals(underlyingField.ContainingType, TypeCompareKind.IgnoreDynamicAndTupleNames),
                                "fields that map directly to underlying should not be represented by " + nameof(TupleVirtualElementFieldSymbol));

            _name = name;
        }
예제 #18
0
        public TupleElementFieldSymbol(
            TupleTypeSymbol container, 
            FieldSymbol underlyingField, 
            int tupleElementIndex, 
            Location location, 
            bool isImplicitlyDeclared, 
            TupleElementFieldSymbol correspondingDefaultFieldOpt)

            : base(container, underlyingField, (object)correspondingDefaultFieldOpt == null ? tupleElementIndex << 1 : (tupleElementIndex << 1) + 1)
        {
            _locations = location == null ? ImmutableArray<Location>.Empty : ImmutableArray.Create(location);
            _isImplicitlyDeclared = isImplicitlyDeclared;

            Debug.Assert((correspondingDefaultFieldOpt == null) == this.IsDefaultTupleElement);
            Debug.Assert(correspondingDefaultFieldOpt == null || correspondingDefaultFieldOpt.IsDefaultTupleElement);

            _correspondingDefaultField = correspondingDefaultFieldOpt ?? this;
        }
예제 #19
0
 public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleElementIndex, Location location, bool isImplicitlyDeclared)
     : base(container, underlyingField, tupleElementIndex)
 {
     _locations            = location == null ? ImmutableArray <Location> .Empty : ImmutableArray.Create(location);
     _isImplicitlyDeclared = isImplicitlyDeclared;
 }
예제 #20
0
 public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent)
     : base(underlyingEvent)
 {
     _containingType = container;
 }
예제 #21
0
 public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId, Location location)
     : base(container, underlyingField, tupleFieldId)
 {
     _locations = location == null ? ImmutableArray <Location> .Empty : ImmutableArray.Create(location);
 }
예제 #22
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 typesBuilder = ArrayBuilder <TypeSymbol> .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);
                    }
                }

                typesBuilder.Add(mergedType);
                locationsBuilder.Add(element.Syntax.Location);
            }

            if (typesBuilder.Any(t => t == null))
            {
                typesBuilder.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(TupleTypeSymbol.Create(
                       locationOpt: null,
                       elementTypes: typesBuilder.ToImmutableAndFree(),
                       elementLocations: locationsBuilder.ToImmutableAndFree(),
                       elementNames: default(ImmutableArray <string>),
                       compilation: compilation,
                       diagnostics: diagnostics,
                       shouldCheckConstraints: true,
                       errorPositions: default(ImmutableArray <bool>),
                       syntax: syntax));
        }
예제 #23
0
 public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId)
     : base(underlyingField)
 {
     _containingTuple = container;
     _tupleFieldId    = tupleFieldId;
 }
        /// <summary>
        /// Converts the expression for creating a tuple instance into an expression creating a ValueTuple (if short) or nested ValueTuples (if longer).
        ///
        /// For instance, for a long tuple we'll generate:
        /// creationExpression(ctor=largestCtor, args=firstArgs+(nested creationExpression for remainder, with smaller ctor and next few args))
        /// </summary>
        private BoundNode RewriteTupleCreationExpression(BoundTupleExpression node, ImmutableArray <BoundExpression> rewrittenArguments)
        {
            NamedTypeSymbol underlyingTupleType = node.Type.TupleUnderlyingType;

            ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain);

            try
            {
                // make a creation expression for the smallest type
                NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop();
                ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1),
                                                                                               smallestType.Arity);
                var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition,
                                                                                          TupleTypeSymbol.GetTupleCtor(smallestType.Arity),
                                                                                          _diagnostics,
                                                                                          node.Syntax);
                if ((object)smallestCtor == null)
                {
                    return(node);
                }

                MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType);
                BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(node.Syntax, smallestConstructor, smallestCtorArguments);

                if (underlyingTupleTypeChain.Count > 0)
                {
                    NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek();
                    var             tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition,
                                                                                                        TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition),
                                                                                                        _diagnostics,
                                                                                                        node.Syntax);
                    if ((object)tuple8Ctor == null)
                    {
                        return(node);
                    }

                    // make successively larger creation expressions containing the previous one
                    do
                    {
                        ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1),
                                                                                               TupleTypeSymbol.RestPosition - 1)
                                                                         .Add(currentCreation);

                        MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop());
                        currentCreation = new BoundObjectCreationExpression(node.Syntax, constructor, ctorArguments);
                    }while (underlyingTupleTypeChain.Count > 0);
                }

                return(currentCreation);
            }
            finally
            {
                underlyingTupleTypeChain.Free();
            }
        }
예제 #25
0
        private BoundTupleLiteral DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax, ArrayBuilder <DeconstructionVariable> variables,
                                                                 DiagnosticBag diagnostics, bool ignoreDiagnosticsFromTuple)
        {
            int count         = variables.Count;
            var valuesBuilder = ArrayBuilder <BoundExpression> .GetInstance(count);

            var typesBuilder = ArrayBuilder <TypeSymbolWithAnnotations> .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);
                typesBuilder.Add(value.GetTypeAndNullability());
                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 = TupleTypeSymbol.Create(
                                                                                               syntax.Location,
                                                                                               typesBuilder.ToImmutableAndFree(), locationsBuilder.ToImmutableAndFree(),
                                                                                               tupleNames, this.Compilation,
                                                                                               shouldCheckConstraints: !ignoreDiagnosticsFromTuple,
                                                                                               includeNullability: false,
                                                                                               errorPositions: disallowInferredNames ? inferredPositions : default,
예제 #26
0
        internal PEPropertySymbol(
            PEModuleSymbol moduleSymbol,
            PENamedTypeSymbol containingType,
            PropertyDefinitionHandle handle,
            PEMethodSymbol getMethod,
            PEMethodSymbol setMethod)
        {
            Debug.Assert((object)moduleSymbol != null);
            Debug.Assert((object)containingType != null);
            Debug.Assert(!handle.IsNil);

            _containingType = containingType;
            var module = moduleSymbol.Module;
            PropertyAttributes      mdFlags = 0;
            BadImageFormatException mrEx    = null;

            try
            {
                module.GetPropertyDefPropsOrThrow(handle, out _name, out mdFlags);
            }
            catch (BadImageFormatException e)
            {
                mrEx = e;

                if ((object)_name == null)
                {
                    _name = string.Empty;
                }
            }

            _getMethod = getMethod;
            _setMethod = setMethod;
            _handle    = handle;

            var                     metadataDecoder = new MetadataDecoder(moduleSymbol, containingType);
            SignatureHeader         callingConvention;
            BadImageFormatException propEx;
            var                     propertyParams = metadataDecoder.GetSignatureForProperty(handle, out callingConvention, out propEx, allowByRefReturn: true);

            Debug.Assert(propertyParams.Length > 0);

            SignatureHeader         unusedCallingConvention;
            BadImageFormatException getEx = null;
            var getMethodParams           = (object)getMethod == null ? null : metadataDecoder.GetSignatureForMethod(getMethod.Handle, out unusedCallingConvention, out getEx, allowByRefReturn: true);
            BadImageFormatException setEx = null;
            var setMethodParams           = (object)setMethod == null ? null : metadataDecoder.GetSignatureForMethod(setMethod.Handle, out unusedCallingConvention, out setEx, allowByRefReturn: false);

            // NOTE: property parameter names are not recorded in metadata, so we have to
            // use the parameter names from one of the indexers
            // NB: prefer setter names to getter names if both are present.
            bool isBad;

            _parameters = GetParameters(moduleSymbol, this, propertyParams, setMethodParams ?? getMethodParams, out isBad);

            if (propEx != null || getEx != null || setEx != null || mrEx != null || isBad)
            {
                _lazyUseSiteDiagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this);
            }

            _typeCustomModifiers = CSharpCustomModifier.Convert(propertyParams[0].CustomModifiers);

            _refKind = propertyParams[0].IsByRef ? RefKind.Ref : RefKind.None;

            // CONSIDER: Can we make parameter type computation lazy?
            TypeSymbol originalPropertyType = propertyParams[0].Type;

            _propertyType = DynamicTypeDecoder.TransformType(originalPropertyType, _typeCustomModifiers.Length, handle, moduleSymbol);

            // Dynamify object type if necessary
            _propertyType = _propertyType.AsDynamicIfNoPia(_containingType);

            _propertyType = TupleTypeSymbol.TransformToTupleIfCompatible(_propertyType); // temporary shallow unification

            // A property is bogus and must be accessed by calling its accessors directly if the
            // accessor signatures do not agree, both with each other and with the property,
            // or if it has parameters and is not an indexer or indexed property.
            bool callMethodsDirectly = !DoSignaturesMatch(module, metadataDecoder, propertyParams, _getMethod, getMethodParams, _setMethod, setMethodParams) ||
                                       MustCallMethodsDirectlyCore();

            if (!callMethodsDirectly)
            {
                if ((object)_getMethod != null)
                {
                    _getMethod.SetAssociatedProperty(this, MethodKind.PropertyGet);
                }

                if ((object)_setMethod != null)
                {
                    _setMethod.SetAssociatedProperty(this, MethodKind.PropertySet);
                }
            }

            if (callMethodsDirectly)
            {
                _flags |= Flags.CallMethodsDirectly;
            }

            if ((mdFlags & PropertyAttributes.SpecialName) != 0)
            {
                _flags |= Flags.IsSpecialName;
            }

            if ((mdFlags & PropertyAttributes.RTSpecialName) != 0)
            {
                _flags |= Flags.IsRuntimeSpecialName;
            }
        }
예제 #27
0
            public override Symbol VisitNamedType(NamedTypeSymbol sourceType)
            {
                var originalDef = sourceType.OriginalDefinition;

                if ((object)originalDef != (object)sourceType)
                {
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    var typeArguments = sourceType.GetAllTypeArguments(ref useSiteDiagnostics);

                    var otherDef = (NamedTypeSymbol)this.Visit(originalDef);
                    if ((object)otherDef == null)
                    {
                        return(null);
                    }

                    var  otherTypeParameters = otherDef.GetAllTypeParameters();
                    bool translationFailed   = false;

                    var otherTypeArguments = typeArguments.SelectAsArray((t, v) =>
                    {
                        var newType = (TypeSymbol)v.Visit(t.Type);

                        if ((object)newType == null)
                        {
                            // For a newly added type, there is no match in the previous generation, so it could be null.
                            translationFailed = true;
                            newType           = t.Type;
                        }

                        return(new TypeWithModifiers(newType, v.VisitCustomModifiers(t.CustomModifiers)));
                    }, this);

                    if (translationFailed)
                    {
                        // For a newly added type, there is no match in the previous generation, so it could be null.
                        return(null);
                    }

                    // TODO: LambdaFrame has alpha renamed type parameters, should we rather fix that?
                    var typeMap = new TypeMap(otherTypeParameters, otherTypeArguments, allowAlpha: true);
                    return(typeMap.SubstituteNamedType(otherDef));
                }
                else if (sourceType.IsTupleType)
                {
                    var otherDef = (NamedTypeSymbol)this.Visit(sourceType.TupleUnderlyingType);
                    if ((object)otherDef == null || !otherDef.IsTupleOrCompatibleWithTupleOfCardinality(sourceType.TupleElementTypes.Length))
                    {
                        return(null);
                    }

                    return(TupleTypeSymbol.Create(otherDef, sourceType.TupleElementNames));
                }

                Debug.Assert(sourceType.IsDefinition);

                var otherContainer = this.Visit(sourceType.ContainingSymbol);

                // Containing type will be missing from other assembly
                // if the type was added in the (newer) source assembly.
                if ((object)otherContainer == null)
                {
                    return(null);
                }

                switch (otherContainer.Kind)
                {
                case SymbolKind.Namespace:
                    if (AnonymousTypeManager.IsAnonymousTypeTemplate(sourceType))
                    {
                        Debug.Assert((object)otherContainer == (object)_otherAssembly.GlobalNamespace);
                        AnonymousTypeValue value;
                        this.TryFindAnonymousType(sourceType, out value);
                        return((NamedTypeSymbol)value.Type);
                    }
                    else if (sourceType.IsAnonymousType)
                    {
                        return(this.Visit(AnonymousTypeManager.TranslateAnonymousTypeSymbol(sourceType)));
                    }
                    else
                    {
                        return(FindMatchingNamespaceMember((NamespaceSymbol)otherContainer, sourceType, AreNamedTypesEqual));
                    }

                case SymbolKind.NamedType:
                    return(FindMatchingNamedTypeMember((NamedTypeSymbol)otherContainer, sourceType, AreNamedTypesEqual));

                default:
                    throw ExceptionUtilities.UnexpectedValue(otherContainer.Kind);
                }
            }
예제 #28
0
        private NamedTypeSymbol DecodeNamedType(NamedTypeSymbol type)
        {
            // First decode the type arguments
            var typeArgs    = type.TypeArgumentsNoUseSiteDiagnostics;
            var decodedArgs = DecodeTypeArguments(typeArgs);

            NamedTypeSymbol decodedType = type;

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

            if ((object)containingType != null && 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)
            {
                var newTypeArgs = type.HasTypeArgumentsCustomModifiers
                    ? decodedArgs.ZipAsArray(type.TypeArgumentsCustomModifiers, (t, m) => new TypeWithModifiers(t, m))
                    : decodedArgs.SelectAsArray(TypeMap.TypeSymbolAsTypeWithModifiers);

                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(newTypeArgs));
                }

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

            // Now decode into a tuple, if it is one
            int tupleCardinality;

            if (decodedType.IsTupleCompatible(out tupleCardinality))
            {
                var elementNames = EatElementNamesIfAvailable(tupleCardinality);

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

                decodedType = elementNames.IsDefault
                    ? TupleTypeSymbol.Create(decodedType)
                    : TupleTypeSymbol.Create(decodedType, elementNames);
            }

            return(decodedType);
        }
예제 #29
0
 public TuplePropertySymbol(TupleTypeSymbol container, PropertySymbol underlyingProperty)
     : base(underlyingProperty)
 {
     _containingType = container;
 }
예제 #30
0
        private PEParameterSymbol(
            PEModuleSymbol moduleSymbol,
            Symbol containingSymbol,
            int ordinal,
            bool isByRef,
            TypeWithAnnotations typeWithAnnotations,
            ParameterHandle handle,
            Symbol nullableContext,
            int countOfCustomModifiers,
            out bool isBad)
        {
            Debug.Assert((object)moduleSymbol != null);
            Debug.Assert((object)containingSymbol != null);
            Debug.Assert(ordinal >= 0);
            Debug.Assert(typeWithAnnotations.HasType);

            isBad             = false;
            _moduleSymbol     = moduleSymbol;
            _containingSymbol = containingSymbol;
            _ordinal          = (ushort)ordinal;

            _handle = handle;

            RefKind refKind = RefKind.None;

            if (handle.IsNil)
            {
                refKind = isByRef ? RefKind.Ref : RefKind.None;

                typeWithAnnotations = TupleTypeSymbol.TryTransformToTuple(typeWithAnnotations.Type, out TupleTypeSymbol tuple) ?
                                      TypeWithAnnotations.Create(tuple) :
                                      typeWithAnnotations;
                byte?value = nullableContext.GetNullableContextValue();
                if (value.HasValue)
                {
                    typeWithAnnotations = NullableTypeDecoder.TransformType(typeWithAnnotations, value.GetValueOrDefault(), default);
                }
                _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty;
                _lazyDefaultValue     = ConstantValue.NotAvailable;
                _lazyIsParams         = ThreeState.False;
            }
            else
            {
                try
                {
                    moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags);
                }
                catch (BadImageFormatException)
                {
                    isBad = true;
                }

                if (isByRef)
                {
                    ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In);

                    if (inOutFlags == ParameterAttributes.Out)
                    {
                        refKind = RefKind.Out;
                    }
                    else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle))
                    {
                        refKind = RefKind.In;
                    }
                    else
                    {
                        refKind = RefKind.Ref;
                    }
                }

                var typeSymbol = DynamicTypeDecoder.TransformType(typeWithAnnotations.Type, countOfCustomModifiers, handle, moduleSymbol, refKind);
                typeWithAnnotations = typeWithAnnotations.WithTypeAndModifiers(typeSymbol, typeWithAnnotations.CustomModifiers);
                // Decode nullable before tuple types to avoid converting between
                // NamedTypeSymbol and TupleTypeSymbol unnecessarily.

                // The containing type is passed to NullableTypeDecoder.TransformType to determine access
                // for property parameters because the property does not have explicit accessibility in metadata.
                var accessSymbol = containingSymbol.Kind == SymbolKind.Property ? containingSymbol.ContainingSymbol : containingSymbol;
                typeWithAnnotations = NullableTypeDecoder.TransformType(typeWithAnnotations, handle, moduleSymbol, accessSymbol: accessSymbol, nullableContext: nullableContext);
                typeWithAnnotations = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithAnnotations, handle, moduleSymbol);
            }

            _typeWithAnnotations = typeWithAnnotations;

            bool hasNameInMetadata = !string.IsNullOrEmpty(_name);

            if (!hasNameInMetadata)
            {
                // As was done historically, if the parameter doesn't have a name, we give it the name "value".
                _name = "value";
            }

            _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata);

            Debug.Assert(refKind == this.RefKind);
            Debug.Assert(hasNameInMetadata == this.HasNameInMetadata);
        }
예제 #31
0
 /// <summary>
 /// Checks whether the element name is reserved.
 ///
 /// For example:
 /// "Item3" is reserved (at certain positions).
 /// "Rest", "ToString" and other members of System.ValueTuple are reserved (in any position).
 /// Names that are not reserved return false.
 /// </summary>
 public static bool IsReservedTupleElementName(string elementName)
 {
     return(TupleTypeSymbol.IsElementNameReserved(elementName) != -1);
 }
예제 #32
0
 public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleElementIndex, Location location, bool isImplicitlyDeclared)
     : base(container, underlyingField, tupleElementIndex)
 {
     _locations = location == null ? ImmutableArray<Location>.Empty : ImmutableArray.Create(location);
     _isImplicitlyDeclared = isImplicitlyDeclared;
 }