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); }
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; }
/// <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)); }
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(); } }
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)); }
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()); }
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); }
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; }
public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId) : base(underlyingField) { _containingTuple = container; _tupleFieldId = tupleFieldId; }
public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent) : base(underlyingEvent) { _containingType = container; }
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(); } }
public TuplePropertySymbol(TupleTypeSymbol container, PropertySymbol underlyingProperty) : base(underlyingProperty) { _containingType = container; }
/// <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)); }
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); }
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; }
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; }
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; }
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; }
public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId, Location location) : base(container, underlyingField, tupleFieldId) { _locations = location == null ? ImmutableArray <Location> .Empty : ImmutableArray.Create(location); }
/// <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)); }
/// <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(); } }
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,
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; } }
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); } }
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); }
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); }
/// <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); }
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; }