From eda603e42b354edcf4503b4d64f9e3eaf13c4900 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sun, 24 Apr 2016 22:24:31 -0700 Subject: [PATCH 1/3] Extract common code into Wrapper...Symbol classes. No behavior changes intended. --- .../CSharp/Portable/CSharpCodeAnalysis.csproj | 8 +- .../Symbols/ReducedExtensionMethodSymbol.cs | 31 +- .../Retargeting/RetargetingEventSymbol.cs | 143 +------ .../Retargeting/RetargetingFieldSymbol.cs | 161 +------ .../Retargeting/RetargetingMethodSymbol.cs | 299 +------------ .../Retargeting/RetargetingNamedTypeSymbol.cs | 210 +--------- .../Retargeting/RetargetingParameterSymbol.cs | 123 +----- .../Retargeting/RetargetingPropertySymbol.cs | 169 +------- .../RetargetingTypeParameterSymbol.cs | 105 +---- .../Symbols/SubstitutedEventSymbol.cs | 115 +---- .../Symbols/SubstitutedFieldSymbol.cs | 160 +------ .../Symbols/SubstitutedMethodSymbol.cs | 298 ++----------- .../Symbols/SubstitutedNamedTypeSymbol.cs | 169 ++------ .../Symbols/SubstitutedParameterSymbol.cs | 30 +- .../Symbols/SubstitutedPropertySymbol.cs | 147 +------ .../Symbols/SubstitutedTypeParameterSymbol.cs | 95 +---- .../Symbols/WrappedParameterSymbol.cs | 179 -------- .../Symbols/Wrappers/WrapperEventSymbol.cs | 205 +++++++++ .../Symbols/Wrappers/WrapperFieldSymbol.cs | 209 ++++++++++ .../Symbols/Wrappers/WrapperMethodSymbol.cs | 392 ++++++++++++++++++ .../Wrappers/WrapperNamedTypeSymbol.cs | 327 +++++++++++++++ .../Wrappers/WrapperParameterSymbol.cs | 171 ++++++++ .../Symbols/Wrappers/WrapperPropertySymbol.cs | 232 +++++++++++ .../Wrappers/WrapperTypeParameterSymbol.cs | 142 +++++++ 24 files changed, 1852 insertions(+), 2268 deletions(-) delete mode 100644 src/Compilers/CSharp/Portable/Symbols/WrappedParameterSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperEventSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperFieldSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperMethodSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperParameterSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperPropertySymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperTypeParameterSymbol.cs diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index 79782b70148af..7261cd47cb3ef 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -726,7 +726,13 @@ - + + + + + + + diff --git a/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs index 2c7fcba1471fd..0ac8db01c09d3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs @@ -428,7 +428,7 @@ public override int GetHashCode() return _reducedFrom.GetHashCode(); } - private sealed class ReducedExtensionMethodParameterSymbol : WrappedParameterSymbol + private sealed class ReducedExtensionMethodParameterSymbol : WrapperParameterSymbol { private readonly ReducedExtensionMethodSymbol _containingMethod; @@ -446,21 +446,44 @@ public override Symbol ContainingSymbol public override int Ordinal { - get { return this.underlyingParameter.Ordinal - 1; } + get { return this._underlyingParameter.Ordinal - 1; } } public override TypeSymbol Type { - get { return _containingMethod._typeMap.SubstituteType(this.underlyingParameter.Type).Type; } + get { return _containingMethod._typeMap.SubstituteType(this._underlyingParameter.Type).Type; } } public override ImmutableArray CustomModifiers { get { - return _containingMethod._typeMap.SubstituteCustomModifiers(this.underlyingParameter.Type, this.underlyingParameter.CustomModifiers); + return _containingMethod._typeMap.SubstituteCustomModifiers(this._underlyingParameter.Type, this._underlyingParameter.CustomModifiers); } } + + public sealed override bool Equals(object obj) + { + if ((object)this == obj) + { + return true; + } + + // Equality of ordinal and containing symbol is a correct + // implementation for all ParameterSymbols, but we don't + // define it on the base type because most can simply use + // ReferenceEquals. + + var other = obj as ReducedExtensionMethodParameterSymbol; + return (object)other != null && + this.Ordinal == other.Ordinal && + this.ContainingSymbol.Equals(other.ContainingSymbol); + } + + public sealed override int GetHashCode() + { + return Hash.Combine(ContainingSymbol, _underlyingParameter.Ordinal); + } } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs index c6364ce4efa17..7b0e2a4acf175 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs @@ -14,31 +14,25 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting { - internal sealed class RetargetingEventSymbol : EventSymbol + internal sealed class RetargetingEventSymbol : WrapperEventSymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying EventSymbol, cannot be another RetargetingEventSymbol. - /// - private readonly EventSymbol _underlyingEvent; - //we want to compute this lazily since it may be expensive for the underlying symbol private ImmutableArray _lazyExplicitInterfaceImplementations; private DiagnosticInfo _lazyUseSiteDiagnostic = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. public RetargetingEventSymbol(RetargetingModuleSymbol retargetingModule, EventSymbol underlyingEvent) + : base(underlyingEvent) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingEvent != null); Debug.Assert(!(underlyingEvent is RetargetingEventSymbol)); _retargetingModule = retargetingModule; - _underlyingEvent = underlyingEvent; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -49,30 +43,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public EventSymbol UnderlyingEvent - { - get - { - return _underlyingEvent; - } - } - - public override bool IsImplicitlyDeclared - { - get - { - return _underlyingEvent.IsImplicitlyDeclared; - } - } - - internal override bool HasSpecialName - { - get - { - return _underlyingEvent.HasSpecialName; - } - } - public override TypeSymbol Type { get @@ -180,99 +150,6 @@ internal override ModuleSymbol ContainingModule } } - public override string Name - { - get - { - return _underlyingEvent.Name; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingEvent.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - public override ImmutableArray Locations - { - get - { - return _underlyingEvent.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _underlyingEvent.DeclaringSyntaxReferences; - } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _underlyingEvent.DeclaredAccessibility; - } - } - - public override bool IsStatic - { - get - { - return _underlyingEvent.IsStatic; - } - } - - public override bool IsVirtual - { - get - { - return _underlyingEvent.IsVirtual; - } - } - - public override bool IsOverride - { - get - { - return _underlyingEvent.IsOverride; - } - } - - public override bool IsAbstract - { - get - { - return _underlyingEvent.IsAbstract; - } - } - - public override bool IsSealed - { - get - { - return _underlyingEvent.IsSealed; - } - } - - public override bool IsExtern - { - get - { - return _underlyingEvent.IsExtern; - } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return _underlyingEvent.ObsoleteAttributeData; - } - } - public override ImmutableArray GetAttributes() { return _underlyingEvent.GetAttributes(); @@ -303,22 +180,6 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() return _lazyUseSiteDiagnostic; } - public override bool IsWindowsRuntimeEvent - { - get - { - return _underlyingEvent.IsWindowsRuntimeEvent; - } - } - - internal override bool HasRuntimeSpecialName - { - get - { - return _underlyingEvent.HasRuntimeSpecialName; - } - } - internal sealed override CSharpCompilation DeclaringCompilation // perf, not correctness { get { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs index 8b085d63386d2..d8c2b86489285 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs @@ -19,18 +19,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting /// another FieldSymbol that is responsible for retargeting symbols from one assembly to another. /// It can retarget symbols for multiple assemblies at the same time. /// - internal sealed class RetargetingFieldSymbol : FieldSymbol + internal sealed class RetargetingFieldSymbol : WrapperFieldSymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying FieldSymbol, cannot be another RetargetingFieldSymbol. - /// - private readonly FieldSymbol _underlyingField; - private ImmutableArray _lazyCustomModifiers; /// @@ -41,13 +36,12 @@ internal sealed class RetargetingFieldSymbol : FieldSymbol private DiagnosticInfo _lazyUseSiteDiagnostic = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. public RetargetingFieldSymbol(RetargetingModuleSymbol retargetingModule, FieldSymbol underlyingField) + : base (underlyingField) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingField != null); Debug.Assert(!(underlyingField is RetargetingFieldSymbol)); _retargetingModule = retargetingModule; - _underlyingField = underlyingField; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -58,14 +52,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public FieldSymbol UnderlyingField - { - get - { - return _underlyingField; - } - } - public RetargetingModuleSymbol RetargetingModule { get @@ -74,11 +60,6 @@ public RetargetingModuleSymbol RetargetingModule } } - public override bool IsImplicitlyDeclared - { - get { return _underlyingField.IsImplicitlyDeclared; } - } - internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound) { return this.RetargetingTranslator.Retarget(_underlyingField.GetFieldType(fieldsBeingBound), RetargetOptions.RetargetPrimitiveTypesByTypeCode); @@ -100,14 +81,6 @@ public override Symbol ContainingSymbol } } - public override Accessibility DeclaredAccessibility - { - get - { - return _underlyingField.DeclaredAccessibility; - } - } - public override ImmutableArray GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingField.GetAttributes(), ref _lazyCustomAttributes); @@ -134,51 +107,6 @@ internal override ModuleSymbol ContainingModule } } - public override string Name - { - get - { - return _underlyingField.Name; - } - } - - internal override bool HasSpecialName - { - get - { - return _underlyingField.HasSpecialName; - } - } - - internal override bool HasRuntimeSpecialName - { - get - { - return _underlyingField.HasRuntimeSpecialName; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingField.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal override bool IsNotSerialized - { - get - { - return _underlyingField.IsNotSerialized; - } - } - - internal override bool IsMarshalledExplicitly - { - get - { - return _underlyingField.IsMarshalledExplicitly; - } - } - internal override MarshalPseudoCustomAttributeData MarshallingInformation { get @@ -187,22 +115,6 @@ internal override MarshalPseudoCustomAttributeData MarshallingInformation } } - internal override ImmutableArray MarshallingDescriptor - { - get - { - return _underlyingField.MarshallingDescriptor; - } - } - - internal override int? TypeLayoutOffset - { - get - { - return _underlyingField.TypeLayoutOffset; - } - } - public override Symbol AssociatedSymbol { get @@ -212,75 +124,6 @@ public override Symbol AssociatedSymbol } } - public override bool IsReadOnly - { - get - { - return _underlyingField.IsReadOnly; - } - } - - public override bool IsVolatile - { - get - { - return _underlyingField.IsVolatile; - } - } - - public override bool IsConst - { - get - { - return _underlyingField.IsConst; - } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return _underlyingField.ObsoleteAttributeData; - } - } - - public override object ConstantValue - { - get - { - return _underlyingField.ConstantValue; - } - } - - internal override ConstantValue GetConstantValue(ConstantFieldsInProgress inProgress, bool earlyDecodingWellKnownAttributes) - { - return _underlyingField.GetConstantValue(inProgress, earlyDecodingWellKnownAttributes); - } - - public override ImmutableArray Locations - { - get - { - return _underlyingField.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _underlyingField.DeclaringSyntaxReferences; - } - } - - public override bool IsStatic - { - get - { - return _underlyingField.IsStatic; - } - } - internal override DiagnosticInfo GetUseSiteDiagnostic() { if (ReferenceEquals(_lazyUseSiteDiagnostic, CSDiagnosticInfo.EmptyErrorInfo)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs index cff89b9b4c82d..eac7cbac4386d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs @@ -19,18 +19,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting /// another MethodSymbol that is responsible for retargeting symbols from one assembly to another. /// It can retarget symbols for multiple assemblies at the same time. /// - internal sealed class RetargetingMethodSymbol : MethodSymbol + internal sealed class RetargetingMethodSymbol : WrapperMethodSymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying MethodSymbol, cannot be another RetargetingMethodSymbol. - /// - private readonly MethodSymbol _underlyingMethod; - private ImmutableArray _lazyTypeParameters; private ImmutableArray _lazyParameters; @@ -53,13 +48,12 @@ internal sealed class RetargetingMethodSymbol : MethodSymbol private TypeSymbol _lazyReturnType; public RetargetingMethodSymbol(RetargetingModuleSymbol retargetingModule, MethodSymbol underlyingMethod) + : base(underlyingMethod) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingMethod != null); Debug.Assert(!(underlyingMethod is RetargetingMethodSymbol)); _retargetingModule = retargetingModule; - _underlyingMethod = underlyingMethod; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -70,14 +64,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public MethodSymbol UnderlyingMethod - { - get - { - return _underlyingMethod; - } - } - public RetargetingModuleSymbol RetargetingModule { get @@ -86,30 +72,6 @@ public RetargetingModuleSymbol RetargetingModule } } - public override bool IsVararg - { - get - { - return _underlyingMethod.IsVararg; - } - } - - public override bool IsGenericMethod - { - get - { - return _underlyingMethod.IsGenericMethod; - } - } - - public override int Arity - { - get - { - return _underlyingMethod.Arity; - } - } - public override ImmutableArray TypeParameters { get @@ -154,14 +116,6 @@ public override bool ReturnsVoid } } - internal override RefKind RefKind - { - get - { - return _underlyingMethod.RefKind; - } - } - public override TypeSymbol ReturnType { get @@ -185,11 +139,6 @@ public override ImmutableArray ReturnTypeCustomModifiers } } - internal override int ParameterCount - { - get { return _underlyingMethod.ParameterCount; } - } - public override ImmutableArray Parameters { get @@ -234,22 +183,6 @@ public override Symbol AssociatedSymbol } } - public override bool IsExtensionMethod - { - get - { - return _underlyingMethod.IsExtensionMethod; - } - } - - public override bool HidesBaseMethodsByName - { - get - { - return _underlyingMethod.HidesBaseMethodsByName; - } - } - public override Symbol ContainingSymbol { get @@ -258,125 +191,6 @@ public override Symbol ContainingSymbol } } - public override ImmutableArray Locations - { - get - { - return _underlyingMethod.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _underlyingMethod.DeclaringSyntaxReferences; - } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _underlyingMethod.DeclaredAccessibility; - } - } - - public override bool IsStatic - { - get - { - return _underlyingMethod.IsStatic; - } - } - - public override bool IsVirtual - { - get - { - return _underlyingMethod.IsVirtual; - } - } - - public override bool IsAsync - { - get - { - return _underlyingMethod.IsAsync; - } - } - - public override bool IsOverride - { - get - { - return _underlyingMethod.IsOverride; - } - } - - public override bool IsAbstract - { - get - { - return _underlyingMethod.IsAbstract; - } - } - - public override bool IsSealed - { - get - { - return _underlyingMethod.IsSealed; - } - } - - public override bool IsExtern - { - get - { - return _underlyingMethod.IsExtern; - } - } - - public override bool IsImplicitlyDeclared - { - get - { - return _underlyingMethod.IsImplicitlyDeclared; - } - } - - internal sealed override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) - { - return _underlyingMethod.IsMetadataVirtual(ignoreInterfaceImplementationChanges); - } - - internal override bool IsMetadataFinal - { - get - { - return _underlyingMethod.IsMetadataFinal; - } - } - - internal sealed override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) - { - return _underlyingMethod.IsMetadataNewSlot(ignoreInterfaceImplementationChanges); - } - - internal override bool RequiresSecurityObject - { - get - { - return _underlyingMethod.RequiresSecurityObject; - } - } - - public override DllImportData GetDllImportData() - { - return _underlyingMethod.GetDllImportData(); - } - internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation { get @@ -385,21 +199,6 @@ internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInforma } } - internal override bool HasDeclarativeSecurity - { - get { return _underlyingMethod.HasDeclarativeSecurity; } - } - - internal override IEnumerable GetSecurityInformation() - { - return _underlyingMethod.GetSecurityInformation(); - } - - internal override ImmutableArray GetAppliedConditionalSymbols() - { - return _underlyingMethod.GetAppliedConditionalSymbols(); - } - public override ImmutableArray GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingMethod.GetAttributes(), ref _lazyCustomAttributes); @@ -416,14 +215,6 @@ public override ImmutableArray GetReturnTypeAttributes() return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingMethod.GetReturnTypeAttributes(), ref _lazyReturnTypeCustomAttributes); } - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return _underlyingMethod.ObsoleteAttributeData; - } - } - public override AssemblySymbol ContainingAssembly { get @@ -440,51 +231,6 @@ internal override ModuleSymbol ContainingModule } } - public override string Name - { - get - { - return _underlyingMethod.Name; - } - } - - internal override bool HasSpecialName - { - get - { - return _underlyingMethod.HasSpecialName; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingMethod.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal override System.Reflection.MethodImplAttributes ImplementationAttributes - { - get - { - return _underlyingMethod.ImplementationAttributes; - } - } - - public override MethodKind MethodKind - { - get - { - return _underlyingMethod.MethodKind; - } - } - - internal override Microsoft.Cci.CallingConvention CallingConvention - { - get - { - return _underlyingMethod.CallingConvention; - } - } - internal override bool IsExplicitInterfaceImplementation { get { return _underlyingMethod.IsExplicitInterfaceImplementation; } @@ -542,47 +288,6 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() return _lazyUseSiteDiagnostic; } - internal override bool IsAccessCheckedOnOverride - { - get - { - return _underlyingMethod.IsAccessCheckedOnOverride; - } - } - - internal override bool IsExternal - { - get - { - return _underlyingMethod.IsExternal; - } - } - - internal override bool HasRuntimeSpecialName - { - get - { - return _underlyingMethod.HasRuntimeSpecialName; - } - } - - - internal override bool ReturnValueIsMarshalledExplicitly - { - get - { - return _underlyingMethod.ReturnValueIsMarshalledExplicitly; - } - } - - internal override ImmutableArray ReturnValueMarshallingDescriptor - { - get - { - return _underlyingMethod.ReturnValueMarshallingDescriptor; - } - } - internal sealed override CSharpCompilation DeclaringCompilation // perf, not correctness { get { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index 044ceb244b89d..f52e778244148 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -20,18 +20,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting /// another NamedTypeSymbol that is responsible for retargeting referenced symbols from one assembly to another. /// It can retarget symbols for multiple assemblies at the same time. /// - internal sealed class RetargetingNamedTypeSymbol : NamedTypeSymbol + internal sealed class RetargetingNamedTypeSymbol : WrapperNamedTypeSymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying NamedTypeSymbol, cannot be another RetargetingNamedTypeSymbol. - /// - private readonly NamedTypeSymbol _underlyingType; - private ImmutableArray _lazyTypeParameters; private NamedTypeSymbol _lazyBaseType = ErrorTypeSymbol.UnknownResultType; @@ -45,13 +40,12 @@ internal sealed class RetargetingNamedTypeSymbol : NamedTypeSymbol private DiagnosticInfo _lazyUseSiteDiagnostic = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. public RetargetingNamedTypeSymbol(RetargetingModuleSymbol retargetingModule, NamedTypeSymbol underlyingType) + : base(underlyingType) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingType != null); Debug.Assert(!(underlyingType is RetargetingNamedTypeSymbol)); _retargetingModule = retargetingModule; - _underlyingType = underlyingType; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -62,27 +56,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public NamedTypeSymbol UnderlyingNamedType - { - get - { - return _underlyingType; - } - } - - public override bool IsImplicitlyDeclared - { - get { return _underlyingType.IsImplicitlyDeclared; } - } - - public override int Arity - { - get - { - return _underlyingType.Arity; - } - } - public override ImmutableArray TypeParameters { get @@ -153,50 +126,6 @@ public override NamedTypeSymbol EnumUnderlyingType } } - public override bool MightContainExtensionMethods - { - get - { - return _underlyingType.MightContainExtensionMethods; - } - } - - public override string Name - { - get - { - return _underlyingType.Name; - } - } - - public override string MetadataName - { - get - { - return _underlyingType.MetadataName; - } - } - internal override bool HasSpecialName - { - get - { - return _underlyingType.HasSpecialName; - } - } - - internal override bool MangleName - { - get - { - return _underlyingType.MangleName; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingType.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - public override IEnumerable MemberNames { get @@ -299,30 +228,6 @@ public override ImmutableArray GetTypeMembers(string name, int return this.RetargetingTranslator.Retarget(_underlyingType.GetTypeMembers(name, arity)); } - public override Accessibility DeclaredAccessibility - { - get - { - return _underlyingType.DeclaredAccessibility; - } - } - - public override TypeKind TypeKind - { - get - { - return _underlyingType.TypeKind; - } - } - - internal override bool IsInterface - { - get - { - return _underlyingType.IsInterface; - } - } - public override Symbol ContainingSymbol { get @@ -331,62 +236,6 @@ public override Symbol ContainingSymbol } } - public override ImmutableArray Locations - { - get - { - return _underlyingType.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _underlyingType.DeclaringSyntaxReferences; - } - } - - public override bool IsStatic - { - get - { - return _underlyingType.IsStatic; - } - } - - public override bool IsAbstract - { - get - { - return _underlyingType.IsAbstract; - } - } - - internal override bool IsMetadataAbstract - { - get - { - return _underlyingType.IsMetadataAbstract; - } - } - - public override bool IsSealed - { - get - { - return _underlyingType.IsSealed; - } - } - - internal override bool IsMetadataSealed - { - get - { - return _underlyingType.IsMetadataSealed; - } - } - public override ImmutableArray GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingType.GetAttributes(), ref _lazyCustomAttributes); @@ -526,64 +375,9 @@ internal override bool IsComImport get { return _underlyingType.IsComImport; } } - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get { return _underlyingType.ObsoleteAttributeData; } - } - - internal override bool ShouldAddWinRTMembers - { - get { return _underlyingType.ShouldAddWinRTMembers; } - } - - internal override bool IsWindowsRuntimeImport - { - get { return _underlyingType.IsWindowsRuntimeImport; } - } - - internal override TypeLayout Layout - { - get { return _underlyingType.Layout; } - } - - internal override CharSet MarshallingCharSet - { - get { return _underlyingType.MarshallingCharSet; } - } - - internal override bool IsSerializable - { - get { return _underlyingType.IsSerializable; } - } - - internal override bool HasDeclarativeSecurity - { - get { return _underlyingType.HasDeclarativeSecurity; } - } - - internal override IEnumerable GetSecurityInformation() - { - return _underlyingType.GetSecurityInformation(); - } - - internal override ImmutableArray GetAppliedConditionalSymbols() - { - return _underlyingType.GetAppliedConditionalSymbols(); - } - - internal override AttributeUsageInfo GetAttributeUsageInfo() - { - return _underlyingType.GetAttributeUsageInfo(); - } - internal sealed override CSharpCompilation DeclaringCompilation // perf, not correctness { get { return null; } } - - internal override bool GetGuidString(out string guidString) - { - return _underlyingType.GetGuidString(out guidString); - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs index cb28b41fa1406..13b796a00cb3e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs @@ -15,9 +15,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting /// another ParameterSymbol that is responsible for retargeting symbols from one assembly to another. /// It can retarget symbols for multiple assemblies at the same time. /// - internal abstract class RetargetingParameterSymbol : ParameterSymbol + internal abstract class RetargetingParameterSymbol : WrapperParameterSymbol { - private readonly ParameterSymbol _underlyingParameter; private ImmutableArray _lazyCustomModifiers; /// @@ -26,18 +25,9 @@ internal abstract class RetargetingParameterSymbol : ParameterSymbol private ImmutableArray _lazyCustomAttributes; protected RetargetingParameterSymbol(ParameterSymbol underlyingParameter) + : base(underlyingParameter) { Debug.Assert(!(underlyingParameter is RetargetingParameterSymbol)); - _underlyingParameter = underlyingParameter; - } - - // test only - internal ParameterSymbol UnderlyingParameter - { - get - { - return _underlyingParameter; - } } protected abstract RetargetingModuleSymbol RetargetingModule @@ -133,115 +123,6 @@ internal override ImmutableArray MarshallingDescriptor { get { return null; } } - - #region Forwarded - - internal sealed override ConstantValue ExplicitDefaultConstantValue - { - get { return _underlyingParameter.ExplicitDefaultConstantValue; } - } - - public sealed override RefKind RefKind - { - get { return _underlyingParameter.RefKind; } - } - - internal sealed override bool IsMetadataIn - { - get { return _underlyingParameter.IsMetadataIn; } - } - - internal sealed override bool IsMetadataOut - { - get { return _underlyingParameter.IsMetadataOut; } - } - - public sealed override ImmutableArray Locations - { - get { return _underlyingParameter.Locations; } - } - - public sealed override ImmutableArray DeclaringSyntaxReferences - { - get { return _underlyingParameter.DeclaringSyntaxReferences; } - } - - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) - { - _underlyingParameter.AddSynthesizedAttributes(compilationState, ref attributes); - } - - public override int Ordinal - { - get { return _underlyingParameter.Ordinal; } - } - - public override bool IsParams - { - get { return _underlyingParameter.IsParams; } - } - - internal override bool IsMetadataOptional - { - get { return _underlyingParameter.IsMetadataOptional; } - } - - public override bool IsImplicitlyDeclared - { - get { return _underlyingParameter.IsImplicitlyDeclared; } - } - - public sealed override string Name - { - get { return _underlyingParameter.Name; } - } - - public sealed override string MetadataName - { - get { return _underlyingParameter.MetadataName; } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingParameter.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal sealed override UnmanagedType MarshallingType - { - get { return _underlyingParameter.MarshallingType; } - } - - internal sealed override bool IsIDispatchConstant - { - get { return _underlyingParameter.IsIDispatchConstant; } - } - - internal sealed override bool IsIUnknownConstant - { - get { return _underlyingParameter.IsIUnknownConstant; } - } - - internal sealed override bool IsCallerLineNumber - { - get { return _underlyingParameter.IsCallerLineNumber; } - } - - internal sealed override bool IsCallerFilePath - { - get { return _underlyingParameter.IsCallerFilePath; } - } - - internal sealed override bool IsCallerMemberName - { - get { return _underlyingParameter.IsCallerMemberName; } - } - - internal sealed override ushort CountOfCustomModifiersPrecedingByRef - { - get { return _underlyingParameter.CountOfCustomModifiersPrecedingByRef; } - } - - #endregion } internal sealed class RetargetingMethodParameterSymbol : RetargetingParameterSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs index b3a81de284993..5ed4112b4444c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs @@ -14,18 +14,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting { - internal sealed class RetargetingPropertySymbol : PropertySymbol + internal sealed class RetargetingPropertySymbol : WrapperPropertySymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying PropertySymbol, cannot be another RetargetingPropertySymbol. - /// - private readonly PropertySymbol _underlyingProperty; - //we want to compute this lazily since it may be expensive for the underlying symbol private ImmutableArray _lazyExplicitInterfaceImplementations; private ImmutableArray _lazyParameters; @@ -41,13 +36,12 @@ internal sealed class RetargetingPropertySymbol : PropertySymbol private TypeSymbol _lazyType; public RetargetingPropertySymbol(RetargetingModuleSymbol retargetingModule, PropertySymbol underlyingProperty) + : base(underlyingProperty) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingProperty != null); Debug.Assert(!(underlyingProperty is RetargetingPropertySymbol)); _retargetingModule = retargetingModule; - _underlyingProperty = underlyingProperty; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -58,19 +52,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public PropertySymbol UnderlyingProperty - { - get - { - return _underlyingProperty; - } - } - - public override bool IsImplicitlyDeclared - { - get { return _underlyingProperty.IsImplicitlyDeclared; } - } - public RetargetingModuleSymbol RetargetingModule { get @@ -79,14 +60,6 @@ public RetargetingModuleSymbol RetargetingModule } } - internal override RefKind RefKind - { - get - { - return _underlyingProperty.RefKind; - } - } - public override TypeSymbol Type { get @@ -145,14 +118,6 @@ private ImmutableArray RetargetParameters() } } - public override bool IsIndexer - { - get - { - return _underlyingProperty.IsIndexer; - } - } - public override MethodSymbol GetMethod { get @@ -173,14 +138,6 @@ public override MethodSymbol SetMethod } } - internal override Microsoft.Cci.CallingConvention CallingConvention - { - get - { - return _underlyingProperty.CallingConvention; - } - } - internal override bool IsExplicitInterfaceImplementation { get @@ -254,107 +211,6 @@ internal override ModuleSymbol ContainingModule } } - public override string Name - { - get - { - return _underlyingProperty.Name; - } - } - - internal override bool HasSpecialName - { - get - { - return _underlyingProperty.HasSpecialName; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingProperty.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - public override ImmutableArray Locations - { - get - { - return _underlyingProperty.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return this.UnderlyingProperty.DeclaringSyntaxReferences; - } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _underlyingProperty.DeclaredAccessibility; - } - } - - public override bool IsStatic - { - get - { - return _underlyingProperty.IsStatic; - } - } - - public override bool IsVirtual - { - get - { - return _underlyingProperty.IsVirtual; - } - } - - public override bool IsOverride - { - get - { - return _underlyingProperty.IsOverride; - } - } - - public override bool IsAbstract - { - get - { - return _underlyingProperty.IsAbstract; - } - } - - public override bool IsSealed - { - get - { - return _underlyingProperty.IsSealed; - } - } - - public override bool IsExtern - { - get - { - return _underlyingProperty.IsExtern; - } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return _underlyingProperty.ObsoleteAttributeData; - } - } - public override ImmutableArray GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingProperty.GetAttributes(), ref _lazyCustomAttributes); @@ -385,27 +241,6 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() return _lazyUseSiteDiagnostic; } - public override string MetadataName - { - // We'll never emit this symbol, so it doesn't really - // make sense for it to have a metadata name. However, all - // symbols have an implementation of MetadataName (since it - // is virtual on Symbol) so we might as well define it in a - // consistent way. - - get - { - return _underlyingProperty.MetadataName; - } - } - internal override bool HasRuntimeSpecialName - { - get - { - return _underlyingProperty.HasRuntimeSpecialName; - } - } - internal sealed override CSharpCompilation DeclaringCompilation // perf, not correctness { get { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.cs index d521b0c8ec76a..6eba3e3df2a56 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.cs @@ -19,31 +19,25 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting /// It can retarget symbols for multiple assemblies at the same time. /// internal sealed class RetargetingTypeParameterSymbol - : TypeParameterSymbol + : WrapperTypeParameterSymbol { /// /// Owning RetargetingModuleSymbol. /// private readonly RetargetingModuleSymbol _retargetingModule; - /// - /// The underlying TypeParameterSymbol, cannot be another RetargetingTypeParameterSymbol. - /// - private readonly TypeParameterSymbol _underlyingTypeParameter; - /// /// Retargeted custom attributes /// private ImmutableArray _lazyCustomAttributes; public RetargetingTypeParameterSymbol(RetargetingModuleSymbol retargetingModule, TypeParameterSymbol underlyingTypeParameter) + : base(underlyingTypeParameter) { Debug.Assert((object)retargetingModule != null); - Debug.Assert((object)underlyingTypeParameter != null); Debug.Assert(!(underlyingTypeParameter is RetargetingTypeParameterSymbol)); _retargetingModule = retargetingModule; - _underlyingTypeParameter = underlyingTypeParameter; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -54,67 +48,6 @@ private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslato } } - public TypeParameterSymbol UnderlyingTypeParameter - { - get - { - return _underlyingTypeParameter; - } - } - - public override bool IsImplicitlyDeclared - { - get { return _underlyingTypeParameter.IsImplicitlyDeclared; } - } - - public override TypeParameterKind TypeParameterKind - { - get - { - return _underlyingTypeParameter.TypeParameterKind; - } - } - - public override int Ordinal - { - get - { - return _underlyingTypeParameter.Ordinal; - } - } - - public override bool HasConstructorConstraint - { - get - { - return _underlyingTypeParameter.HasConstructorConstraint; - } - } - - public override bool HasReferenceTypeConstraint - { - get - { - return _underlyingTypeParameter.HasReferenceTypeConstraint; - } - } - - public override bool HasValueTypeConstraint - { - get - { - return _underlyingTypeParameter.HasValueTypeConstraint; - } - } - - public override VarianceKind Variance - { - get - { - return _underlyingTypeParameter.Variance; - } - } - public override Symbol ContainingSymbol { get @@ -123,22 +56,6 @@ public override Symbol ContainingSymbol } } - public override ImmutableArray Locations - { - get - { - return _underlyingTypeParameter.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _underlyingTypeParameter.DeclaringSyntaxReferences; - } - } - public override ImmutableArray GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingTypeParameter.GetAttributes(), ref _lazyCustomAttributes); @@ -160,24 +77,6 @@ internal override ModuleSymbol ContainingModule } } - public override string Name - { - get - { - return _underlyingTypeParameter.Name; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _underlyingTypeParameter.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal override void EnsureAllConstraintsAreResolved() - { - _underlyingTypeParameter.EnsureAllConstraintsAreResolved(); - } - internal override ImmutableArray GetConstraintTypes(ConsList inProgress) { return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetConstraintTypes(inProgress)); diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedEventSymbol.cs index 033ee2f8b33e2..4793542797a42 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedEventSymbol.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; +using System.Diagnostics; using System.Globalization; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; @@ -9,17 +10,17 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal sealed class SubstitutedEventSymbol : EventSymbol + internal sealed class SubstitutedEventSymbol : WrapperEventSymbol { - private readonly EventSymbol _originalDefinition; private readonly SubstitutedNamedTypeSymbol _containingType; private TypeSymbol _lazyType; internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition) + : base(originalDefinition) { + Debug.Assert(originalDefinition.IsDefinition); _containingType = containingType; - _originalDefinition = originalDefinition; } public override TypeSymbol Type @@ -28,31 +29,13 @@ public override TypeSymbol Type { if ((object)_lazyType == null) { - Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(_originalDefinition.Type).Type, null); + Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(OriginalDefinition.Type).Type, null); } return _lazyType; } } - public override string Name - { - get - { - return _originalDefinition.Name; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _originalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal override bool HasSpecialName - { - get { return _originalDefinition.HasSpecialName; } - } - public override Symbol ContainingSymbol { get @@ -65,82 +48,20 @@ public override EventSymbol OriginalDefinition { get { - return _originalDefinition; - } - } - - public override ImmutableArray Locations - { - get - { - return _originalDefinition.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _originalDefinition.DeclaringSyntaxReferences; + return _underlyingEvent; } } public override ImmutableArray GetAttributes() { - return _originalDefinition.GetAttributes(); - } - - public override bool IsStatic - { - get - { - return _originalDefinition.IsStatic; - } - } - - public override bool IsExtern - { - get { return _originalDefinition.IsExtern; } - } - - public override bool IsSealed - { - get { return _originalDefinition.IsSealed; } - } - - public override bool IsAbstract - { - get { return _originalDefinition.IsAbstract; } - } - - public override bool IsVirtual - { - get { return _originalDefinition.IsVirtual; } - } - - public override bool IsOverride - { - get { return _originalDefinition.IsOverride; } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get { return _originalDefinition.ObsoleteAttributeData; } - } - - public override bool IsImplicitlyDeclared - { - get - { - return _originalDefinition.IsImplicitlyDeclared; - } + return OriginalDefinition.GetAttributes(); } public override MethodSymbol AddMethod { get { - MethodSymbol originalAddMethod = _originalDefinition.AddMethod; + MethodSymbol originalAddMethod = OriginalDefinition.AddMethod; return (object)originalAddMethod == null ? null : originalAddMethod.AsMember(_containingType); } } @@ -149,7 +70,7 @@ public override MethodSymbol RemoveMethod { get { - MethodSymbol originalRemoveMethod = _originalDefinition.RemoveMethod; + MethodSymbol originalRemoveMethod = OriginalDefinition.RemoveMethod; return (object)originalRemoveMethod == null ? null : originalRemoveMethod.AsMember(_containingType); } } @@ -158,14 +79,14 @@ internal override FieldSymbol AssociatedField { get { - FieldSymbol originalAssociatedField = _originalDefinition.AssociatedField; + FieldSymbol originalAssociatedField = OriginalDefinition.AssociatedField; return (object)originalAssociatedField == null ? null : originalAssociatedField.AsMember(_containingType); } } internal override bool IsExplicitInterfaceImplementation { - get { return _originalDefinition.IsExplicitInterfaceImplementation; } + get { return OriginalDefinition.IsExplicitInterfaceImplementation; } } //we want to compute this lazily since it may be expensive for the underlying symbol @@ -181,7 +102,7 @@ public override ImmutableArray ExplicitInterfaceImplementations { ImmutableInterlocked.InterlockedCompareExchange( ref _lazyExplicitInterfaceImplementations, - ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(_originalDefinition.ExplicitInterfaceImplementations, _containingType.TypeSubstitution), + ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(OriginalDefinition.ExplicitInterfaceImplementations, _containingType.TypeSubstitution), default(ImmutableArray)); } return _lazyExplicitInterfaceImplementations; @@ -190,15 +111,7 @@ public override ImmutableArray ExplicitInterfaceImplementations internal override bool MustCallMethodsDirectly { - get { return _originalDefinition.MustCallMethodsDirectly; } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _originalDefinition.DeclaredAccessibility; - } + get { return OriginalDefinition.MustCallMethodsDirectly; } } internal override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembers @@ -221,7 +134,7 @@ public override bool IsWindowsRuntimeEvent // from the original definition, in case the type has changed. However, is should // never be the case that providing type arguments changes a WinRT event to a // non-WinRT event or vice versa, so we'll delegate to the original definition. - return _originalDefinition.IsWindowsRuntimeEvent; + return OriginalDefinition.IsWindowsRuntimeEvent; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedFieldSymbol.cs index d4a04bef03359..d3c64e1a98dd1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedFieldSymbol.cs @@ -12,82 +12,27 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal sealed class SubstitutedFieldSymbol : FieldSymbol + internal sealed class SubstitutedFieldSymbol : WrapperFieldSymbol { private readonly SubstitutedNamedTypeSymbol _containingType; - private readonly FieldSymbol _originalDefinition; - private TypeSymbol _lazyType; internal SubstitutedFieldSymbol(SubstitutedNamedTypeSymbol containingType, FieldSymbol substitutedFrom) + : base((FieldSymbol)substitutedFrom.OriginalDefinition) { _containingType = containingType; - _originalDefinition = substitutedFrom.OriginalDefinition as FieldSymbol; } internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound) { if ((object)_lazyType == null) { - Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(_originalDefinition.GetFieldType(fieldsBeingBound)).Type, null); + Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(OriginalDefinition.GetFieldType(fieldsBeingBound)).Type, null); } return _lazyType; } - public override string Name - { - get - { - return _originalDefinition.Name; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _originalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal override bool HasSpecialName - { - get - { - return _originalDefinition.HasSpecialName; - } - } - - internal override bool HasRuntimeSpecialName - { - get - { - return _originalDefinition.HasRuntimeSpecialName; - } - } - - internal override bool IsNotSerialized - { - get - { - return _originalDefinition.IsNotSerialized; - } - } - - internal override MarshalPseudoCustomAttributeData MarshallingInformation - { - get - { - return _originalDefinition.MarshallingInformation; - } - } - - internal override int? TypeLayoutOffset - { - get - { - return _originalDefinition.TypeLayoutOffset; - } - } - public override Symbol ContainingSymbol { get @@ -108,36 +53,20 @@ public override FieldSymbol OriginalDefinition { get { - return _originalDefinition.OriginalDefinition; - } - } - - public override ImmutableArray Locations - { - get - { - return _originalDefinition.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _originalDefinition.DeclaringSyntaxReferences; + return _underlyingField; } } public override ImmutableArray GetAttributes() { - return _originalDefinition.GetAttributes(); + return OriginalDefinition.GetAttributes(); } public override Symbol AssociatedSymbol { get { - Symbol underlying = _originalDefinition.AssociatedSymbol; + Symbol underlying = OriginalDefinition.AssociatedSymbol; if ((object)underlying == null) { @@ -148,80 +77,11 @@ public override Symbol AssociatedSymbol } } - public override bool IsStatic - { - get - { - return _originalDefinition.IsStatic; - } - } - - public override bool IsReadOnly - { - get - { - return _originalDefinition.IsReadOnly; - } - } - - public override bool IsConst - { - get - { - return _originalDefinition.IsConst; - } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return _originalDefinition.ObsoleteAttributeData; - } - } - - public override object ConstantValue - { - get - { - return _originalDefinition.ConstantValue; - } - } - - internal override ConstantValue GetConstantValue(ConstantFieldsInProgress inProgress, bool earlyDecodingWellKnownAttributes) - { - return _originalDefinition.GetConstantValue(inProgress, earlyDecodingWellKnownAttributes); - } - - public override bool IsVolatile - { - get - { - return _originalDefinition.IsVolatile; - } - } - - public override bool IsImplicitlyDeclared - { - get - { - return _originalDefinition.IsImplicitlyDeclared; - } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _originalDefinition.DeclaredAccessibility; - } - } - public override ImmutableArray CustomModifiers { get { - return _containingType.TypeSubstitution.SubstituteCustomModifiers(_originalDefinition.Type, _originalDefinition.CustomModifiers); + return _containingType.TypeSubstitution.SubstituteCustomModifiers(OriginalDefinition.Type, OriginalDefinition.CustomModifiers); } } @@ -231,7 +91,7 @@ internal override NamedTypeSymbol FixedImplementationType(PEModuleBuilder emitMo // containing a fixed-size buffer. Given the rarity there would be little // benefit to "optimizing" the performance of this by caching the // translated implementation type. - return (NamedTypeSymbol)_containingType.TypeSubstitution.SubstituteType(_originalDefinition.FixedImplementationType(emitModule)).Type; + return (NamedTypeSymbol)_containingType.TypeSubstitution.SubstituteType(OriginalDefinition.FixedImplementationType(emitModule)).Type; } public override bool Equals(object obj) @@ -242,12 +102,12 @@ public override bool Equals(object obj) } var other = obj as SubstitutedFieldSymbol; - return (object)other != null && _containingType == other._containingType && _originalDefinition == other._originalDefinition; + return (object)other != null && _containingType == other._containingType && OriginalDefinition == other.OriginalDefinition; } public override int GetHashCode() { - return Hash.Combine(_containingType, _originalDefinition.GetHashCode()); + return Hash.Combine(_containingType, OriginalDefinition.GetHashCode()); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs index 5b50063c730d6..a426a20a47003 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -19,10 +20,9 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols // C is a ConstructedTypeSymbol. // C.M<> is a SubstitutedMethodSymbol. It has parameters of types X and U. // C.M is a ConstructedMethodSymbol. - internal class SubstitutedMethodSymbol : MethodSymbol + internal class SubstitutedMethodSymbol : WrapperMethodSymbol { private readonly NamedTypeSymbol _containingType; - protected readonly MethodSymbol originalDefinition; private readonly TypeMap _inputMap; private readonly MethodSymbol _constructedFrom; @@ -43,10 +43,10 @@ internal SubstitutedMethodSymbol(SubstitutedNamedTypeSymbol containingSymbol, Me } protected SubstitutedMethodSymbol(NamedTypeSymbol containingSymbol, TypeMap map, MethodSymbol originalDefinition, MethodSymbol constructedFrom) + : base (originalDefinition) { Debug.Assert(originalDefinition.IsDefinition); _containingType = containingSymbol; - this.originalDefinition = originalDefinition; _inputMap = map; if ((object)constructedFrom != null) { @@ -69,11 +69,6 @@ public override MethodSymbol ConstructedFrom } } - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return originalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - private TypeMap Map { get @@ -103,114 +98,25 @@ private void EnsureMapAndTypeParameters() Debug.Assert(ReferenceEquals(_constructedFrom, this)); // We're creating a new unconstructed Method from another; alpha-rename type parameters. - var newMap = _inputMap.WithAlphaRename(this.originalDefinition, this, out typeParameters); + var newMap = _inputMap.WithAlphaRename(this.OriginalDefinition, this, out typeParameters); var prevMap = Interlocked.CompareExchange(ref _lazyMap, newMap, null); if (prevMap != null) { // There is a race with another thread who has already set the map // need to ensure that typeParameters, matches the map - typeParameters = prevMap.SubstituteTypeParameters(this.originalDefinition.TypeParameters); + typeParameters = prevMap.SubstituteTypeParameters(this.OriginalDefinition.TypeParameters); } ImmutableInterlocked.InterlockedCompareExchange(ref _lazyTypeParameters, typeParameters, default(ImmutableArray)); Debug.Assert(_lazyTypeParameters != null); } - internal sealed override Microsoft.Cci.CallingConvention CallingConvention - { - get - { - return originalDefinition.CallingConvention; - } - } - - public sealed override int Arity - { - get - { - return originalDefinition.Arity; - } - } - - public sealed override string Name - { - get - { - return originalDefinition.Name; - } - } - - internal sealed override bool HasSpecialName - { - get - { - return originalDefinition.HasSpecialName; - } - } - - internal sealed override System.Reflection.MethodImplAttributes ImplementationAttributes - { - get - { - return originalDefinition.ImplementationAttributes; - } - } - - internal sealed override bool RequiresSecurityObject - { - get - { - return originalDefinition.RequiresSecurityObject; - } - } - - public sealed override DllImportData GetDllImportData() - { - return originalDefinition.GetDllImportData(); - } - - internal sealed override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation - { - get { return originalDefinition.ReturnValueMarshallingInformation; } - } - - internal sealed override bool HasDeclarativeSecurity - { - get { return originalDefinition.HasDeclarativeSecurity; } - } - - internal sealed override IEnumerable GetSecurityInformation() - { - return originalDefinition.GetSecurityInformation(); - } - - internal sealed override ImmutableArray GetAppliedConditionalSymbols() - { - return originalDefinition.GetAppliedConditionalSymbols(); - } - public sealed override AssemblySymbol ContainingAssembly { get { - return originalDefinition.ContainingAssembly; - } - } - - public sealed override ImmutableArray Locations - { - get - { - return originalDefinition.Locations; - } - } - - public sealed override ImmutableArray DeclaringSyntaxReferences - { - get - { - return originalDefinition.DeclaringSyntaxReferences; + return OriginalDefinition.ContainingAssembly; } } @@ -226,79 +132,7 @@ public sealed override MethodSymbol OriginalDefinition { get { - return originalDefinition; - } - } - - public sealed override bool IsExtern - { - get - { - return originalDefinition.IsExtern; - } - } - - public sealed override bool IsSealed - { - get - { - return originalDefinition.IsSealed; - } - } - - public sealed override bool IsVirtual - { - get - { - return originalDefinition.IsVirtual; - } - } - - public sealed override bool IsAsync - { - get - { - return originalDefinition.IsAsync; - } - } - - public sealed override bool IsAbstract - { - get - { - return originalDefinition.IsAbstract; - } - } - - public sealed override bool IsOverride - { - get - { - return originalDefinition.IsOverride; - } - } - - public sealed override bool IsStatic - { - get - { - return originalDefinition.IsStatic; - } - } - - public sealed override bool IsExtensionMethod - { - get - { - return originalDefinition.IsExtensionMethod; - } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get - { - return originalDefinition.ObsoleteAttributeData; + return _underlyingMethod; } } @@ -306,7 +140,7 @@ internal sealed override MethodSymbol CallsiteReducedFromMethod { get { - var method = originalDefinition.ReducedFrom; + var method = OriginalDefinition.ReducedFrom; return ((object)method == null) ? null : method.Construct(this.TypeArguments); } } @@ -328,9 +162,9 @@ public override TypeSymbol ReceiverType public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter) { // This will throw if API shouldn't be supported or there is a problem with the argument. - var notUsed = originalDefinition.GetTypeInferredDuringReduction(reducedFromTypeParameter); + var notUsed = OriginalDefinition.GetTypeInferredDuringReduction(reducedFromTypeParameter); - Debug.Assert((object)notUsed == null && (object)originalDefinition.ReducedFrom != null); + Debug.Assert((object)notUsed == null && (object)OriginalDefinition.ReducedFrom != null); return this.TypeArguments[reducedFromTypeParameter.Ordinal]; } @@ -338,44 +172,10 @@ public sealed override MethodSymbol ReducedFrom { get { - return originalDefinition.ReducedFrom; - } - } - - public sealed override bool HidesBaseMethodsByName - { - get - { - return originalDefinition.HidesBaseMethodsByName; - } - } - - public sealed override Accessibility DeclaredAccessibility - { - get - { - return originalDefinition.DeclaredAccessibility; - } - } - - internal sealed override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) - { - return originalDefinition.IsMetadataVirtual(ignoreInterfaceImplementationChanges); - } - - internal override bool IsMetadataFinal - { - get - { - return originalDefinition.IsMetadataFinal; + return OriginalDefinition.ReducedFrom; } } - internal sealed override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) - { - return originalDefinition.IsMetadataNewSlot(ignoreInterfaceImplementationChanges); - } - public sealed override Symbol ContainingSymbol { get @@ -394,23 +194,20 @@ public override NamedTypeSymbol ContainingType public sealed override ImmutableArray GetAttributes() { - return this.originalDefinition.GetAttributes(); + return this.OriginalDefinition.GetAttributes(); } - public sealed override Symbol AssociatedSymbol + public override ImmutableArray GetReturnTypeAttributes() { - get - { - Symbol underlying = originalDefinition.AssociatedSymbol; - return ((object)underlying == null) ? null : underlying.SymbolAsMember(ContainingType); - } + return this.OriginalDefinition.GetReturnTypeAttributes(); } - public sealed override MethodKind MethodKind + public sealed override Symbol AssociatedSymbol { get { - return originalDefinition.MethodKind; + Symbol underlying = OriginalDefinition.AssociatedSymbol; + return ((object)underlying == null) ? null : underlying.SymbolAsMember(ContainingType); } } @@ -418,47 +215,7 @@ public sealed override bool ReturnsVoid { get { - return originalDefinition.ReturnsVoid; - } - } - - public sealed override bool IsGenericMethod - { - get - { - return originalDefinition.IsGenericMethod; - } - } - - public sealed override bool IsImplicitlyDeclared - { - get - { - return this.originalDefinition.IsImplicitlyDeclared; - } - } - - internal sealed override bool GenerateDebugInfo - { - get - { - return this.originalDefinition.GenerateDebugInfo; - } - } - - public sealed override bool IsVararg - { - get - { - return originalDefinition.IsVararg; - } - } - - internal sealed override RefKind RefKind - { - get - { - return originalDefinition.RefKind; + return OriginalDefinition.ReturnsVoid; } } @@ -472,7 +229,7 @@ public sealed override TypeSymbol ReturnType return returnType; } - returnType = Map.SubstituteType(originalDefinition.ReturnType).Type; + returnType = Map.SubstituteType(OriginalDefinition.ReturnType).Type; return Interlocked.CompareExchange(ref _lazyReturnType, returnType, null) ?? returnType; } } @@ -481,15 +238,10 @@ public sealed override ImmutableArray ReturnTypeCustomModifiers { get { - return Map.SubstituteCustomModifiers(originalDefinition.ReturnType, originalDefinition.ReturnTypeCustomModifiers); + return Map.SubstituteCustomModifiers(OriginalDefinition.ReturnType, OriginalDefinition.ReturnTypeCustomModifiers); } } - internal sealed override int ParameterCount - { - get { return this.originalDefinition.ParameterCount; } - } - public sealed override ImmutableArray Parameters { get @@ -505,7 +257,7 @@ public sealed override ImmutableArray Parameters internal sealed override bool IsExplicitInterfaceImplementation { - get { return this.originalDefinition.IsExplicitInterfaceImplementation; } + get { return this.OriginalDefinition.IsExplicitInterfaceImplementation; } } public sealed override ImmutableArray ExplicitInterfaceImplementations @@ -521,7 +273,7 @@ public sealed override ImmutableArray ExplicitInterfaceImplementat { ImmutableInterlocked.InterlockedCompareExchange( ref _lazyExplicitInterfaceImplementations, - ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(this.originalDefinition.ExplicitInterfaceImplementations, Map), + ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(this.OriginalDefinition.ExplicitInterfaceImplementations, Map), default(ImmutableArray)); } return _lazyExplicitInterfaceImplementations; @@ -545,7 +297,7 @@ internal sealed override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembe internal sealed override bool CallsAreOmitted(SyntaxTree syntaxTree) { - return originalDefinition.CallsAreOmitted(syntaxTree); + return OriginalDefinition.CallsAreOmitted(syntaxTree); } internal sealed override TypeMap TypeSubstitution @@ -561,7 +313,7 @@ internal sealed override bool TryGetThisParameter(out ParameterSymbol thisParame // There should never be any reason to call this in normal compilation // scenarios, but the behavior should be sensible if it does occur. ParameterSymbol originalThisParameter; - if (!originalDefinition.TryGetThisParameter(out originalThisParameter)) + if (!OriginalDefinition.TryGetThisParameter(out originalThisParameter)) { thisParameter = null; return false; @@ -575,7 +327,7 @@ internal sealed override bool TryGetThisParameter(out ParameterSymbol thisParame private ImmutableArray SubstituteParameters() { - var unsubstitutedParameters = originalDefinition.Parameters; + var unsubstitutedParameters = OriginalDefinition.Parameters; int count = unsubstitutedParameters.Length; if (count == 0) diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index 87f96046cc66b..c6721469eb88f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -19,12 +19,11 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols /// Either a SubstitutedNestedTypeSymbol or a ConstructedNamedTypeSymbol, which share in common that they /// have type parameters substituted. /// - internal abstract class SubstitutedNamedTypeSymbol : NamedTypeSymbol + internal abstract class SubstitutedNamedTypeSymbol : WrapperNamedTypeSymbol { private static readonly Func s_symbolAsMemberFunc = SymbolExtensions.SymbolAsMember; private readonly bool _unbound; - private readonly NamedTypeSymbol _originalDefinition; private readonly TypeMap _inputMap; // The container of a substituted named type symbol is typically a named type or a namespace. @@ -45,9 +44,9 @@ internal abstract class SubstitutedNamedTypeSymbol : NamedTypeSymbol private ConcurrentCache> _lazyMembersByNameCache; protected SubstitutedNamedTypeSymbol(Symbol newContainer, TypeMap map, NamedTypeSymbol originalDefinition, NamedTypeSymbol constructedFrom = null, bool unbound = false) + : base(originalDefinition) { Debug.Assert(originalDefinition.IsDefinition); - _originalDefinition = originalDefinition; _newContainer = newContainer; _inputMap = map; _unbound = unbound; @@ -98,14 +97,14 @@ private void EnsureMapAndTypeParameters() ImmutableArray typeParameters; // We're creating a new unconstructed Method from another; alpha-rename type parameters. - var newMap = _inputMap.WithAlphaRename(_originalDefinition, this, out typeParameters); + var newMap = _inputMap.WithAlphaRename(OriginalDefinition, this, out typeParameters); var prevMap = Interlocked.CompareExchange(ref _lazyMap, newMap, null); if (prevMap != null) { // There is a race with another thread who has already set the map // need to ensure that typeParameters, matches the map - typeParameters = prevMap.SubstituteTypeParameters(_originalDefinition.TypeParameters); + typeParameters = prevMap.SubstituteTypeParameters(OriginalDefinition.TypeParameters); } ImmutableInterlocked.InterlockedCompareExchange(ref _lazyTypeParameters, typeParameters, default(ImmutableArray)); @@ -125,77 +124,14 @@ public override NamedTypeSymbol ContainingType } } - public sealed override string Name - { - get { return _originalDefinition.Name; } - } - - internal sealed override bool MangleName - { - get { return _originalDefinition.MangleName; } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _originalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - - internal sealed override bool HasSpecialName - { - get { return _originalDefinition.HasSpecialName; } - } - - public sealed override int Arity - { - get { return _originalDefinition.Arity; } - } - - public sealed override Accessibility DeclaredAccessibility - { - get { return _originalDefinition.DeclaredAccessibility; } - } - - public sealed override ImmutableArray Locations - { - get { return _originalDefinition.Locations; } - } - - public sealed override ImmutableArray DeclaringSyntaxReferences - { - get { return _originalDefinition.DeclaringSyntaxReferences; } - } - public sealed override SymbolKind Kind { - get { return _originalDefinition.Kind; } + get { return OriginalDefinition.Kind; } } public sealed override NamedTypeSymbol OriginalDefinition { - get { return _originalDefinition; } - } - - public sealed override TypeKind TypeKind - { - get { return _originalDefinition.TypeKind; } - } - - internal sealed override bool IsInterface - { - get { return _originalDefinition.IsInterface; } - } - - public sealed override bool IsStatic - { - get { return _originalDefinition.IsStatic; } - } - - public sealed override bool IsImplicitlyDeclared - { - get - { - return _originalDefinition.IsImplicitlyDeclared; - } + get { return _underlyingType; } } internal sealed override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) @@ -238,48 +174,33 @@ public sealed override IEnumerable MemberNames { get { - return _unbound ? new List(GetTypeMembersUnordered().Select(s => s.Name).Distinct()) : _originalDefinition.MemberNames; + return _unbound ? new List(GetTypeMembersUnordered().Select(s => s.Name).Distinct()) : OriginalDefinition.MemberNames; } } - public sealed override bool IsSealed - { - get { return _originalDefinition.IsSealed; } - } - - public sealed override bool IsAbstract - { - get { return _originalDefinition.IsAbstract; } - } - public sealed override ImmutableArray GetAttributes() { - return _originalDefinition.GetAttributes(); - } - - public sealed override bool MightContainExtensionMethods - { - get { return _originalDefinition.MightContainExtensionMethods; } + return OriginalDefinition.GetAttributes(); } internal sealed override ImmutableArray GetTypeMembersUnordered() { - return _originalDefinition.GetTypeMembersUnordered().SelectAsArray((t, self) => t.AsMember(self), this); + return OriginalDefinition.GetTypeMembersUnordered().SelectAsArray((t, self) => t.AsMember(self), this); } public sealed override ImmutableArray GetTypeMembers() { - return _originalDefinition.GetTypeMembers().SelectAsArray((t, self) => t.AsMember(self), this); + return OriginalDefinition.GetTypeMembers().SelectAsArray((t, self) => t.AsMember(self), this); } public sealed override ImmutableArray GetTypeMembers(string name) { - return _originalDefinition.GetTypeMembers(name).SelectAsArray((t, self) => t.AsMember(self), this); + return OriginalDefinition.GetTypeMembers(name).SelectAsArray((t, self) => t.AsMember(self), this); } public sealed override ImmutableArray GetTypeMembers(string name, int arity) { - return _originalDefinition.GetTypeMembers(name, arity).SelectAsArray((t, self) => t.AsMember(self), this); + return OriginalDefinition.GetTypeMembers(name, arity).SelectAsArray((t, self) => t.AsMember(self), this); } public sealed override ImmutableArray GetMembers() @@ -289,7 +210,7 @@ public sealed override ImmutableArray GetMembers() if (_unbound) { // Preserve order of members. - foreach (var t in _originalDefinition.GetMembers()) + foreach (var t in OriginalDefinition.GetMembers()) { if (t.Kind == SymbolKind.NamedType) { @@ -299,7 +220,7 @@ public sealed override ImmutableArray GetMembers() } else { - foreach (var t in _originalDefinition.GetMembers()) + foreach (var t in OriginalDefinition.GetMembers()) { builder.Add(t.SymbolAsMember(this)); } @@ -314,7 +235,7 @@ internal sealed override ImmutableArray GetMembersUnordered() if (_unbound) { - foreach (var t in _originalDefinition.GetMembersUnordered()) + foreach (var t in OriginalDefinition.GetMembersUnordered()) { if (t.Kind == SymbolKind.NamedType) { @@ -324,7 +245,7 @@ internal sealed override ImmutableArray GetMembersUnordered() } else { - foreach (var t in _originalDefinition.GetMembersUnordered()) + foreach (var t in OriginalDefinition.GetMembersUnordered()) { builder.Add(t.SymbolAsMember(this)); } @@ -349,7 +270,7 @@ public sealed override ImmutableArray GetMembers(string name) private ImmutableArray GetMembersWorker(string name) { - var originalMembers = _originalDefinition.GetMembers(name); + var originalMembers = OriginalDefinition.GetMembers(name); if (originalMembers.IsDefaultOrEmpty) { return originalMembers; @@ -382,7 +303,7 @@ internal override ImmutableArray GetEarlyAttributeDecodingMembers() { return _unbound ? GetMembers() - : _originalDefinition.GetEarlyAttributeDecodingMembers().SelectAsArray(s_symbolAsMemberFunc, this); + : OriginalDefinition.GetEarlyAttributeDecodingMembers().SelectAsArray(s_symbolAsMemberFunc, this); } internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) @@ -390,7 +311,7 @@ internal override ImmutableArray GetEarlyAttributeDecodingMembers(string if (_unbound) return GetMembers(name); var builder = ArrayBuilder.GetInstance(); - foreach (var t in _originalDefinition.GetEarlyAttributeDecodingMembers(name)) + foreach (var t in OriginalDefinition.GetEarlyAttributeDecodingMembers(name)) { builder.Add(t.SymbolAsMember(this)); } @@ -402,7 +323,7 @@ public sealed override NamedTypeSymbol EnumUnderlyingType { get { - return _originalDefinition.EnumUnderlyingType; + return OriginalDefinition.EnumUnderlyingType; } } @@ -423,62 +344,32 @@ internal sealed override TypeMap TypeSubstitution internal sealed override bool IsComImport { - get { return _originalDefinition.IsComImport; } + get { return OriginalDefinition.IsComImport; } } internal sealed override NamedTypeSymbol ComImportCoClass { - get { return _originalDefinition.ComImportCoClass; } + get { return OriginalDefinition.ComImportCoClass; } } - internal sealed override bool ShouldAddWinRTMembers + internal override IEnumerable GetMethodsToEmit() { - get { return _originalDefinition.ShouldAddWinRTMembers; } - } - - internal sealed override bool IsWindowsRuntimeImport - { - get { return _originalDefinition.IsWindowsRuntimeImport; } - } - - internal sealed override TypeLayout Layout - { - get { return _originalDefinition.Layout; } - } - - internal override CharSet MarshallingCharSet - { - get { return _originalDefinition.MarshallingCharSet; } - } - - internal sealed override bool IsSerializable - { - get { return _originalDefinition.IsSerializable; } - } - - internal sealed override bool HasDeclarativeSecurity - { - get { return _originalDefinition.HasDeclarativeSecurity; } - } - - internal sealed override IEnumerable GetSecurityInformation() - { - return _originalDefinition.GetSecurityInformation(); + throw ExceptionUtilities.Unreachable; } - internal sealed override ImmutableArray GetAppliedConditionalSymbols() + internal override IEnumerable GetEventsToEmit() { - return _originalDefinition.GetAppliedConditionalSymbols(); + throw ExceptionUtilities.Unreachable; } - internal override ObsoleteAttributeData ObsoleteAttributeData + internal override IEnumerable GetPropertiesToEmit() { - get { return _originalDefinition.ObsoleteAttributeData; } + throw ExceptionUtilities.Unreachable; } - internal override AttributeUsageInfo GetAttributeUsageInfo() + internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) { - return _originalDefinition.GetAttributeUsageInfo(); + throw ExceptionUtilities.Unreachable; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedParameterSymbol.cs index 086698cebdae3..7d8c1487d6a8d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedParameterSymbol.cs @@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal sealed class SubstitutedParameterSymbol : WrappedParameterSymbol + internal sealed class SubstitutedParameterSymbol : WrapperParameterSymbol { // initially set to map which is only used to get the type, which is once computed is stored here. private object _mapOrType; @@ -34,7 +34,7 @@ internal sealed class SubstitutedParameterSymbol : WrappedParameterSymbol public override ParameterSymbol OriginalDefinition { - get { return underlyingParameter.OriginalDefinition; } + get { return _underlyingParameter.OriginalDefinition; } } public override Symbol ContainingSymbol @@ -53,7 +53,7 @@ public override TypeSymbol Type return type; } - TypeWithModifiers substituted = ((TypeMap)mapOrType).SubstituteType(this.underlyingParameter.Type); + TypeWithModifiers substituted = ((TypeMap)mapOrType).SubstituteType(this._underlyingParameter.Type); type = substituted.Type; @@ -71,13 +71,31 @@ public override ImmutableArray CustomModifiers get { var map = _mapOrType as TypeMap; - return map != null ? map.SubstituteCustomModifiers(this.underlyingParameter.Type, this.underlyingParameter.CustomModifiers) : this.underlyingParameter.CustomModifiers; + return map != null ? map.SubstituteCustomModifiers(this._underlyingParameter.Type, this._underlyingParameter.CustomModifiers) : this._underlyingParameter.CustomModifiers; } } - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + public sealed override bool Equals(object obj) { - return underlyingParameter.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + if ((object)this == obj) + { + return true; + } + + // Equality of ordinal and containing symbol is a correct + // implementation for all ParameterSymbols, but we don't + // define it on the base type because most can simply use + // ReferenceEquals. + + var other = obj as SubstitutedParameterSymbol; + return (object)other != null && + this.Ordinal == other.Ordinal && + this.ContainingSymbol.Equals(other.ContainingSymbol); + } + + public sealed override int GetHashCode() + { + return Roslyn.Utilities.Hash.Combine(ContainingSymbol, _underlyingParameter.Ordinal); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs index a5c38a3435984..4954747afe858 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs @@ -9,26 +9,17 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal sealed class SubstitutedPropertySymbol : PropertySymbol + internal sealed class SubstitutedPropertySymbol : WrapperPropertySymbol { - private readonly PropertySymbol _originalDefinition; private readonly SubstitutedNamedTypeSymbol _containingType; private TypeSymbol _lazyType; private ImmutableArray _lazyParameters; internal SubstitutedPropertySymbol(SubstitutedNamedTypeSymbol containingType, PropertySymbol originalDefinition) + : base(originalDefinition) { _containingType = containingType; - _originalDefinition = originalDefinition; - } - - internal override RefKind RefKind - { - get - { - return _originalDefinition.RefKind; - } } public override TypeSymbol Type @@ -37,34 +28,13 @@ public override TypeSymbol Type { if ((object)_lazyType == null) { - Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(_originalDefinition.Type).Type, null); + Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(OriginalDefinition.Type).Type, null); } return _lazyType; } } - public override string Name - { - get - { - return _originalDefinition.Name; - } - } - - internal override bool HasSpecialName - { - get - { - return _originalDefinition.HasSpecialName; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _originalDefinition.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - public override Symbol ContainingSymbol { get @@ -85,82 +55,18 @@ public override PropertySymbol OriginalDefinition { get { - return _originalDefinition; - } - } - - public override ImmutableArray Locations - { - get - { - return _originalDefinition.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _originalDefinition.DeclaringSyntaxReferences; + return _underlyingProperty; } } public override ImmutableArray GetAttributes() { - return _originalDefinition.GetAttributes(); - } - - public override bool IsStatic - { - get - { - return _originalDefinition.IsStatic; - } - } - - public override bool IsExtern - { - get { return _originalDefinition.IsExtern; } - } - - public override bool IsSealed - { - get { return _originalDefinition.IsSealed; } - } - - public override bool IsAbstract - { - get { return _originalDefinition.IsAbstract; } - } - - public override bool IsVirtual - { - get { return _originalDefinition.IsVirtual; } - } - - public override bool IsOverride - { - get { return _originalDefinition.IsOverride; } - } - - public override bool IsImplicitlyDeclared - { - get { return _originalDefinition.IsImplicitlyDeclared; } - } - - internal override ObsoleteAttributeData ObsoleteAttributeData - { - get { return _originalDefinition.ObsoleteAttributeData; } - } - - public override bool IsIndexer - { - get { return _originalDefinition.IsIndexer; } + return OriginalDefinition.GetAttributes(); } public override ImmutableArray TypeCustomModifiers { - get { return _containingType.TypeSubstitution.SubstituteCustomModifiers(_originalDefinition.Type, _originalDefinition.TypeCustomModifiers); } + get { return _containingType.TypeSubstitution.SubstituteCustomModifiers(OriginalDefinition.Type, OriginalDefinition.TypeCustomModifiers); } } public override ImmutableArray Parameters @@ -176,12 +82,11 @@ public override ImmutableArray Parameters } } - public override MethodSymbol GetMethod { get { - MethodSymbol originalGetMethod = _originalDefinition.GetMethod; + MethodSymbol originalGetMethod = OriginalDefinition.GetMethod; return (object)originalGetMethod == null ? null : originalGetMethod.AsMember(_containingType); } } @@ -190,14 +95,14 @@ public override MethodSymbol SetMethod { get { - MethodSymbol originalSetMethod = _originalDefinition.SetMethod; + MethodSymbol originalSetMethod = OriginalDefinition.SetMethod; return (object)originalSetMethod == null ? null : originalSetMethod.AsMember(_containingType); } } internal override bool IsExplicitInterfaceImplementation { - get { return _originalDefinition.IsExplicitInterfaceImplementation; } + get { return OriginalDefinition.IsExplicitInterfaceImplementation; } } //we want to compute this lazily since it may be expensive for the underlying symbol @@ -213,29 +118,16 @@ public override ImmutableArray ExplicitInterfaceImplementations { ImmutableInterlocked.InterlockedCompareExchange( ref _lazyExplicitInterfaceImplementations, - ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(_originalDefinition.ExplicitInterfaceImplementations, _containingType.TypeSubstitution), + ExplicitInterfaceHelpers.SubstituteExplicitInterfaceImplementations(OriginalDefinition.ExplicitInterfaceImplementations, _containingType.TypeSubstitution), default(ImmutableArray)); } return _lazyExplicitInterfaceImplementations; } } - internal override Microsoft.Cci.CallingConvention CallingConvention - { - get { return _originalDefinition.CallingConvention; } - } - internal override bool MustCallMethodsDirectly { - get { return _originalDefinition.MustCallMethodsDirectly; } - } - - public override Accessibility DeclaredAccessibility - { - get - { - return _originalDefinition.DeclaredAccessibility; - } + get { return OriginalDefinition.MustCallMethodsDirectly; } } internal override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembers @@ -246,13 +138,14 @@ internal override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembers { Interlocked.CompareExchange(ref _lazyOverriddenOrHiddenMembers, this.MakeOverriddenOrHiddenMembers(), null); } + return _lazyOverriddenOrHiddenMembers; } } private ImmutableArray SubstituteParameters() { - var unsubstitutedParameters = _originalDefinition.Parameters; + var unsubstitutedParameters = OriginalDefinition.Parameters; if (unsubstitutedParameters.IsEmpty) { @@ -269,19 +162,5 @@ private ImmutableArray SubstituteParameters() return substituted.AsImmutableOrNull(); } } - - public override string MetadataName - { - // We'll never emit this symbol, so it doesn't really - // make sense for it to have a metadata name. However, all - // symbols have an implementation of MetadataName (since it - // is virtual on Symbol) so we might as well define it in a - // consistent way. - - get - { - return _originalDefinition.MetadataName; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs index a403063f55dc9..f89876e187683 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedTypeParameterSymbol.cs @@ -10,11 +10,10 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal class SubstitutedTypeParameterSymbol : TypeParameterSymbol + internal class SubstitutedTypeParameterSymbol : WrapperTypeParameterSymbol { private readonly Symbol _container; private readonly TypeMap _map; - private readonly TypeParameterSymbol _substitutedFrom; private readonly int _ordinal; #if DEBUG_ALPHA @@ -23,26 +22,18 @@ internal class SubstitutedTypeParameterSymbol : TypeParameterSymbol #endif internal SubstitutedTypeParameterSymbol(Symbol newContainer, TypeMap map, TypeParameterSymbol substitutedFrom, int ordinal) + : base(substitutedFrom) { _container = newContainer; // it is important that we don't use the map here in the constructor, as the map is still being filled // in by TypeMap.WithAlphaRename. Instead, we can use the map lazily when yielding the constraints. _map = map; - _substitutedFrom = substitutedFrom; _ordinal = ordinal; #if DEBUG_ALPHA _mySequence = _nextSequence++; #endif } - public override TypeParameterKind TypeParameterKind - { - get - { - return _substitutedFrom.TypeParameterKind; - } - } - public override Symbol ContainingSymbol { get @@ -51,22 +42,6 @@ public override Symbol ContainingSymbol } } - public override ImmutableArray Locations - { - get - { - return _substitutedFrom.Locations; - } - } - - public override ImmutableArray DeclaringSyntaxReferences - { - get - { - return _substitutedFrom.DeclaringSyntaxReferences; - } - } - public override TypeParameterSymbol OriginalDefinition { get @@ -74,8 +49,8 @@ public override TypeParameterSymbol OriginalDefinition // A substituted type parameter symbol is used as a type parameter of a frame type for lambda-captured // variables within a generic method. In that case the frame's own type parameter is an original. return - ContainingSymbol.OriginalDefinition != _substitutedFrom.ContainingSymbol.OriginalDefinition ? this : - _substitutedFrom.OriginalDefinition; + ContainingSymbol.OriginalDefinition != _underlyingTypeParameter.ContainingSymbol.OriginalDefinition ? this : + _underlyingTypeParameter.OriginalDefinition; } } @@ -97,14 +72,6 @@ public override TypeParameterSymbol ReducedFrom } } - public override bool HasConstructorConstraint - { - get - { - return _substitutedFrom.HasConstructorConstraint; - } - } - public override int Ordinal { get @@ -113,35 +80,11 @@ public override int Ordinal } } - public override VarianceKind Variance - { - get - { - return _substitutedFrom.Variance; - } - } - - public override bool HasValueTypeConstraint - { - get - { - return _substitutedFrom.HasValueTypeConstraint; - } - } - - public override bool HasReferenceTypeConstraint - { - get - { - return _substitutedFrom.HasReferenceTypeConstraint; - } - } - public override string Name { get { - return _substitutedFrom.Name + return base.Name #if DEBUG_ALPHA + "#" + _mySequence #endif @@ -149,47 +92,29 @@ public override string Name } } - public override bool IsImplicitlyDeclared - { - get - { - return _substitutedFrom.IsImplicitlyDeclared; - } - } - - public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return _substitutedFrom.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); - } - public override ImmutableArray GetAttributes() { - return _substitutedFrom.GetAttributes(); - } - - internal override void EnsureAllConstraintsAreResolved() - { - _substitutedFrom.EnsureAllConstraintsAreResolved(); + return _underlyingTypeParameter.GetAttributes(); } internal override ImmutableArray GetConstraintTypes(ConsList inProgress) { - return _map.SubstituteTypesWithoutModifiers(_substitutedFrom.GetConstraintTypes(inProgress)).WhereAsArray(s_isNotObjectFunc).Distinct(); + return _map.SubstituteTypesWithoutModifiers(_underlyingTypeParameter.GetConstraintTypes(inProgress)).WhereAsArray(s_isNotObjectFunc).Distinct(); } internal override ImmutableArray GetInterfaces(ConsList inProgress) { - return _map.SubstituteNamedTypes(_substitutedFrom.GetInterfaces(inProgress)); + return _map.SubstituteNamedTypes(_underlyingTypeParameter.GetInterfaces(inProgress)); } internal override NamedTypeSymbol GetEffectiveBaseClass(ConsList inProgress) { - return _map.SubstituteNamedType(_substitutedFrom.GetEffectiveBaseClass(inProgress)); + return _map.SubstituteNamedType(_underlyingTypeParameter.GetEffectiveBaseClass(inProgress)); } internal override TypeSymbol GetDeducedBaseType(ConsList inProgress) { - return _map.SubstituteType(_substitutedFrom.GetDeducedBaseType(inProgress)).AsTypeSymbolOnly(); + return _map.SubstituteType(_underlyingTypeParameter.GetDeducedBaseType(inProgress)).AsTypeSymbolOnly(); } private static readonly Func s_isNotObjectFunc = type => type.SpecialType != SpecialType.System_Object; diff --git a/src/Compilers/CSharp/Portable/Symbols/WrappedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/WrappedParameterSymbol.cs deleted file mode 100644 index 4882926f14a7c..0000000000000 --- a/src/Compilers/CSharp/Portable/Symbols/WrappedParameterSymbol.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Immutable; -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.CodeAnalysis.CSharp.Emit; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.CSharp.Symbols -{ - internal abstract class WrappedParameterSymbol : ParameterSymbol - { - protected readonly ParameterSymbol underlyingParameter; - - protected WrappedParameterSymbol(ParameterSymbol underlyingParameter) - { - Debug.Assert((object)underlyingParameter != null); - - this.underlyingParameter = underlyingParameter; - } - - public abstract override Symbol ContainingSymbol - { - get; - } - - public override ParameterSymbol OriginalDefinition - { - get { return this; } - } - - public sealed override bool Equals(object obj) - { - if ((object)this == obj) - { - return true; - } - - // Equality of ordinal and containing symbol is a correct - // implementation for all ParameterSymbols, but we don't - // define it on the base type because most can simply use - // ReferenceEquals. - - var other = obj as WrappedParameterSymbol; - return (object)other != null && - this.Ordinal == other.Ordinal && - this.ContainingSymbol.Equals(other.ContainingSymbol); - } - - public sealed override int GetHashCode() - { - return Hash.Combine(ContainingSymbol, underlyingParameter.Ordinal); - } - - #region Forwarded - - public override TypeSymbol Type - { - get { return underlyingParameter.Type; } - } - - public sealed override RefKind RefKind - { - get { return underlyingParameter.RefKind; } - } - - internal sealed override bool IsMetadataIn - { - get { return underlyingParameter.IsMetadataIn; } - } - - internal sealed override bool IsMetadataOut - { - get { return underlyingParameter.IsMetadataOut; } - } - - public sealed override ImmutableArray Locations - { - get { return underlyingParameter.Locations; } - } - - public sealed override ImmutableArray DeclaringSyntaxReferences - { - get { return underlyingParameter.DeclaringSyntaxReferences; } - } - - public override ImmutableArray GetAttributes() - { - return underlyingParameter.GetAttributes(); - } - - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) - { - underlyingParameter.AddSynthesizedAttributes(compilationState, ref attributes); - } - - internal sealed override ConstantValue ExplicitDefaultConstantValue - { - get { return underlyingParameter.ExplicitDefaultConstantValue; } - } - - public override int Ordinal - { - get { return underlyingParameter.Ordinal; } - } - - public override bool IsParams - { - get { return underlyingParameter.IsParams; } - } - - internal override bool IsMetadataOptional - { - get { return underlyingParameter.IsMetadataOptional; } - } - - public override bool IsImplicitlyDeclared - { - get { return underlyingParameter.IsImplicitlyDeclared; } - } - - public sealed override string Name - { - get { return underlyingParameter.Name; } - } - - public sealed override string MetadataName - { - get { return underlyingParameter.MetadataName; } - } - - public override ImmutableArray CustomModifiers - { - get { return underlyingParameter.CustomModifiers; } - } - - internal override MarshalPseudoCustomAttributeData MarshallingInformation - { - get { return underlyingParameter.MarshallingInformation; } - } - - internal override UnmanagedType MarshallingType - { - get { return underlyingParameter.MarshallingType; } - } - - internal override bool IsIDispatchConstant - { - get { return underlyingParameter.IsIDispatchConstant; } - } - - internal override bool IsIUnknownConstant - { - get { return underlyingParameter.IsIUnknownConstant; } - } - - internal override bool IsCallerLineNumber - { - get { return underlyingParameter.IsCallerLineNumber; } - } - - internal override bool IsCallerFilePath - { - get { return underlyingParameter.IsCallerFilePath; } - } - - internal override bool IsCallerMemberName - { - get { return underlyingParameter.IsCallerMemberName; } - } - - internal sealed override ushort CountOfCustomModifiersPrecedingByRef - { - get { return underlyingParameter.CountOfCustomModifiersPrecedingByRef; } - } - - #endregion - } -} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperEventSymbol.cs new file mode 100644 index 0000000000000..c1bd082d90df0 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperEventSymbol.cs @@ -0,0 +1,205 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents an event that is based on another event. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperEventSymbol : EventSymbol + { + /// + /// The underlying EventSymbol. + /// + protected readonly EventSymbol _underlyingEvent; + + public WrapperEventSymbol(EventSymbol underlyingEvent) + { + Debug.Assert((object)underlyingEvent != null); + _underlyingEvent = underlyingEvent; + } + + public EventSymbol UnderlyingEvent + { + get + { + return _underlyingEvent; + } + } + + public override bool IsImplicitlyDeclared + { + get + { + return _underlyingEvent.IsImplicitlyDeclared; + } + } + + internal override bool HasSpecialName + { + get + { + return _underlyingEvent.HasSpecialName; + } + } + + public override abstract TypeSymbol Type + { + get; + } + + public override abstract MethodSymbol AddMethod + { + get; + } + + public override abstract MethodSymbol RemoveMethod + { + get; + } + + internal override abstract FieldSymbol AssociatedField + { + get; + } + + internal override abstract bool IsExplicitInterfaceImplementation + { + get; + } + + public override abstract ImmutableArray ExplicitInterfaceImplementations + { + get; + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override string Name + { + get + { + return _underlyingEvent.Name; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingEvent.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + public override ImmutableArray Locations + { + get + { + return _underlyingEvent.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingEvent.DeclaringSyntaxReferences; + } + } + + public override Accessibility DeclaredAccessibility + { + get + { + return _underlyingEvent.DeclaredAccessibility; + } + } + + public override bool IsStatic + { + get + { + return _underlyingEvent.IsStatic; + } + } + + public override bool IsVirtual + { + get + { + return _underlyingEvent.IsVirtual; + } + } + + public override bool IsOverride + { + get + { + return _underlyingEvent.IsOverride; + } + } + + public override bool IsAbstract + { + get + { + return _underlyingEvent.IsAbstract; + } + } + + public override bool IsSealed + { + get + { + return _underlyingEvent.IsSealed; + } + } + + public override bool IsExtern + { + get + { + return _underlyingEvent.IsExtern; + } + } + + internal override ObsoleteAttributeData ObsoleteAttributeData + { + get + { + return _underlyingEvent.ObsoleteAttributeData; + } + } + + public override abstract ImmutableArray GetAttributes(); + + internal override abstract bool MustCallMethodsDirectly + { + get; + } + + public override bool IsWindowsRuntimeEvent + { + get + { + return _underlyingEvent.IsWindowsRuntimeEvent; + } + } + + internal override bool HasRuntimeSpecialName + { + get + { + return _underlyingEvent.HasRuntimeSpecialName; + } + } + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperFieldSymbol.cs new file mode 100644 index 0000000000000..dab4baeb93437 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperFieldSymbol.cs @@ -0,0 +1,209 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Threading; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a field that is based on another field. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperFieldSymbol : FieldSymbol + { + /// + /// The underlying FieldSymbol. + /// + protected readonly FieldSymbol _underlyingField; + + public WrapperFieldSymbol(FieldSymbol underlyingField) + { + Debug.Assert((object)underlyingField != null); + _underlyingField = underlyingField; + } + + public FieldSymbol UnderlyingField + { + get + { + return _underlyingField; + } + } + + public override bool IsImplicitlyDeclared + { + get { return _underlyingField.IsImplicitlyDeclared; } + } + + internal override abstract TypeSymbol GetFieldType(ConsList fieldsBeingBound); + + public override abstract ImmutableArray CustomModifiers + { + get; + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override Accessibility DeclaredAccessibility + { + get + { + return _underlyingField.DeclaredAccessibility; + } + } + + public override abstract ImmutableArray GetAttributes(); + + public override string Name + { + get + { + return _underlyingField.Name; + } + } + + internal override bool HasSpecialName + { + get + { + return _underlyingField.HasSpecialName; + } + } + + internal override bool HasRuntimeSpecialName + { + get + { + return _underlyingField.HasRuntimeSpecialName; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingField.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + internal override bool IsNotSerialized + { + get + { + return _underlyingField.IsNotSerialized; + } + } + + internal override bool IsMarshalledExplicitly + { + get + { + return _underlyingField.IsMarshalledExplicitly; + } + } + + internal override MarshalPseudoCustomAttributeData MarshallingInformation + { + get + { + return _underlyingField.MarshallingInformation; + } + } + + internal override ImmutableArray MarshallingDescriptor + { + get + { + return _underlyingField.MarshallingDescriptor; + } + } + + internal override int? TypeLayoutOffset + { + get + { + return _underlyingField.TypeLayoutOffset; + } + } + + public override abstract Symbol AssociatedSymbol + { + get; + } + + public override bool IsReadOnly + { + get + { + return _underlyingField.IsReadOnly; + } + } + + public override bool IsVolatile + { + get + { + return _underlyingField.IsVolatile; + } + } + + public override bool IsConst + { + get + { + return _underlyingField.IsConst; + } + } + + internal override ObsoleteAttributeData ObsoleteAttributeData + { + get + { + return _underlyingField.ObsoleteAttributeData; + } + } + + public override object ConstantValue + { + get + { + return _underlyingField.ConstantValue; + } + } + + internal override ConstantValue GetConstantValue(ConstantFieldsInProgress inProgress, bool earlyDecodingWellKnownAttributes) + { + return _underlyingField.GetConstantValue(inProgress, earlyDecodingWellKnownAttributes); + } + + public override ImmutableArray Locations + { + get + { + return _underlyingField.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingField.DeclaringSyntaxReferences; + } + } + + public override bool IsStatic + { + get + { + return _underlyingField.IsStatic; + } + } + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperMethodSymbol.cs new file mode 100644 index 0000000000000..bbae77c6387aa --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperMethodSymbol.cs @@ -0,0 +1,392 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a method that is based on another method. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperMethodSymbol : MethodSymbol + { + /// + /// The underlying MethodSymbol. + /// + protected readonly MethodSymbol _underlyingMethod; + + public WrapperMethodSymbol(MethodSymbol underlyingMethod) + { + Debug.Assert((object)underlyingMethod != null); + _underlyingMethod = underlyingMethod; + } + + public MethodSymbol UnderlyingMethod + { + get + { + return _underlyingMethod; + } + } + + public override bool IsVararg + { + get + { + return _underlyingMethod.IsVararg; + } + } + + public override bool IsGenericMethod + { + get + { + return _underlyingMethod.IsGenericMethod; + } + } + + public override int Arity + { + get + { + return _underlyingMethod.Arity; + } + } + + public override abstract ImmutableArray TypeParameters + { + get; + } + + public override abstract ImmutableArray TypeArguments + { + get; + } + + public override abstract bool ReturnsVoid + { + get; + } + + internal override RefKind RefKind + { + get + { + return _underlyingMethod.RefKind; + } + } + + public override abstract TypeSymbol ReturnType + { + get; + } + + public override abstract ImmutableArray ReturnTypeCustomModifiers + { + get; + } + + internal override int ParameterCount + { + get { return _underlyingMethod.ParameterCount; } + } + + public override abstract ImmutableArray Parameters + { + get; + } + + public override abstract Symbol AssociatedSymbol + { + get; + } + + public override bool IsExtensionMethod + { + get + { + return _underlyingMethod.IsExtensionMethod; + } + } + + public override bool HidesBaseMethodsByName + { + get + { + return _underlyingMethod.HidesBaseMethodsByName; + } + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override ImmutableArray Locations + { + get + { + return _underlyingMethod.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingMethod.DeclaringSyntaxReferences; + } + } + + public override Accessibility DeclaredAccessibility + { + get + { + return _underlyingMethod.DeclaredAccessibility; + } + } + + public override bool IsStatic + { + get + { + return _underlyingMethod.IsStatic; + } + } + + public override bool IsVirtual + { + get + { + return _underlyingMethod.IsVirtual; + } + } + + public override bool IsAsync + { + get + { + return _underlyingMethod.IsAsync; + } + } + + public override bool IsOverride + { + get + { + return _underlyingMethod.IsOverride; + } + } + + public override bool IsAbstract + { + get + { + return _underlyingMethod.IsAbstract; + } + } + + public override bool IsSealed + { + get + { + return _underlyingMethod.IsSealed; + } + } + + public override bool IsExtern + { + get + { + return _underlyingMethod.IsExtern; + } + } + + public override bool IsImplicitlyDeclared + { + get + { + return _underlyingMethod.IsImplicitlyDeclared; + } + } + + internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) + { + return _underlyingMethod.IsMetadataVirtual(ignoreInterfaceImplementationChanges); + } + + internal override bool IsMetadataFinal + { + get + { + return _underlyingMethod.IsMetadataFinal; + } + } + + internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) + { + return _underlyingMethod.IsMetadataNewSlot(ignoreInterfaceImplementationChanges); + } + + internal override bool RequiresSecurityObject + { + get + { + return _underlyingMethod.RequiresSecurityObject; + } + } + + public override DllImportData GetDllImportData() + { + return _underlyingMethod.GetDllImportData(); + } + + internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation + { + get + { + return _underlyingMethod.ReturnValueMarshallingInformation; + } + } + + internal override bool HasDeclarativeSecurity + { + get { return _underlyingMethod.HasDeclarativeSecurity; } + } + + internal override IEnumerable GetSecurityInformation() + { + return _underlyingMethod.GetSecurityInformation(); + } + + internal override ImmutableArray GetAppliedConditionalSymbols() + { + return _underlyingMethod.GetAppliedConditionalSymbols(); + } + + public override abstract ImmutableArray GetAttributes(); + + // Get return type attributes + public override abstract ImmutableArray GetReturnTypeAttributes(); + + internal override ObsoleteAttributeData ObsoleteAttributeData + { + get + { + return _underlyingMethod.ObsoleteAttributeData; + } + } + + public override string Name + { + get + { + return _underlyingMethod.Name; + } + } + + internal override bool HasSpecialName + { + get + { + return _underlyingMethod.HasSpecialName; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingMethod.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + internal override System.Reflection.MethodImplAttributes ImplementationAttributes + { + get + { + return _underlyingMethod.ImplementationAttributes; + } + } + + public override MethodKind MethodKind + { + get + { + return _underlyingMethod.MethodKind; + } + } + + internal override Microsoft.Cci.CallingConvention CallingConvention + { + get + { + return _underlyingMethod.CallingConvention; + } + } + + internal override abstract bool IsExplicitInterfaceImplementation + { + get; + } + + public override abstract ImmutableArray ExplicitInterfaceImplementations + { + get; + } + + internal override bool IsAccessCheckedOnOverride + { + get + { + return _underlyingMethod.IsAccessCheckedOnOverride; + } + } + + internal override bool IsExternal + { + get + { + return _underlyingMethod.IsExternal; + } + } + + internal override bool HasRuntimeSpecialName + { + get + { + return _underlyingMethod.HasRuntimeSpecialName; + } + } + + internal override bool ReturnValueIsMarshalledExplicitly + { + get + { + return _underlyingMethod.ReturnValueIsMarshalledExplicitly; + } + } + + internal override ImmutableArray ReturnValueMarshallingDescriptor + { + get + { + return _underlyingMethod.ReturnValueMarshallingDescriptor; + } + } + + internal override bool GenerateDebugInfo + { + get + { + return _underlyingMethod.GenerateDebugInfo; + } + } + + internal override abstract int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree); + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs new file mode 100644 index 0000000000000..3e10f84f9c112 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs @@ -0,0 +1,327 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Threading; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a named type that is based on another named type. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperNamedTypeSymbol : NamedTypeSymbol + { + /// + /// The underlying NamedTypeSymbol. + /// + protected readonly NamedTypeSymbol _underlyingType; + + public WrapperNamedTypeSymbol(NamedTypeSymbol underlyingType) + { + Debug.Assert((object)underlyingType != null); + _underlyingType = underlyingType; + } + + public NamedTypeSymbol UnderlyingNamedType + { + get + { + return _underlyingType; + } + } + + public override bool IsImplicitlyDeclared + { + get { return _underlyingType.IsImplicitlyDeclared; } + } + + public override int Arity + { + get + { + return _underlyingType.Arity; + } + } + + public override abstract ImmutableArray TypeParameters + { + get; + } + + internal override abstract ImmutableArray TypeArgumentsNoUseSiteDiagnostics + { + get; + } + + internal override abstract bool HasTypeArgumentsCustomModifiers + { + get; + } + + internal override abstract ImmutableArray> TypeArgumentsCustomModifiers + { + get; + } + + public override abstract NamedTypeSymbol ConstructedFrom + { + get; + } + + public override abstract NamedTypeSymbol EnumUnderlyingType + { + get; + } + + public override bool MightContainExtensionMethods + { + get + { + return _underlyingType.MightContainExtensionMethods; + } + } + + public override string Name + { + get + { + return _underlyingType.Name; + } + } + + public override string MetadataName + { + get + { + return _underlyingType.MetadataName; + } + } + + internal override bool HasSpecialName + { + get + { + return _underlyingType.HasSpecialName; + } + } + + internal override bool MangleName + { + get + { + return _underlyingType.MangleName; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingType.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + public override abstract IEnumerable MemberNames + { + get; + } + + public override abstract ImmutableArray GetMembers(); + + internal override abstract ImmutableArray GetMembersUnordered(); + + public override abstract ImmutableArray GetMembers(string name); + + internal override abstract IEnumerable GetFieldsToEmit(); + + internal override abstract IEnumerable GetMethodsToEmit(); + + internal override abstract IEnumerable GetPropertiesToEmit(); + + internal override abstract IEnumerable GetEventsToEmit(); + + internal override abstract ImmutableArray GetEarlyAttributeDecodingMembers(); + + internal override abstract ImmutableArray GetEarlyAttributeDecodingMembers(string name); + + internal override abstract ImmutableArray GetTypeMembersUnordered(); + + public override abstract ImmutableArray GetTypeMembers(); + + public override abstract ImmutableArray GetTypeMembers(string name); + + public override abstract ImmutableArray GetTypeMembers(string name, int arity); + + public override Accessibility DeclaredAccessibility + { + get + { + return _underlyingType.DeclaredAccessibility; + } + } + + public override TypeKind TypeKind + { + get + { + return _underlyingType.TypeKind; + } + } + + internal override bool IsInterface + { + get + { + return _underlyingType.IsInterface; + } + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override ImmutableArray Locations + { + get + { + return _underlyingType.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingType.DeclaringSyntaxReferences; + } + } + + public override bool IsStatic + { + get + { + return _underlyingType.IsStatic; + } + } + + public override bool IsAbstract + { + get + { + return _underlyingType.IsAbstract; + } + } + + internal override bool IsMetadataAbstract + { + get + { + return _underlyingType.IsMetadataAbstract; + } + } + + public override bool IsSealed + { + get + { + return _underlyingType.IsSealed; + } + } + + internal override bool IsMetadataSealed + { + get + { + return _underlyingType.IsMetadataSealed; + } + } + + public override abstract ImmutableArray GetAttributes(); + + internal override abstract IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState); + + internal override abstract NamedTypeSymbol BaseTypeNoUseSiteDiagnostics + { + get; + } + + internal override abstract ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved); + + internal override abstract ImmutableArray GetInterfacesToEmit(); + + internal override abstract NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved); + + internal override abstract ImmutableArray GetDeclaredInterfaces(ConsList basesBeingResolved); + + internal override abstract NamedTypeSymbol ComImportCoClass + { + get; + } + + internal override abstract bool IsComImport + { + get; + } + + internal override ObsoleteAttributeData ObsoleteAttributeData + { + get { return _underlyingType.ObsoleteAttributeData; } + } + + internal override bool ShouldAddWinRTMembers + { + get { return _underlyingType.ShouldAddWinRTMembers; } + } + + internal override bool IsWindowsRuntimeImport + { + get { return _underlyingType.IsWindowsRuntimeImport; } + } + + internal override TypeLayout Layout + { + get { return _underlyingType.Layout; } + } + + internal override CharSet MarshallingCharSet + { + get { return _underlyingType.MarshallingCharSet; } + } + + internal override bool IsSerializable + { + get { return _underlyingType.IsSerializable; } + } + + internal override bool HasDeclarativeSecurity + { + get { return _underlyingType.HasDeclarativeSecurity; } + } + + internal override IEnumerable GetSecurityInformation() + { + return _underlyingType.GetSecurityInformation(); + } + + internal override ImmutableArray GetAppliedConditionalSymbols() + { + return _underlyingType.GetAppliedConditionalSymbols(); + } + + internal override AttributeUsageInfo GetAttributeUsageInfo() + { + return _underlyingType.GetAttributeUsageInfo(); + } + + internal override bool GetGuidString(out string guidString) + { + return _underlyingType.GetGuidString(out guidString); + } + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperParameterSymbol.cs new file mode 100644 index 0000000000000..d2773dbe46c26 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperParameterSymbol.cs @@ -0,0 +1,171 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a parameter that is based on another parameter. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperParameterSymbol : ParameterSymbol + { + protected readonly ParameterSymbol _underlyingParameter; + + protected WrapperParameterSymbol(ParameterSymbol underlyingParameter) + { + Debug.Assert((object)underlyingParameter != null); + + this._underlyingParameter = underlyingParameter; + } + + public ParameterSymbol UnderlyingParameter + { + get + { + return _underlyingParameter; + } + } + + public abstract override Symbol ContainingSymbol + { + get; + } + + #region Forwarded + + public override TypeSymbol Type + { + get { return _underlyingParameter.Type; } + } + + public sealed override RefKind RefKind + { + get { return _underlyingParameter.RefKind; } + } + + internal sealed override bool IsMetadataIn + { + get { return _underlyingParameter.IsMetadataIn; } + } + + internal sealed override bool IsMetadataOut + { + get { return _underlyingParameter.IsMetadataOut; } + } + + public sealed override ImmutableArray Locations + { + get { return _underlyingParameter.Locations; } + } + + public sealed override ImmutableArray DeclaringSyntaxReferences + { + get { return _underlyingParameter.DeclaringSyntaxReferences; } + } + + public override ImmutableArray GetAttributes() + { + return _underlyingParameter.GetAttributes(); + } + + internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + { + _underlyingParameter.AddSynthesizedAttributes(compilationState, ref attributes); + } + + internal sealed override ConstantValue ExplicitDefaultConstantValue + { + get { return _underlyingParameter.ExplicitDefaultConstantValue; } + } + + public override int Ordinal + { + get { return _underlyingParameter.Ordinal; } + } + + public override bool IsParams + { + get { return _underlyingParameter.IsParams; } + } + + internal override bool IsMetadataOptional + { + get { return _underlyingParameter.IsMetadataOptional; } + } + + public override bool IsImplicitlyDeclared + { + get { return _underlyingParameter.IsImplicitlyDeclared; } + } + + public sealed override string Name + { + get { return _underlyingParameter.Name; } + } + + public sealed override string MetadataName + { + get { return _underlyingParameter.MetadataName; } + } + + public override ImmutableArray CustomModifiers + { + get { return _underlyingParameter.CustomModifiers; } + } + + internal override MarshalPseudoCustomAttributeData MarshallingInformation + { + get { return _underlyingParameter.MarshallingInformation; } + } + + internal override UnmanagedType MarshallingType + { + get { return _underlyingParameter.MarshallingType; } + } + + internal override bool IsIDispatchConstant + { + get { return _underlyingParameter.IsIDispatchConstant; } + } + + internal override bool IsIUnknownConstant + { + get { return _underlyingParameter.IsIUnknownConstant; } + } + + internal override bool IsCallerLineNumber + { + get { return _underlyingParameter.IsCallerLineNumber; } + } + + internal override bool IsCallerFilePath + { + get { return _underlyingParameter.IsCallerFilePath; } + } + + internal override bool IsCallerMemberName + { + get { return _underlyingParameter.IsCallerMemberName; } + } + + internal sealed override ushort CountOfCustomModifiersPrecedingByRef + { + get { return _underlyingParameter.CountOfCustomModifiersPrecedingByRef; } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingParameter.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + #endregion + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperPropertySymbol.cs new file mode 100644 index 0000000000000..d6c9f224e54bd --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperPropertySymbol.cs @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a property that is based on another property. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperPropertySymbol : PropertySymbol + { + /// + /// The underlying PropertySymbol. + /// + protected readonly PropertySymbol _underlyingProperty; + + public WrapperPropertySymbol(PropertySymbol underlyingProperty) + { + Debug.Assert((object)underlyingProperty != null); + _underlyingProperty = underlyingProperty; + } + + public PropertySymbol UnderlyingProperty + { + get + { + return _underlyingProperty; + } + } + + public override bool IsImplicitlyDeclared + { + get { return _underlyingProperty.IsImplicitlyDeclared; } + } + + internal override RefKind RefKind + { + get + { + return _underlyingProperty.RefKind; + } + } + + public override abstract TypeSymbol Type + { + get; + } + + public override abstract ImmutableArray TypeCustomModifiers + { + get; + } + + public override abstract ImmutableArray Parameters + { + get; + } + + public override bool IsIndexer + { + get + { + return _underlyingProperty.IsIndexer; + } + } + + public override abstract MethodSymbol GetMethod + { + get; + } + + public override abstract MethodSymbol SetMethod + { + get; + } + + internal override Microsoft.Cci.CallingConvention CallingConvention + { + get + { + return _underlyingProperty.CallingConvention; + } + } + + internal override abstract bool IsExplicitInterfaceImplementation + { + get; + } + + public override abstract ImmutableArray ExplicitInterfaceImplementations + { + get; + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override string Name + { + get + { + return _underlyingProperty.Name; + } + } + + internal override bool HasSpecialName + { + get + { + return _underlyingProperty.HasSpecialName; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingProperty.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + public override ImmutableArray Locations + { + get + { + return _underlyingProperty.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingProperty.DeclaringSyntaxReferences; + } + } + + public override Accessibility DeclaredAccessibility + { + get + { + return _underlyingProperty.DeclaredAccessibility; + } + } + + public override bool IsStatic + { + get + { + return _underlyingProperty.IsStatic; + } + } + + public override bool IsVirtual + { + get + { + return _underlyingProperty.IsVirtual; + } + } + + public override bool IsOverride + { + get + { + return _underlyingProperty.IsOverride; + } + } + + public override bool IsAbstract + { + get + { + return _underlyingProperty.IsAbstract; + } + } + + public override bool IsSealed + { + get + { + return _underlyingProperty.IsSealed; + } + } + + public override bool IsExtern + { + get + { + return _underlyingProperty.IsExtern; + } + } + + internal override ObsoleteAttributeData ObsoleteAttributeData + { + get + { + return _underlyingProperty.ObsoleteAttributeData; + } + } + + public override abstract ImmutableArray GetAttributes(); + + internal override abstract bool MustCallMethodsDirectly + { + get; + } + + public override string MetadataName + { + get + { + return _underlyingProperty.MetadataName; + } + } + + internal override bool HasRuntimeSpecialName + { + get + { + return _underlyingProperty.HasRuntimeSpecialName; + } + } + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperTypeParameterSymbol.cs new file mode 100644 index 0000000000000..998fee2e3e4e9 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperTypeParameterSymbol.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Threading; +using Roslyn.Utilities; +using System.Diagnostics; +using System.Globalization; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a type parameter that is based on another type parameter. + /// When inheriting from this class, one shouldn't assume that + /// the default behavior it has is appropriate for every case. + /// That behavior should be carefully reviewed and derived type + /// should override behavior as appropriate. + /// + internal abstract class WrapperTypeParameterSymbol + : TypeParameterSymbol + { + /// + /// The underlying TypeParameterSymbol, cannot be another RetargetingTypeParameterSymbol. + /// + protected readonly TypeParameterSymbol _underlyingTypeParameter; + + public WrapperTypeParameterSymbol(TypeParameterSymbol underlyingTypeParameter) + { + Debug.Assert((object)underlyingTypeParameter != null); + _underlyingTypeParameter = underlyingTypeParameter; + } + + public TypeParameterSymbol UnderlyingTypeParameter + { + get + { + return _underlyingTypeParameter; + } + } + + public override bool IsImplicitlyDeclared + { + get { return _underlyingTypeParameter.IsImplicitlyDeclared; } + } + + public override TypeParameterKind TypeParameterKind + { + get + { + return _underlyingTypeParameter.TypeParameterKind; + } + } + + public override int Ordinal + { + get + { + return _underlyingTypeParameter.Ordinal; + } + } + + public override bool HasConstructorConstraint + { + get + { + return _underlyingTypeParameter.HasConstructorConstraint; + } + } + + public override bool HasReferenceTypeConstraint + { + get + { + return _underlyingTypeParameter.HasReferenceTypeConstraint; + } + } + + public override bool HasValueTypeConstraint + { + get + { + return _underlyingTypeParameter.HasValueTypeConstraint; + } + } + + public override VarianceKind Variance + { + get + { + return _underlyingTypeParameter.Variance; + } + } + + public override abstract Symbol ContainingSymbol + { + get; + } + + public override ImmutableArray Locations + { + get + { + return _underlyingTypeParameter.Locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return _underlyingTypeParameter.DeclaringSyntaxReferences; + } + } + + public override abstract ImmutableArray GetAttributes(); + + public override string Name + { + get + { + return _underlyingTypeParameter.Name; + } + } + + public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) + { + return _underlyingTypeParameter.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + } + + internal override void EnsureAllConstraintsAreResolved() + { + _underlyingTypeParameter.EnsureAllConstraintsAreResolved(); + } + + internal override abstract ImmutableArray GetConstraintTypes(ConsList inProgress); + + internal override abstract ImmutableArray GetInterfaces(ConsList inProgress); + + internal override abstract NamedTypeSymbol GetEffectiveBaseClass(ConsList inProgress); + + internal override abstract TypeSymbol GetDeducedBaseType(ConsList inProgress); + } +} From dad5ac239ca5e6c30fdb800cbe8414b74832d96b Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sat, 30 Apr 2016 16:06:15 -0700 Subject: [PATCH 2/3] Tuple and underlying type unification. Part 1. - Include memebers of underlying type into a set of members returned by tuple type symbol. Properties and events are not supported at the moment. - Track declaration locations for tuple related symbols. - Ensure Rest extensions are tuples. --- .../Portable/Binder/Binder_Conversions.cs | 13 +- .../Portable/Binder/Binder_Expressions.cs | 32 +- .../CSharp/Portable/Binder/Binder_Lookup.cs | 7 - .../CSharp/Portable/Binder/Binder_Symbols.cs | 33 +- .../Semantics/Conversions/Conversions.cs | 11 +- .../OverloadResolution/MethodTypeInference.cs | 27 +- .../OverloadResolution/OverloadResolution.cs | 10 +- .../CSharp/Portable/CSharpCodeAnalysis.csproj | 3 + .../Portable/Compilation/CSharpCompilation.cs | 2 +- .../Portable/Emitter/Model/PEModuleBuilder.cs | 16 +- .../LocalRewriter/LocalRewriter_Field.cs | 45 +- .../LocalRewriter_TupleCreationExpression.cs | 4 +- .../Lowering/MethodToClassRewriter.cs | 72 +- .../Portable/Symbols/AbstractTypeMap.cs | 4 +- .../Symbols/Compilation_WellKnownMembers.cs | 34 - .../Symbols/ConstructedMethodSymbol.cs | 16 + .../CSharp/Portable/Symbols/FieldSymbol.cs | 24 + .../CSharp/Portable/Symbols/MethodSymbol.cs | 23 + .../Portable/Symbols/NamedTypeSymbol.cs | 77 +- .../Retargeting/RetargetingMethodSymbol.cs | 16 +- .../Symbols/SubstitutedMethodSymbol.cs | 12 +- .../CSharp/Portable/Symbols/SymbolVisitor.cs | 5 - .../Portable/Symbols/SymbolVisitor`1.cs | 5 - .../Portable/Symbols/SymbolVisitor`2.cs | 12 - .../Portable/Symbols/TupleFieldSymbol.cs | 211 +- .../Portable/Symbols/TupleTypeSymbol.cs | 690 +++- .../Symbols/Tuples/TupleErrorFieldSymbol.cs | 122 + .../Symbols/Tuples/TupleMethodSymbol.cs | 203 ++ .../Symbols/Tuples/TupleParameterSymbol.cs | 49 + .../CSharp/Portable/Symbols/TypeSymbol.cs | 41 +- .../Portable/Symbols/TypeSymbolExtensions.cs | 12 +- .../Symbols/Wrappers/WrapperMethodSymbol.cs | 96 +- .../Wrappers/WrapperNamedTypeSymbol.cs | 4 - .../Test/Emit/CodeGen/CodeGenTupleTest.cs | 2917 ++++++++++++++++- .../Core/SharedCollections/ArrayBuilder.cs | 5 + 35 files changed, 4257 insertions(+), 596 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Symbols/Tuples/TupleErrorFieldSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs create mode 100644 src/Compilers/CSharp/Portable/Symbols/Tuples/TupleParameterSymbol.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index dccb5a24eb6bf..3eac1dd1b26c4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -344,26 +344,21 @@ private BoundExpression CreateTupleConversion(CSharpSyntaxNode syntax, BoundTupl NamedTypeSymbol targetType = (NamedTypeSymbol)destinationWithoutNullable; - NamedTypeSymbol targetUnderlyingType; if (targetType.IsTupleType) { var destTupleType = (TupleTypeSymbol)targetType; - targetUnderlyingType = destTupleType.UnderlyingTupleType; // do not lose the original element names in the literal if different from names in the target + + // PROTOTYPE(tuples): Come back to this, what about locations? targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt); } - else - { - targetUnderlyingType = targetType; - } var arguments = sourceTuple.Arguments; - Debug.Assert(Compilation.IsWellKnownTupleType(targetUnderlyingType, arguments.Length), "converting a tuple literal to incompatible type?"); - var convertedArguments = ArrayBuilder.GetInstance(arguments.Length); var targetElementTypes = ArrayBuilder.GetInstance(arguments.Length); - TupleTypeSymbol.AddElementTypes(targetUnderlyingType, targetElementTypes); + TupleTypeSymbol.AddElementTypes(targetType, targetElementTypes); + Debug.Assert(targetElementTypes.Count == arguments.Length, "converting a tuple literal to incompatible type?"); for (int i = 0; i < arguments.Length; i++) { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 0041f95463a6a..e7dba7065e22e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -666,6 +666,7 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost var boundArguments = ArrayBuilder.GetInstance(arguments.Count); var elementTypes = ArrayBuilder.GetInstance(arguments.Count); + var elementLocations = ArrayBuilder.GetInstance(arguments.Count); ArrayBuilder elementNames = null; int countOfExplicitNames = 0; @@ -673,7 +674,18 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost for (int i = 0, l = numElements; i < l; i++) { ArgumentSyntax argumentSyntax = arguments[i]; - string name = argumentSyntax.NameColon?.Name?.Identifier.ValueText; + string name = null; + IdentifierNameSyntax nameSyntax = argumentSyntax.NameColon?.Name; + + if (nameSyntax != null) + { + name = nameSyntax.Identifier.ValueText; + elementLocations.Add(nameSyntax.Location); + } + else + { + elementLocations.Add(argumentSyntax.Location); + } // validate name if we have one if (name != null) @@ -711,12 +723,13 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost default(ImmutableArray) : elementNames.ToImmutableAndFree(); - TupleTypeSymbol tupleTypeOpt = null; + NamedTypeSymbol tupleTypeOpt = null; var elements = elementTypes.ToImmutableAndFree(); + var locations = elementLocations.ToImmutableAndFree(); if (hasNaturalType) { - tupleTypeOpt = TupleTypeSymbol.Create(elements, elementNamesArray, this.Compilation, node, diagnostics); + tupleTypeOpt = TupleTypeSymbol.Create(node.Location, elements, locations, elementNamesArray, this.Compilation, node, diagnostics); } return new BoundTupleLiteral(node, elementNamesArray, boundArguments.ToImmutableAndFree(), tupleTypeOpt, hasErrors); @@ -3929,15 +3942,6 @@ private bool IsConstructorAccessible(MethodSymbol constructor, ref HashSet overloadResolutionResult = OverloadResolutionResult.GetInstance(); - this.OverloadResolution.ObjectCreationOverloadResolution(GetAccessibleConstructorsForOverloadResolution(typeContainingConstructors, ref useSiteDiagnostics), analyzedArguments, overloadResolutionResult, ref useSiteDiagnostics); + this.OverloadResolution.ObjectCreationOverloadResolution(GetAccessibleConstructorsForOverloadResolution(type, ref useSiteDiagnostics), analyzedArguments, overloadResolutionResult, ref useSiteDiagnostics); diagnostics.Add(node, useSiteDiagnostics); useSiteDiagnostics = null; @@ -3989,7 +3993,7 @@ private bool IsConstructorAccessible(MethodSymbol constructor, ref HashSet candidateConstructors; if (TryPerformConstructorOverloadResolution( - typeContainingConstructors, + type, analyzedArguments, typeName, typeNode.Location, diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index 3ef18c8ae2906..b08ba29634ab8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -715,13 +715,6 @@ internal virtual bool SupportsExtensionMethods break; } - var tuple = currentType as TupleTypeSymbol; - if ((object)tuple != null) - { - currentType = tuple.UnderlyingTupleType; - continue; - } - if (basesBeingResolved != null && basesBeingResolved.ContainsReference(type.OriginalDefinition)) { var other = GetNearestOtherSymbol(basesBeingResolved, type); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index fc1615a8da08d..a2c0005b5e68c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -399,6 +399,7 @@ private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnosti { int numElements = syntax.Elements.Count; var types = ArrayBuilder.GetInstance(numElements); + var locations = ArrayBuilder.GetInstance(numElements); ArrayBuilder elementNames = null; // set of names already used @@ -417,16 +418,26 @@ private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnosti Error(diagnostics, ErrorCode.ERR_FieldCantBeRefAny, argumentSyntax, argumentType); } - string name = argumentSyntax.Name?.Identifier.ValueText; + string name = null; + IdentifierNameSyntax nameSyntax = argumentSyntax.Name; - // validate name if we have one - if (name != null) + if (nameSyntax != null) { + name = nameSyntax.Identifier.ValueText; + + // validate name if we have one countOfExplicitNames++; - CheckTupleMemberName(name, i, argumentSyntax.Name, diagnostics, uniqueFieldNames); + CheckTupleMemberName(name, i, nameSyntax, diagnostics, uniqueFieldNames); + locations.Add(nameSyntax.Location); + } + else + { + locations.Add(argumentSyntax.Location); } + CollectTupleFieldMemberNames(name, i + 1, numElements, ref elementNames); } + uniqueFieldNames.Free(); if (countOfExplicitNames != 0 && countOfExplicitNames != numElements) @@ -435,18 +446,22 @@ private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnosti } ImmutableArray typesArray = types.ToImmutableAndFree(); + ImmutableArray locationsArray = locations.ToImmutableAndFree(); + if (typesArray.Length < 2) { return new ExtendedErrorTypeSymbol(this.Compilation.Assembly.GlobalNamespace, LookupResultKind.NotCreatable, diagnostics.Add(ErrorCode.ERR_TupleTooFewElements, syntax.Location)); } - return TupleTypeSymbol.Create(typesArray, - elementNames == null ? + return TupleTypeSymbol.Create(syntax.Location, + typesArray, + locationsArray, + elementNames == null ? default(ImmutableArray) : elementNames.ToImmutableAndFree(), - this.Compilation, - syntax, - diagnostics); + this.Compilation, + syntax, + diagnostics); } private static void CollectTupleFieldMemberNames(string name, int position, int tupleSize, ref ArrayBuilder elementNames) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 41665bd465115..dba5e70116366 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -709,14 +709,9 @@ protected override bool HasImplicitTupleConversion(BoundExpression source, TypeS var tupleExpression = (BoundTupleLiteral)source; var arguments = tupleExpression.Arguments; - // unwrap tuple to its underlying - if (destination.IsTupleType) - { - destination = ((TupleTypeSymbol)destination).UnderlyingTupleType; - } - - // check if underlying type is actually a possible underlying type for a tuple of given arity - if(!Compilation.IsWellKnownTupleType(destination, arguments.Length)) + // check if the type is actually compatible type for a tuple of given cardinality + int cardinality; + if (!destination.IsTupleCompatible(out cardinality) || cardinality != arguments.Length) { return false; } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index fcb2417abc9d3..6d0c2ff1a2848 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -650,16 +650,11 @@ private void MakeExplicitParameterTypeInferences(Binder binder, BoundTupleLitera } var destination = (NamedTypeSymbol)target; - - if (destination.IsTupleType) - { - destination = ((TupleTypeSymbol)destination).UnderlyingTupleType; - } - var sourceArguments = argument.Arguments; - // check if underlying type is actually a possible underlying type for a tuple of given arity - if (!binder.Compilation.IsWellKnownTupleType(destination, sourceArguments.Length)) + // check if the type is actually compatible type for a tuple of given cardinality + int cardinality; + if (!destination.IsTupleCompatible(out cardinality) || cardinality != sourceArguments.Length) { // target is not a tuple of appropriate shape return; @@ -839,16 +834,12 @@ private void MakeOutputTypeInferences(Binder binder, BoundTupleLiteral argument, var destination = (NamedTypeSymbol)formalType; - if (destination.IsTupleType) - { - destination = ((TupleTypeSymbol)destination).UnderlyingTupleType; - } - Debug.Assert(argument.Type == null, "should not need to dig into elements if tuple has natural type"); var sourceArguments = argument.Arguments; - // check if underlying type is actually a possible underlying type for a tuple of given arity - if (!binder.Compilation.IsWellKnownTupleType(destination, sourceArguments.Length)) + // check if the type is actually compatible type for a tuple of given cardinality + int cardinality; + if (!destination.IsTupleCompatible(out cardinality) || cardinality != sourceArguments.Length) { return; } @@ -1618,13 +1609,13 @@ private bool ExactTupleInference(TypeSymbol source, TypeSymbol target, ref HashS bool hasTuples = false; if (source.IsTupleType) { - source = ((TupleTypeSymbol)source).UnderlyingTupleType; + source = source.TupleUnderlyingType; hasTuples = true; } if (target.IsTupleType) { - target = ((TupleTypeSymbol)target).UnderlyingTupleType; + target = target.TupleUnderlyingType; hasTuples = true; } @@ -2489,7 +2480,7 @@ private bool Fix(int iParam, ref HashSet useSiteDiagnostics) { if (candidate.IsTupleType) { - best = ((TupleTypeSymbol)candidate).UnderlyingTupleType; + best = candidate.TupleUnderlyingType; break; } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 45263a88530e5..61e10840366cd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -1950,16 +1950,12 @@ private bool ExpressionMatchExactly(BoundTupleLiteral tupleSource, TypeSymbol ta var destination = (NamedTypeSymbol)targetType; - if (destination.IsTupleType) - { - destination = ((TupleTypeSymbol)destination).UnderlyingTupleType; - } - Debug.Assert((object)tupleSource.Type == null, "should not need to dig into elements if tuple has natural type"); var sourceArguments = tupleSource.Arguments; - // check if underlying type is actually a possible underlying type for a tuple of given arity - if (!Compilation.IsWellKnownTupleType(destination, sourceArguments.Length)) + // check if the type is actually compatible type for a tuple of given cardinality + int cardinality; + if (!destination.IsTupleCompatible(out cardinality) || cardinality != sourceArguments.Length) { return false; } diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index 7261cd47cb3ef..d0a525b838155 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -512,6 +512,9 @@ + + + diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index a896fe66b180f..1273bee7092eb 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -2831,7 +2831,7 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(ImmutableArray($"{nameof(elementTypes)}[{i}]")); } - return TupleTypeSymbol.Create(typesBuilder.ToImmutableAndFree(), elementNames, this); + return TupleTypeSymbol.Create(null, typesBuilder.ToImmutableAndFree(), default(ImmutableArray), elementNames, this); } protected override ITypeSymbol CommonDynamicType diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 0ddd2fb3e2a3c..389449d2228c7 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -770,7 +770,7 @@ protected virtual Cci.IModuleReference TranslateModule(ModuleSymbol module, Diag } else if (namedTypeSymbol.IsTupleType) { - namedTypeSymbol = ((TupleTypeSymbol)namedTypeSymbol).UnderlyingTupleType; + namedTypeSymbol = namedTypeSymbol.TupleUnderlyingType; } // Substitute error types with a special singleton object. @@ -929,8 +929,12 @@ internal static Cci.IGenericParameterReference Translate(TypeParameterSymbol par DiagnosticBag diagnostics, bool needDeclaration = false) { + if (fieldSymbol.IsTupleField) + { + fieldSymbol = fieldSymbol.TupleUnderlyingField; + } + Debug.Assert(fieldSymbol.IsDefinitionOrDistinct()); - Debug.Assert(!fieldSymbol.ContainingType.IsTupleType, "tuple fields should be rewritten to underlying by now"); if (!fieldSymbol.IsDefinition) { @@ -1085,13 +1089,17 @@ internal override Cci.IMethodReference Translate(MethodSymbol symbol, Diagnostic Cci.IMethodReference methodRef; NamedTypeSymbol container = methodSymbol.ContainingType; - Debug.Assert(methodSymbol.IsDefinitionOrDistinct()); - // Method of anonymous type being translated if (container.IsAnonymousType) { methodSymbol = AnonymousTypeManager.TranslateAnonymousTypeMethodSymbol(methodSymbol); } + else if (methodSymbol.IsTupleMethod) + { + methodSymbol = methodSymbol.TupleUnderlyingMethod; + } + + Debug.Assert(methodSymbol.IsDefinitionOrDistinct()); if (!methodSymbol.IsDefinition) { diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs index 5ab4aae8e2f99..bb5f242cd6b94 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs @@ -23,10 +23,9 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node) BoundFieldAccess oldNodeOpt = null) { - var tupleField = fieldSymbol as TupleFieldSymbol; - if (tupleField != null) + if (fieldSymbol.IsTupleField) { - return MakeTupleFieldAccess(syntax, tupleField, rewrittenReceiver, constantValueOpt, resultKind, type); + return MakeTupleFieldAccess(syntax, fieldSymbol, rewrittenReceiver, constantValueOpt, resultKind, type); } BoundExpression result = oldNodeOpt != null ? @@ -51,29 +50,33 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node) /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple)) /// private BoundExpression MakeTupleFieldAccess( - CSharpSyntaxNode syntax, - TupleFieldSymbol tupleField, + CSharpSyntaxNode syntax, + FieldSymbol tupleField, BoundExpression rewrittenReceiver, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { - var tupleType = (TupleTypeSymbol)tupleField.ContainingSymbol; + var tupleType = tupleField.ContainingType; - int fieldRemainder; - int loop = TupleTypeSymbol.NumberOfValueTuples(tupleField.Position, out fieldRemainder); + NamedTypeSymbol currentLinkType = tupleType.TupleUnderlyingType; + FieldSymbol underlyingField = tupleField.TupleUnderlyingField; - NamedTypeSymbol currentLinkType = tupleType.UnderlyingTupleType; + if ((object)underlyingField == null) + { + // Use-site error must have been repoted elsewhere. + return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); + } - if (loop > 1) + if (underlyingField.ContainingType != currentLinkType) { WellKnownMember wellKnownTupleRest = TupleTypeSymbol.GetTupleTypeMember(TupleTypeSymbol.RestPosition, TupleTypeSymbol.RestPosition); - var tupleRestField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _compilation.Assembly, _diagnostics, syntax); + var tupleRestField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax); if ((object)tupleRestField == null) { // error tolerance for cases when Rest is missing - return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type); + return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); } // make nested field accesses to Rest @@ -81,26 +84,14 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node) { FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType); - currentLinkType = (NamedTypeSymbol)currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1]; + currentLinkType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType; rewrittenReceiver = new BoundFieldAccess(syntax, rewrittenReceiver, nestedFieldSymbol, ConstantValue.NotAvailable, LookupResultKind.Viable, currentLinkType); - loop--; } - while (loop > 1); + while (underlyingField.ContainingType != currentLinkType); } // make a field access for the most local access - WellKnownMember wellKnownTypeMember = TupleTypeSymbol.GetTupleTypeMember(currentLinkType.Arity, fieldRemainder); - var linkField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTypeMember, _compilation.Assembly, _diagnostics, syntax); - - if ((object)linkField == null) - { - // error tolerance for cases when linkField is not avaialable - return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type); - } - - FieldSymbol lastFieldSymbol = linkField.AsMember(currentLinkType); - - return new BoundFieldAccess(syntax, rewrittenReceiver, lastFieldSymbol, constantValueOpt, resultKind, type); + return new BoundFieldAccess(syntax, rewrittenReceiver, underlyingField, constantValueOpt, resultKind, type); } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs index 33567de0901ca..19270f3c8770f 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleCreationExpression.cs @@ -31,7 +31,7 @@ private BoundNode VisitTupleExpression(BoundTupleExpression node) /// private BoundNode RewriteTupleCreationExpression(BoundTupleExpression node, ImmutableArray rewrittenArguments) { - NamedTypeSymbol underlyingTupleType = ((TupleTypeSymbol)node.Type).UnderlyingTupleType; + NamedTypeSymbol underlyingTupleType = node.Type.TupleUnderlyingType; ArrayBuilder underlyingTupleTypeChain = ArrayBuilder.GetInstance(); TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain); @@ -45,7 +45,6 @@ private BoundNode RewriteTupleCreationExpression(BoundTupleExpression node, Immu smallestType.Arity); var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition, TupleTypeSymbol.GetTupleCtor(smallestType.Arity), - _compilation.Assembly, _diagnostics, node.Syntax); if ((object)smallestCtor == null) @@ -61,7 +60,6 @@ private BoundNode RewriteTupleCreationExpression(BoundTupleExpression node, Immu NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek(); var tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition, TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition), - _compilation.Assembly, _diagnostics, node.Syntax); if ((object)tuple8Ctor == null) diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs index 9eaf0419cbef9..e8bc918c27d04 100644 --- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs @@ -497,32 +497,66 @@ protected MethodSymbol VisitMethodSymbol(MethodSymbol method) return null; } - if (!method.ContainingType.IsAnonymousType) + if (method.IsTupleMethod) { - // Method of a regular type - return ((MethodSymbol)method.OriginalDefinition) - .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly()) - .ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)); - } + // Method of a tuple type + var oldType = method.ContainingType; + var constructedFrom = method.ConstructedFrom; + Debug.Assert(oldType.IsTupleType); - // Method of an anonymous type - var newType = (NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly(); - if (ReferenceEquals(newType, method.ContainingType)) - { - // Anonymous type symbol was not rewritten - return method; - } + var newType = (NamedTypeSymbol)TypeMap.SubstituteType(oldType).AsTypeSymbolOnly(); + if ((object)newType == oldType) + { + // tuple type symbol was not rewritten + return constructedFrom.ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)); + } - // get a new method by name - foreach (var member in newType.GetMembers(method.Name)) - { - if (member.Kind == SymbolKind.Method) + Debug.Assert(newType.IsTupleType); + Debug.Assert(oldType.TupleElementTypes.Length == newType.TupleElementTypes.Length); + + // get a new method by position + var oldMembers = oldType.GetMembers(); + var newMembers = newType.GetMembers(); + Debug.Assert(oldMembers.Length == newMembers.Length); + + for (int i = 0; i < oldMembers.Length; i++) { - return (MethodSymbol)member; + if ((object)constructedFrom == oldMembers[i]) + { + return ((MethodSymbol)newMembers[i]).ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)); + } } + + throw ExceptionUtilities.Unreachable; } + else if (method.ContainingType.IsAnonymousType) + { + // Method of an anonymous type + var newType = (NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly(); + if (ReferenceEquals(newType, method.ContainingType)) + { + // Anonymous type symbol was not rewritten + return method; + } - throw ExceptionUtilities.Unreachable; + // get a new method by name + foreach (var member in newType.GetMembers(method.Name)) + { + if (member.Kind == SymbolKind.Method) + { + return (MethodSymbol)member; + } + } + + throw ExceptionUtilities.Unreachable; + } + else + { + // Method of a regular type + return ((MethodSymbol)method.OriginalDefinition) + .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly()) + .ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)); + } } private PropertySymbol VisitPropertySymbol(PropertySymbol property) diff --git a/src/Compilers/CSharp/Portable/Symbols/AbstractTypeMap.cs b/src/Compilers/CSharp/Portable/Symbols/AbstractTypeMap.cs index 46c2699df00f6..2212e89ddfd8c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AbstractTypeMap.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AbstractTypeMap.cs @@ -49,8 +49,8 @@ internal NamedTypeSymbol SubstituteNamedType(NamedTypeSymbol previous) if (previous.IsTupleType) { - TupleTypeSymbol previousTuple = (TupleTypeSymbol)previous; - NamedTypeSymbol oldUnderlyingType = previousTuple.UnderlyingTupleType; + var previousTuple = (TupleTypeSymbol)previous; + NamedTypeSymbol oldUnderlyingType = previousTuple.TupleUnderlyingType; NamedTypeSymbol newUnderlyingType = (NamedTypeSymbol)SubstituteType(oldUnderlyingType).Type; return ((object)newUnderlyingType == (object)oldUnderlyingType) ? previous : previousTuple.WithUnderlyingType(newUnderlyingType); diff --git a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs index ff6dd0f584948..523263dc799e5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs @@ -141,40 +141,6 @@ internal bool IsExceptionType(TypeSymbol type, ref HashSet useSi return IsEqualOrDerivedFromWellKnownClass(type, WellKnownType.System_Exception, ref useSiteDiagnostics); } - internal bool IsWellKnownTupleType(TypeSymbol typeToCheck, int requiredNumberOfElements) - { - Debug.Assert(!typeToCheck.IsTupleType, "The helper is meant to be used to validate underlying types, not with actual tuples"); - - // NOTE: error type symbol is NamedTypeSymbol, - // but not SymbolKind.NamedType, so check the kind before casting. - if (typeToCheck.Kind != SymbolKind.NamedType) - { - return false; - } - - NamedTypeSymbol currentType = (NamedTypeSymbol)typeToCheck; - const int maxNumberOfRegularElements = TupleTypeSymbol.RestPosition; - - // fetch largest tuple that is used to nest the rest - // but only if we really going to need one - var tupleWithNesting = requiredNumberOfElements >= maxNumberOfRegularElements ? - this.GetWellKnownType(TupleTypeSymbol.GetTupleType(maxNumberOfRegularElements)) : - null; - - while (requiredNumberOfElements >= maxNumberOfRegularElements) - { - if ((object)currentType.OriginalDefinition != tupleWithNesting) - { - return false; - } - - currentType = (NamedTypeSymbol)currentType.TypeArgumentsNoUseSiteDiagnostics[maxNumberOfRegularElements - 1]; - requiredNumberOfElements -= maxNumberOfRegularElements - 1; - } - - return (object)currentType.OriginalDefinition == this.GetWellKnownType(TupleTypeSymbol.GetTupleType(requiredNumberOfElements)); - } - internal bool IsEqualOrDerivedFromWellKnownClass(TypeSymbol type, WellKnownType wellKnownType, ref HashSet useSiteDiagnostics) { Debug.Assert(wellKnownType == WellKnownType.System_Attribute || diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstructedMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ConstructedMethodSymbol.cs index 2d57d69a23857..5a3df5e3db884 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstructedMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstructedMethodSymbol.cs @@ -27,5 +27,21 @@ public override ImmutableArray TypeArguments return _typeArguments; } } + + public override bool IsTupleMethod + { + get + { + return ConstructedFrom.IsTupleMethod; + } + } + + public override MethodSymbol TupleUnderlyingMethod + { + get + { + return ConstructedFrom.TupleUnderlyingMethod?.Construct(_typeArguments); + } + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs index 1f0e1a45ace3f..47089028e23bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs @@ -373,6 +373,30 @@ public sealed override bool HasUnsupportedMetadata #endregion + /// + /// Is this a field of a tuple type? + /// + public virtual bool IsTupleField + { + get + { + return false; + } + } + + /// + /// If this is a field of a tuple type, return corresponding underlying field from the + /// tuple underlying type. Otherwise, null. In case of a mulformed underlying type + /// the corresponding underlying field might be missing, return null in this case too. + /// + public virtual FieldSymbol TupleUnderlyingField + { + get + { + return null; + } + } + #region IFieldSymbol Members ISymbol IFieldSymbol.AssociatedSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs index 57aee6bdb2ad2..d3fd648cfb1b7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs @@ -1193,6 +1193,29 @@ INamedTypeSymbol IMethodSymbol.AssociatedAnonymousDelegate #endregion + /// + /// Is this a method of a tuple type? + /// + public virtual bool IsTupleMethod + { + get + { + return false; + } + } + + /// + /// If this is a method of a tuple type, return corresponding underlying method from the + /// tuple underlying type. Otherwise, null. + /// + public virtual MethodSymbol TupleUnderlyingMethod + { + get + { + return null; + } + } + #region IMethodSymbolInternal int IMethodSymbolInternal.CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index bd550e7b24324..0f0a1c950e1b3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -639,6 +639,8 @@ public override int GetHashCode() /// internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiersAndArraySizesAndLowerBounds = false, bool ignoreDynamic = false) { + Debug.Assert(!this.IsTupleType); + if ((object)t2 == this) return true; if ((object)t2 == null) return false; @@ -656,11 +658,9 @@ internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiersAndArrayS // If ignoring dynamic, compare underlying tuple types if (t2.IsTupleType) { - t2 = ((TupleTypeSymbol)t2).UnderlyingTupleType; - if ((object)t2 == this) return true; + t2 = t2.TupleUnderlyingType; + if (this.Equals(t2, ignoreCustomModifiersAndArraySizesAndLowerBounds, ignoreDynamic)) return true; } - - Debug.Assert(!this.IsTupleType); } NamedTypeSymbol other = t2 as NamedTypeSymbol; @@ -1260,6 +1260,65 @@ internal virtual FieldSymbol FixedElementField /// True if this is an interface type. internal abstract bool IsInterface { get; } + /// + /// Verify if the given type can be used to back a tuple type and return cardinality of that tuple type in . + /// + /// If method returns true, contains cardinality of the compatible tuple type. + /// + public override bool IsTupleCompatible(out int tupleCardinality) + { + if (IsTupleType) + { + tupleCardinality = TupleElementTypes.Length; + return true; + } + + // Should this be optimized for perf (caching for VT<0> to VT<7>, etc.)? + if (!IsUnboundGenericType && + ContainingSymbol.Kind == SymbolKind.Namespace && + Name == TupleTypeSymbol.TupleTypeName && ContainingNamespace.Name == "System" && + ContainingNamespace.ContainingNamespace?.IsGlobalNamespace == true) + { + int arity = Arity; + + if (arity > 0 && arity < TupleTypeSymbol.RestPosition) + { + tupleCardinality = arity; + return true; + } + else if (arity == TupleTypeSymbol.RestPosition && !IsDefinition) + { + // Skip through "Rest" extensions + TypeSymbol typeToCheck = this; + int levelsOfNesting = 0; + + do + { + levelsOfNesting++; + typeToCheck = ((NamedTypeSymbol)typeToCheck).TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1]; + } + while (typeToCheck.OriginalDefinition == this.OriginalDefinition && !typeToCheck.IsDefinition); + + if (typeToCheck.IsTupleType) + { + tupleCardinality = (TupleTypeSymbol.RestPosition - 1) * levelsOfNesting + typeToCheck.TupleElementTypes.Length; + return true; + } + + arity = (typeToCheck as NamedTypeSymbol)?.Arity ?? 0; + + if (arity > 0 && arity < TupleTypeSymbol.RestPosition && typeToCheck.IsTupleCompatible(out tupleCardinality)) + { + tupleCardinality += (TupleTypeSymbol.RestPosition - 1) * levelsOfNesting; + return true; + } + } + } + + tupleCardinality = 0; + return false; + } + #region INamedTypeSymbol Members int INamedTypeSymbol.Arity @@ -1370,6 +1429,16 @@ ISymbol INamedTypeSymbol.AssociatedSymbol } } + /// + /// If this symbol represents a tuple type, get the types of the tuple's elements. + /// + ImmutableArray INamedTypeSymbol.TupleElementTypes => StaticCast.From(this.TupleElementTypes); + + /// + /// If this symbol represents a tuple type, get the names of the tuple's elements. + /// + ImmutableArray INamedTypeSymbol.TupleElementNames => this.TupleElementNames; + #endregion #region ISymbol Members diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs index eac7cbac4386d..f1cff9f7e76fa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs @@ -26,6 +26,11 @@ internal sealed class RetargetingMethodSymbol : WrapperMethodSymbol /// private readonly RetargetingModuleSymbol _retargetingModule; + /// + /// The underlying MethodSymbol. + /// + private readonly MethodSymbol _underlyingMethod; + private ImmutableArray _lazyTypeParameters; private ImmutableArray _lazyParameters; @@ -48,12 +53,13 @@ internal sealed class RetargetingMethodSymbol : WrapperMethodSymbol private TypeSymbol _lazyReturnType; public RetargetingMethodSymbol(RetargetingModuleSymbol retargetingModule, MethodSymbol underlyingMethod) - : base(underlyingMethod) { Debug.Assert((object)retargetingModule != null); + Debug.Assert((object)underlyingMethod != null); Debug.Assert(!(underlyingMethod is RetargetingMethodSymbol)); _retargetingModule = retargetingModule; + _underlyingMethod = underlyingMethod; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator @@ -72,6 +78,14 @@ public RetargetingModuleSymbol RetargetingModule } } + public override MethodSymbol UnderlyingMethod + { + get + { + return _underlyingMethod; + } + } + public override ImmutableArray TypeParameters { get diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs index a426a20a47003..2ddac7c8ea011 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs @@ -23,6 +23,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal class SubstitutedMethodSymbol : WrapperMethodSymbol { private readonly NamedTypeSymbol _containingType; + private readonly MethodSymbol _underlyingMethod; private readonly TypeMap _inputMap; private readonly MethodSymbol _constructedFrom; @@ -43,10 +44,11 @@ internal SubstitutedMethodSymbol(SubstitutedNamedTypeSymbol containingSymbol, Me } protected SubstitutedMethodSymbol(NamedTypeSymbol containingSymbol, TypeMap map, MethodSymbol originalDefinition, MethodSymbol constructedFrom) - : base (originalDefinition) { + Debug.Assert((object)originalDefinition != null); Debug.Assert(originalDefinition.IsDefinition); _containingType = containingSymbol; + _underlyingMethod = originalDefinition; _inputMap = map; if ((object)constructedFrom != null) { @@ -61,6 +63,14 @@ protected SubstitutedMethodSymbol(NamedTypeSymbol containingSymbol, TypeMap map, } } + public override MethodSymbol UnderlyingMethod + { + get + { + return _underlyingMethod; + } + } + public override MethodSymbol ConstructedFrom { get diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor.cs index 9dfc89f512f39..a4382285e92b9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor.cs @@ -28,11 +28,6 @@ public virtual void VisitArrayType(ArrayTypeSymbol symbol) DefaultVisit(symbol); } - public virtual void VisitTupleType(TupleTypeSymbol symbol) - { - DefaultVisit(symbol); - } - public virtual void VisitAssembly(AssemblySymbol symbol) { DefaultVisit(symbol); diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`1.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`1.cs index e3f82328d3bbb..2d7aa7ef0056c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`1.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`1.cs @@ -28,11 +28,6 @@ public virtual TResult VisitArrayType(ArrayTypeSymbol symbol) return DefaultVisit(symbol); } - public virtual TResult VisitTupleType(TupleTypeSymbol symbol) - { - return DefaultVisit(symbol); - } - public virtual TResult VisitAssembly(AssemblySymbol symbol) { return DefaultVisit(symbol); diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`2.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`2.cs index 9db0ba9701841..9078491038d48 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`2.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolVisitor`2.cs @@ -104,18 +104,6 @@ public virtual TResult VisitArrayType(ArrayTypeSymbol symbol, TArgument argument return DefaultVisit(symbol, argument); } - /// - /// Called when visiting an ; Override this with specific - /// implementation; Calling if it's not overridden - /// - /// The visited symbol - /// Additional argument - /// - public virtual TResult VisitTupleType(TupleTypeSymbol symbol, TArgument argument) - { - return DefaultVisit(symbol, argument); - } - /// /// Called when visiting a ; Override this with specific /// implementation; Calling if it's not overridden diff --git a/src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs index f35b335ce37d8..916a50be84d5e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs @@ -7,87 +7,67 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// - /// A TupleFieldSymbol represents the field of a tuple type, such as (int, byte).Item2 or (int a, long b).a + /// Represents a non-element field of a tuple type (such as (int, byte).Rest) + /// that is backed by a real field within the tuple underlying type. /// - internal sealed class TupleFieldSymbol : FieldSymbol + internal class TupleFieldSymbol : WrapperFieldSymbol { - private readonly string _name; - private readonly TypeSymbol _type; - private readonly TupleTypeSymbol _containingTuple; - private readonly int _position; - private readonly FieldSymbol _underlyingFieldOpt; + protected readonly TupleTypeSymbol _containingTuple; /// - /// Missing underlying field is handled for error recovery - /// A tuple without backing fields is usable for binding purposes, since we know its name and type, - /// but caller is supposed to report some kind of error at declaration. - /// - /// position is 1 for Item1. + /// If this field represents a tuple element (including the name match), + /// id is an index of the element (zero-based). + /// Otherwise, (-1 - [index in members array]); /// - private TupleFieldSymbol(string name, TupleTypeSymbol containingTuple, TypeSymbol type, int position, FieldSymbol underlyingFieldOpt) - { - _name = name; - _containingTuple = containingTuple; - _underlyingFieldOpt = underlyingFieldOpt; - _type = type; - _position = position; - } + private readonly int _tupleFieldId; - /// - /// Copy this tuple field, but modify it to use the new containing tuple, link type and field type. - /// - internal TupleFieldSymbol WithType(TupleTypeSymbol newContainingTuple, NamedTypeSymbol newlinkType, TypeSymbol newFieldType) + public TupleFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId) + : base(underlyingField) { - FieldSymbol newUnderlyingFieldOpt = _underlyingFieldOpt?.OriginalDefinition.AsMember(newlinkType); - Debug.Assert(newUnderlyingFieldOpt == null || newUnderlyingFieldOpt.Type == newFieldType); - - return new TupleFieldSymbol(_name, newContainingTuple, newFieldType, _position, newUnderlyingFieldOpt); + _containingTuple = container; + _tupleFieldId = tupleFieldId; } - /// - /// Copy this tuple field, but modify it to use the new containing tuple, and field name. - /// - internal TupleFieldSymbol WithName(TupleTypeSymbol newContainingTuple, string newName) + public override bool IsTupleField { - return new TupleFieldSymbol(newName, newContainingTuple, _type, _position, _underlyingFieldOpt); + get + { + return true; + } } /// - /// Helps construct a TupleFieldSymbol. - /// - /// Note that errors related to underlying field are ignored. + /// If this field represents a tuple element (including the name match), + /// id is an index of the element (zero-based). + /// Otherwise, (-1 - [index in members array]); /// - internal static TupleFieldSymbol Create(string elementName, TupleTypeSymbol containingTuple, NamedTypeSymbol linkType, int fieldIndex, AssemblySymbol accessWithin) + public int TupleFieldId { - int fieldRemainder; // one-based - int fieldChainLength = TupleTypeSymbol.NumberOfValueTuples(fieldIndex + 1, out fieldRemainder); - - WellKnownMember wellKnownTypeMember = TupleTypeSymbol.GetTupleTypeMember(linkType.Arity, fieldRemainder); - var linkField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(linkType.OriginalDefinition, wellKnownTypeMember, accessWithin); - FieldSymbol underlyingField = linkField?.AsMember(linkType); - - return new TupleFieldSymbol(elementName, containingTuple, linkType.TypeArgumentsNoUseSiteDiagnostics[fieldRemainder - 1], fieldIndex + 1, underlyingField); + get + { + return _tupleFieldId; + } } - public override string Name + public override FieldSymbol TupleUnderlyingField { get { - return _name; + return _underlyingField; } } - /// - /// Returns the position of this field within the tuple. - /// For instance, the position for Item1 is 1. - /// - public int Position => _position; - public override Symbol AssociatedSymbol { get { - return null; + Symbol underlyingAssociated = _underlyingField.AssociatedSymbol; + if ((object)underlyingAssociated == null) + { + return null; + } + + return _containingTuple.GetTupleMemberSymbolForUnderlyingMember(underlyingAssociated); } } @@ -103,55 +83,67 @@ public override ImmutableArray CustomModifiers { get { - return _underlyingFieldOpt?.CustomModifiers ?? ImmutableArray.Empty; + return _underlyingField.CustomModifiers; } } - public override Accessibility DeclaredAccessibility + internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound) { - get - { - return _underlyingFieldOpt?.DeclaredAccessibility ?? Accessibility.Public; - } + return _underlyingField.GetFieldType(fieldsBeingBound); } - public override bool IsConst + public override ImmutableArray GetAttributes() { - get - { - return _underlyingFieldOpt?.IsConst ?? false; - } + return _underlyingField.GetAttributes(); } - public override bool IsReadOnly + internal override DiagnosticInfo GetUseSiteDiagnostic() { - get - { - return _underlyingFieldOpt?.IsReadOnly ?? false; - } + DiagnosticInfo result = base.GetUseSiteDiagnostic(); + MergeUseSiteDiagnostics(ref result, _underlyingField.GetUseSiteDiagnostic()); + return result; } - public override bool IsStatic + public override sealed int GetHashCode() { - get - { - return _underlyingFieldOpt?.IsStatic ?? false; - } + return Hash.Combine(_containingTuple.GetHashCode(), _tupleFieldId.GetHashCode()); } - public override bool IsVolatile + public override sealed bool Equals(object obj) { - get + return Equals(obj as TupleFieldSymbol); + } + + public bool Equals(TupleFieldSymbol other) + { + if ((object)other == this) { - return _underlyingFieldOpt?.IsVolatile ?? false; + return true; } + + return (object)other != null && _tupleFieldId == other._tupleFieldId && _containingTuple == other._containingTuple; + } + } + + /// + /// Represents an element field of a tuple type (such as (int, byte).Item1) + /// that is backed by a real field with the same name within the tuple underlying type. + /// + internal class TupleElementFieldSymbol : TupleFieldSymbol + { + private readonly ImmutableArray _locations; + + public TupleElementFieldSymbol(TupleTypeSymbol container, FieldSymbol underlyingField, int tupleFieldId, Location location) + : base(container, underlyingField, tupleFieldId) + { + _locations = location == null ? ImmutableArray.Empty : ImmutableArray.Create(location); } public override ImmutableArray Locations { get { - return ImmutableArray.Empty; + return _locations; } } @@ -159,43 +151,70 @@ public override ImmutableArray DeclaringSyntaxReferences { get { - return ImmutableArray.Empty; + return GetDeclaringSyntaxReferenceHelper(_locations); } } - internal override bool HasRuntimeSpecialName + public override bool IsImplicitlyDeclared { get { - return _underlyingFieldOpt?.HasRuntimeSpecialName ?? false; + return false; } } - internal override bool HasSpecialName + internal override int? TypeLayoutOffset { get { - return _underlyingFieldOpt?.HasSpecialName ?? false; + if (_underlyingField.ContainingType != _containingTuple.TupleUnderlyingType) + { + return null; + } + + return base.TypeLayoutOffset; } } - internal override bool IsNotSerialized + public override Symbol AssociatedSymbol { get { - return _underlyingFieldOpt?.IsNotSerialized ?? false; + if (_underlyingField.ContainingType != _containingTuple.TupleUnderlyingType) + { + return null; + } + + return base.AssociatedSymbol; } } + } + + /// + /// Represents an element field of a tuple type (such as (int a, byte b).a, or (int a, byte b).b) + /// that is backed by a real field with a different name within the tuple underlying type. + /// + internal sealed class TupleRenamedElementFieldSymbol : TupleElementFieldSymbol + { + private readonly string _name; + + 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; + } - internal override MarshalPseudoCustomAttributeData MarshallingInformation + public override string Name { get { - return _underlyingFieldOpt?.MarshallingInformation; + return _name; } } - internal override ObsoleteAttributeData ObsoleteAttributeData + internal override int? TypeLayoutOffset { get { @@ -203,22 +222,12 @@ internal override ObsoleteAttributeData ObsoleteAttributeData } } - internal override int? TypeLayoutOffset + public override Symbol AssociatedSymbol { get { - return _underlyingFieldOpt?.TypeLayoutOffset; + return null; } } - - internal override ConstantValue GetConstantValue(ConstantFieldsInProgress inProgress, bool earlyDecodingWellKnownAttributes) - { - return _underlyingFieldOpt?.GetConstantValue(inProgress, earlyDecodingWellKnownAttributes); - } - - internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound) - { - return _type; - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs index 01006680b4727..3d926637e9bbb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.InteropServices; using Microsoft.Cci; +using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.RuntimeMembers; using Roslyn.Utilities; @@ -15,64 +16,45 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols /// /// A TupleTypeSymbol represents a tuple type, such as (int, byte) or (int a, long b). /// - internal sealed class TupleTypeSymbol : NamedTypeSymbol + internal sealed class TupleTypeSymbol : WrapperNamedTypeSymbol { - private readonly NamedTypeSymbol _underlyingType; - private readonly ImmutableArray _fields; - private readonly bool _hasFriendlyNames; + private readonly ImmutableArray _locations; + private readonly ImmutableArray _elementLocations; + private readonly ImmutableArray _elementNames; + private readonly ImmutableArray _elementTypes; + private ImmutableArray _lazyMembers; + private SmallDictionary _lazyUnderlyingDefinitionToMemberMap; internal const int RestPosition = 8; // The Rest field is in 8th position + internal const string TupleTypeName = "ValueTuple"; - /// - /// Construct a TupleTypeSymbol from it's underlying ValueTuple type and element names. - /// - /// Parameter elementsNames has to empty or fully populated. - /// - private TupleTypeSymbol( - NamedTypeSymbol underlyingType, - ImmutableArray elementNames, - AssemblySymbol accessWithin) + public TupleTypeSymbol(Location locationOpt, NamedTypeSymbol underlyingType, ImmutableArray elementLocations, ImmutableArray elementNames, ImmutableArray elementTypes) + : this(locationOpt == null ? ImmutableArray.Empty : ImmutableArray.Create(locationOpt), + underlyingType, elementLocations, elementNames, elementTypes) { - _underlyingType = underlyingType; - _hasFriendlyNames = !elementNames.IsDefault; - - // build the fields - int approxSize = elementNames.IsDefault ? underlyingType.Arity : elementNames.Length; - var fieldsBuilder = ArrayBuilder.GetInstance(approxSize); - NamedTypeSymbol currentLinkType = underlyingType; - int fieldIndex = 0; - - while (currentLinkType.Arity == RestPosition) - { - for (int i = 0; i < RestPosition - 1; i++) - { - string elementName = TupleMemberName(elementNames, fieldIndex + 1); - var field = TupleFieldSymbol.Create(elementName, this, currentLinkType, fieldIndex, accessWithin); - fieldsBuilder.Add(field); - - fieldIndex++; - } - - currentLinkType = (NamedTypeSymbol)currentLinkType.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1]; - } - - for (int i = 0; i < currentLinkType.Arity; i++) - { - string elementName = TupleMemberName(elementNames, fieldIndex + 1); - var field = TupleFieldSymbol.Create(elementName, this, currentLinkType, fieldIndex, accessWithin); - fieldsBuilder.Add(field); + } - fieldIndex++; - } + public TupleTypeSymbol(ImmutableArray locations, NamedTypeSymbol underlyingType, ImmutableArray elementLocations, ImmutableArray elementNames, ImmutableArray elementTypes) + : base(underlyingType) + { + Debug.Assert(elementLocations.IsDefault || elementNames.IsDefault || elementLocations.Length == elementNames.Length); + Debug.Assert(elementLocations.IsDefault || elementLocations.Length == elementTypes.Length); + Debug.Assert(elementNames.IsDefault || elementNames.Length == elementTypes.Length); + Debug.Assert(!underlyingType.IsTupleType); - _fields = fieldsBuilder.ToImmutableAndFree(); + _elementLocations = elementLocations; + _elementNames = elementNames; + _elementTypes = elementTypes; + _locations = locations; } /// /// Helps create a TupleTypeSymbol from source. /// - internal static TupleTypeSymbol Create( + internal static NamedTypeSymbol Create( + Location locationOpt, ImmutableArray elementTypes, + ImmutableArray elementLocations, ImmutableArray elementNames, CSharpCompilation compilation, CSharpSyntaxNode syntax = null, @@ -90,64 +72,115 @@ internal sealed class TupleTypeSymbol : NamedTypeSymbol NamedTypeSymbol underlyingType = GetTupleUnderlyingType(elementTypes, syntax, compilation, diagnostics); - return new TupleTypeSymbol(underlyingType, elementNames, compilation.Assembly); + return Create(locationOpt, underlyingType, elementLocations, elementNames); } - /// - /// Copy the original tuple, but modify it to use the new underlying type. - /// - private TupleTypeSymbol(TupleTypeSymbol originalTuple, - NamedTypeSymbol newUnderlyingType) + public static TupleTypeSymbol Create(Location locationOpt, NamedTypeSymbol tupleCompatibleType, ImmutableArray elementLocations, ImmutableArray elementNames) { - _underlyingType = newUnderlyingType; - _hasFriendlyNames = originalTuple._hasFriendlyNames; + return Create(locationOpt == null ? ImmutableArray.Empty : ImmutableArray.Create(locationOpt), + tupleCompatibleType, elementLocations, elementNames); + } - var fieldsBuilder = ArrayBuilder.GetInstance(originalTuple._fields.Length); + public static TupleTypeSymbol Create(ImmutableArray locations, NamedTypeSymbol tupleCompatibleType, ImmutableArray elementLocations, ImmutableArray elementNames) + { + Debug.Assert(tupleCompatibleType.IsTupleCompatible() && !tupleCompatibleType.IsTupleType); - int fieldIndex = 0; - int remainder = 0; - NamedTypeSymbol currentLinkType = newUnderlyingType; + ImmutableArray elementTypes; - while (true) + if (tupleCompatibleType.Arity == RestPosition) + { + // Ensure all Rest extensions are tuples + tupleCompatibleType = EnsureRestExtensionsAreTuples(tupleCompatibleType); + + var extensionTupleElementTypes = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1].TupleElementTypes; + var typesBuilder = ArrayBuilder.GetInstance(RestPosition - 1 + extensionTupleElementTypes.Length); + typesBuilder.AddRange(tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics, RestPosition - 1); + typesBuilder.AddRange(extensionTupleElementTypes); + elementTypes = typesBuilder.ToImmutableAndFree(); + } + else + { + elementTypes = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics; + } + + return new TupleTypeSymbol(locations, tupleCompatibleType, elementLocations, elementNames, elementTypes); + } + + private static NamedTypeSymbol EnsureRestExtensionsAreTuples(NamedTypeSymbol tupleCompatibleType) + { + if (!tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1].IsTupleType) { - TupleFieldSymbol originalField = originalTuple._fields[fieldIndex]; - TypeSymbol fieldType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[remainder]; - fieldsBuilder.Add(originalField.WithType(this, currentLinkType, fieldType)); + var nonTupleTypeChain = ArrayBuilder.GetInstance(); - fieldIndex++; - if (fieldIndex >= originalTuple._fields.Length) + NamedTypeSymbol currentType = tupleCompatibleType; + do { - break; + nonTupleTypeChain.Add(currentType); + currentType = (NamedTypeSymbol)currentType.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1]; } + while (currentType.Arity == RestPosition); - remainder = fieldIndex % (RestPosition - 1); - if (remainder == 0) + if (!currentType.IsTupleType) { - currentLinkType = (NamedTypeSymbol)currentLinkType.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1]; + nonTupleTypeChain.Add(currentType); } + + Debug.Assert(nonTupleTypeChain.Count > 1); + tupleCompatibleType = nonTupleTypeChain.Pop(); + + var typeArgumentsBuilder = ArrayBuilder.GetInstance(RestPosition); + + do + { + var extensionTuple = Create(null, tupleCompatibleType, default(ImmutableArray), default(ImmutableArray)); + tupleCompatibleType = nonTupleTypeChain.Pop(); + + tupleCompatibleType = ReplaceRestExtensionType(tupleCompatibleType, typeArgumentsBuilder, extensionTuple); + } + while (nonTupleTypeChain.Count != 0); + + typeArgumentsBuilder.Free(); + nonTupleTypeChain.Free(); } - _fields = fieldsBuilder.ToImmutableAndFree(); + return tupleCompatibleType; } - /// - /// Copy the original tuple, but modify it to use new field names. - /// - private TupleTypeSymbol(TupleTypeSymbol originalTuple, - ImmutableArray newElementNames) + private static NamedTypeSymbol ReplaceRestExtensionType(NamedTypeSymbol tupleCompatibleType, ArrayBuilder typeArgumentsBuilder, TupleTypeSymbol extensionTuple) { - _underlyingType = originalTuple._underlyingType; - _hasFriendlyNames = !newElementNames.IsDefault; + var modifiers = default(ImmutableArray>); + + if (tupleCompatibleType.HasTypeArgumentsCustomModifiers) + { + modifiers = tupleCompatibleType.TypeArgumentsCustomModifiers; + } - var fieldsBuilder = ArrayBuilder.GetInstance(originalTuple._fields.Length); - var originalFields = originalTuple._fields; + var arguments = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics; + typeArgumentsBuilder.Clear(); - for (int i = 0; i < originalFields.Length; i++) + for (int i = 0; i < RestPosition - 1; i++) { - fieldsBuilder.Add(originalFields[i].WithName(this, GetFieldNameFromArrayOrDefaultName(newElementNames, i))); + if (!modifiers.IsDefault && !modifiers[i].IsDefaultOrEmpty) + { + typeArgumentsBuilder.Add(new TypeWithModifiers(arguments[i], modifiers[i])); + } + else + { + typeArgumentsBuilder.Add(new TypeWithModifiers(arguments[i])); + } } - _fields = fieldsBuilder.ToImmutableAndFree(); + if (!modifiers.IsDefault && !modifiers[RestPosition - 1].IsDefaultOrEmpty) + { + typeArgumentsBuilder.Add(new TypeWithModifiers(extensionTuple, modifiers[RestPosition - 1])); + } + else + { + typeArgumentsBuilder.Add(new TypeWithModifiers(extensionTuple)); + } + + tupleCompatibleType = tupleCompatibleType.ConstructedFrom.Construct(typeArgumentsBuilder.ToImmutable(), unbound: false); + return tupleCompatibleType; } /// @@ -155,9 +188,9 @@ internal sealed class TupleTypeSymbol : NamedTypeSymbol /// internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType) { - Debug.Assert((object)newUnderlyingType.OriginalDefinition == (object)UnderlyingTupleType.OriginalDefinition); + Debug.Assert((object)newUnderlyingType.OriginalDefinition == (object)_underlyingType.OriginalDefinition); - return new TupleTypeSymbol(this, newUnderlyingType); + return Create(_locations, newUnderlyingType, _elementLocations, _elementNames); } /// @@ -165,24 +198,21 @@ internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType) /// internal TupleTypeSymbol WithElementNames(ImmutableArray newElementNames) { - Debug.Assert(newElementNames.IsDefault || this._fields.Length == newElementNames.Length); + Debug.Assert(newElementNames.IsDefault || this._elementTypes.Length == newElementNames.Length); - var originalFields = _fields; - for (int i = 0; i < originalFields.Length; i++) + if (this._elementNames.IsDefault) { - var originalField = originalFields[i]; - var originalName = originalField.Name; - var newName = GetFieldNameFromArrayOrDefaultName(newElementNames, i); - - if (originalName != newName) + if (newElementNames.IsDefault) { - // at least one name is different - return new TupleTypeSymbol(this, newElementNames); + return this; } } + else if (!newElementNames.IsDefault && this._elementNames.SequenceEqual(newElementNames)) + { + return this; + } - // all names are the same - return this; + return new TupleTypeSymbol(null, _underlyingType, default(ImmutableArray), newElementNames, _elementTypes); } /// @@ -200,7 +230,7 @@ internal static void GetUnderlyingTypeChain(NamedTypeSymbol underlyingTupleType, underlyingTupleTypeChain.Add(currentType); if (currentType.Arity == TupleTypeSymbol.RestPosition) { - currentType = (NamedTypeSymbol)currentType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1]; + currentType = (NamedTypeSymbol)currentType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType; } else { @@ -219,6 +249,12 @@ internal static void AddElementTypes(NamedTypeSymbol underlyingTupleType, ArrayB while (true) { + if (currentType.IsTupleType) + { + tupleElementTypes.AddRange(currentType.TupleElementTypes); + break; + } + var regularElements = Math.Min(currentType.Arity, TupleTypeSymbol.RestPosition - 1); tupleElementTypes.AddRange(currentType.TypeArguments, regularElements); @@ -233,27 +269,20 @@ internal static void AddElementTypes(NamedTypeSymbol underlyingTupleType, ArrayB } } - /// - /// Given an array of names returns a name at given position or a default name for that position. - /// - private static string GetFieldNameFromArrayOrDefaultName(ImmutableArray elementNames, int elementIndex) - { - return elementNames.IsDefault ? TupleMemberName(elementIndex + 1) : elementNames[elementIndex]; - } - /// /// Returns the nested type at a certain depth. /// /// For depth=0, just return the tuple type as-is. /// For depth=1, returns the nested tuple type at position 8. /// - internal static NamedTypeSymbol GetNestedTupleType(NamedTypeSymbol tupleType, int depth) + private static NamedTypeSymbol GetNestedTupleUnderlyingType(NamedTypeSymbol topLevelUnderlyingType, int depth) { - NamedTypeSymbol found = tupleType; + NamedTypeSymbol found = topLevelUnderlyingType; for (int i = 0; i < depth; i++) { - found = (NamedTypeSymbol)found.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1]; + found = (NamedTypeSymbol)found.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1].TupleUnderlyingType; } + return found; } @@ -261,7 +290,7 @@ internal static NamedTypeSymbol GetNestedTupleType(NamedTypeSymbol tupleType, in /// Returns the number of nestings required to represent numElements as nested ValueTuples. /// For example, for 8 elements, you need 2 ValueTuples and the remainder (ie the size of the last nested ValueTuple) is 1. /// - internal static int NumberOfValueTuples(int numElements, out int remainder) + private static int NumberOfValueTuples(int numElements, out int remainder) { remainder = (numElements - 1) % (RestPosition - 1) + 1; return (numElements - 1) / (RestPosition - 1) + 1; @@ -316,7 +345,7 @@ private static NamedTypeSymbol GetTupleUnderlyingType(ImmutableArray /// For example, for arity=2: /// returns WellKnownType.System_ValueTuple_T2 /// - internal static WellKnownType GetTupleType(int arity) + private static WellKnownType GetTupleType(int arity) { if (arity > RestPosition) { @@ -436,11 +465,6 @@ internal static string TupleMemberName(int position) return "Item" + position; } - internal static string TupleMemberName(ImmutableArray elementNames, int position) - { - return elementNames.IsDefault ? TupleMemberName(position) : elementNames[position - 1]; - } - /// /// Checks whether the field name is reserved and tells us which position it's reserved for. /// @@ -480,27 +504,27 @@ internal static int IsMemberNameReserved(string name) /// /// Type that we'll try to find member in. /// A reference to a well-known member type descriptor. Note however that the type in that descriptor is ignored here. - /// The assembly referencing the type. - internal static Symbol GetWellKnownMemberInType(NamedTypeSymbol type, WellKnownMember relativeMember, AssemblySymbol accessWithin) + internal static Symbol GetWellKnownMemberInType(NamedTypeSymbol type, WellKnownMember relativeMember) { Debug.Assert(relativeMember >= 0 && relativeMember < WellKnownMember.Count); Debug.Assert(type.IsDefinition); MemberDescriptor relativeDescriptor = WellKnownMembers.GetDescriptor(relativeMember); - return CSharpCompilation.GetRuntimeMember(type, ref relativeDescriptor, CSharpCompilation.SpecialMembersSignatureComparer.Instance, accessWithinOpt: accessWithin); + return CSharpCompilation.GetRuntimeMember(type, ref relativeDescriptor, CSharpCompilation.SpecialMembersSignatureComparer.Instance, + accessWithinOpt: null); // force lookup of public members only } /// /// Lookup well-known member declaration in provided type and reports diagnostics. /// - internal static Symbol GetWellKnownMemberInType(NamedTypeSymbol type, WellKnownMember relativeMember, AssemblySymbol accessWithin, DiagnosticBag diagnostics, SyntaxNode syntax) + internal static Symbol GetWellKnownMemberInType(NamedTypeSymbol type, WellKnownMember relativeMember, DiagnosticBag diagnostics, SyntaxNode syntax) { - Symbol member = GetWellKnownMemberInType(type, relativeMember, accessWithin); + Symbol member = GetWellKnownMemberInType(type, relativeMember); if ((object)member == null) { MemberDescriptor relativeDescriptor = WellKnownMembers.GetDescriptor(relativeMember); - Binder.Error(diagnostics, ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, syntax, relativeDescriptor.Name, type, accessWithin); + Binder.Error(diagnostics, ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, syntax, relativeDescriptor.Name, type, type.ContainingAssembly); } else { @@ -517,7 +541,7 @@ internal static Symbol GetWellKnownMemberInType(NamedTypeSymbol type, WellKnownM /// /// The ValueTuple type for this tuple. /// - internal NamedTypeSymbol UnderlyingTupleType + public override NamedTypeSymbol TupleUnderlyingType { get { @@ -525,31 +549,6 @@ internal NamedTypeSymbol UnderlyingTupleType } } - internal bool HasFriendlyNames => _hasFriendlyNames; - - public override ImmutableArray TupleElementTypes - { - get - { - return _fields.SelectAsArray(f => (ITypeSymbol)f.Type); - } - } - - public override ImmutableArray TupleElementNames - { - get - { - if (_hasFriendlyNames) - { - return _fields.SelectAsArray(f => f.Name); - } - - return default(ImmutableArray); - } - } - - internal ImmutableArray Fields => _fields; - internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics { get @@ -558,7 +557,7 @@ internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics } } - internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved = null) + internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved) { return _underlyingType.InterfacesNoUseSiteDiagnostics(basesBeingResolved); } @@ -595,39 +594,335 @@ public override bool IsTupleType } } - internal sealed override ObsoleteAttributeData ObsoleteAttributeData + public override bool IsImplicitlyDeclared { get { - return null; + return false; + } + } + + public override ImmutableArray TupleElementTypes + { + get + { + return _elementTypes; + } + } + + public override ImmutableArray TupleElementNames + { + get + { + return _elementNames; } } public override ImmutableArray GetMembers() { - return ImmutableArray.CastUp(_fields); + if (_lazyMembers.IsDefault) + { + ImmutableInterlocked.InterlockedInitialize(ref _lazyMembers, CreateMembers()); + } + + return _lazyMembers; + } + + private ImmutableArray CreateMembers() + { + var namesOfVirtualFields = ArrayBuilder.GetInstance(_elementTypes.Length); + + if (_elementNames.IsDefault) + { + for (int i = 1; i <= _elementTypes.Length; i++) + { + namesOfVirtualFields.Add(TupleMemberName(i)); + } + } + else + { + namesOfVirtualFields.AddRange(_elementNames); + } + + var members = ArrayBuilder.GetInstance(Math.Max(_elementTypes.Length, _underlyingType.OriginalDefinition.GetMembers().Length)); + + NamedTypeSymbol currentUnderlying = _underlyingType; + int currentNestingLevel = 0; + + var fieldsForElements = ArrayBuilder.GetInstance(currentUnderlying.Arity); + + // Lookup field definitions that we are interested in + CollectTargetTupleFields(currentUnderlying, fieldsForElements); + + ImmutableArray underlyingMembers = currentUnderlying.OriginalDefinition.GetMembers(); + + while (true) + { + foreach (Symbol member in underlyingMembers) + { + switch (member.Kind) + { + case SymbolKind.Method: + if (currentNestingLevel == 0) + { + members.Add(new TupleMethodSymbol(this, ((MethodSymbol)member).AsMember(currentUnderlying))); + } + break; + + case SymbolKind.Field: + var field = (FieldSymbol)member; + + int tupleFieldIndex = fieldsForElements.IndexOf(field, ReferenceEqualityComparer.Instance); + if (tupleFieldIndex >= 0) + { + // This is a tuple backing field + var fieldSymbol = field.AsMember(currentUnderlying); + + if (currentNestingLevel != 0) + { + // This is a matching field, but it is in the extension tuple + tupleFieldIndex += (RestPosition - 1) * currentNestingLevel; + + + string defaultName = TupleMemberName(tupleFieldIndex + 1); + // Add a field with default name if the given name is different + if (namesOfVirtualFields[tupleFieldIndex] != defaultName) + { + // The name given doesn't match default name Item8, etc. + members.Add(new TupleRenamedElementFieldSymbol(this, fieldSymbol, defaultName, -members.Count - 1, null)); + } + + // Add a field with the given name + var location = _elementLocations.IsDefault ? null : _elementLocations[tupleFieldIndex]; + + if (field.Name == namesOfVirtualFields[tupleFieldIndex]) + { + members.Add(new TupleElementFieldSymbol(this, fieldSymbol, tupleFieldIndex, location)); + } + else + { + members.Add(new TupleRenamedElementFieldSymbol(this, fieldSymbol, namesOfVirtualFields[tupleFieldIndex], + tupleFieldIndex, location)); + } + } + else if (field.Name == namesOfVirtualFields[tupleFieldIndex]) + { + members.Add(new TupleElementFieldSymbol(this, fieldSymbol, tupleFieldIndex, + _elementLocations.IsDefault ? null : _elementLocations[tupleFieldIndex])); + } + else + { + // Add a field with default name + members.Add(new TupleFieldSymbol(this, fieldSymbol, -members.Count - 1)); + + // Add a field with the given name + members.Add(new TupleRenamedElementFieldSymbol(this, fieldSymbol, namesOfVirtualFields[tupleFieldIndex], tupleFieldIndex, + _elementLocations.IsDefault ? null : _elementLocations[tupleFieldIndex])); + } + + namesOfVirtualFields[tupleFieldIndex] = null; // mark as handled + } + else if (currentNestingLevel == 0) + { + // field at the top level didn't match a tuple backing field, simply add. + members.Add(new TupleFieldSymbol(this, field.AsMember(currentUnderlying), -members.Count - 1)); + } + break; + + case SymbolKind.NamedType: + // We are dropping nested types, if any. Pending real need. + break; + + case SymbolKind.Property: + case SymbolKind.Event: + // PROTOTYPE(tuples): TODO + break; + + default: + if (currentNestingLevel == 0) + { + throw ExceptionUtilities.UnexpectedValue(member.Kind); + } + break; + } + } + + if (currentUnderlying.Arity != RestPosition) + { + break; + } + + var oldUnderlying = currentUnderlying; + currentUnderlying = oldUnderlying.TypeArgumentsNoUseSiteDiagnostics[RestPosition - 1].TupleUnderlyingType; + currentNestingLevel++; + + if (currentUnderlying.Arity != RestPosition) + { + // refresh members and target fields + underlyingMembers = currentUnderlying.OriginalDefinition.GetMembers(); + fieldsForElements.Clear(); + CollectTargetTupleFields(currentUnderlying, fieldsForElements); + } + else + { + Debug.Assert((object)oldUnderlying.OriginalDefinition == currentUnderlying.OriginalDefinition); + } + } + + fieldsForElements.Free(); + + // At the end, add remaining virtual fields + for (int i = 0; i < namesOfVirtualFields.Count; i++) + { + string name = namesOfVirtualFields[i]; + if (name != null) + { + // We couldn't find a backing field for this vitual field. It will be an error to access it. + int fieldRemainder; // one-based + int fieldChainLength = NumberOfValueTuples(i + 1, out fieldRemainder); + NamedTypeSymbol container = GetNestedTupleUnderlyingType(_underlyingType, fieldChainLength - 1).OriginalDefinition; + + var diagnosticInfo = container.IsErrorType() ? + null : + new CSDiagnosticInfo(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, + TupleMemberName(fieldRemainder), + container, + container.ContainingAssembly); + + string defaultName = TupleMemberName(i + 1); + // Add a field with default name if the given name is different + if (name != defaultName) + { + members.Add(new TupleErrorFieldSymbol(this, defaultName, -members.Count - 1, null, _elementTypes[i], diagnosticInfo)); + } + + members.Add(new TupleErrorFieldSymbol(this, name, i, + _elementLocations.IsDefault ? null : _elementLocations[i], + _elementTypes[i], + diagnosticInfo)); + } + } + + return members.ToImmutableAndFree(); + } + + private static void CollectTargetTupleFields(NamedTypeSymbol underlying, ArrayBuilder fieldsForElements) + { + underlying = underlying.OriginalDefinition; + int fieldsPerType = Math.Min(underlying.Arity, RestPosition - 1); + + for (int i = 0; i < fieldsPerType; i++) + { + WellKnownMember wellKnownTupleField = GetTupleTypeMember(underlying.Arity, i + 1); + fieldsForElements.Add((FieldSymbol)GetWellKnownMemberInType(underlying, wellKnownTupleField)); + } + } + + private SmallDictionary UnderlyingDefinitionToMemberMap + { + get + { + if (_lazyUnderlyingDefinitionToMemberMap == null) + { + var map = new SmallDictionary(); + + var underlyingDefinition = _underlyingType.OriginalDefinition; + var members = GetMembers(); + Symbol underlyingMemberDefinition; + + foreach (var member in members) + { + switch (member.Kind) + { + case SymbolKind.Method: + underlyingMemberDefinition = ((MethodSymbol)member).TupleUnderlyingMethod.OriginalDefinition; + break; + + case SymbolKind.Field: + underlyingMemberDefinition = ((FieldSymbol)member).TupleUnderlyingField?.OriginalDefinition; + break; + + case SymbolKind.NamedType: + underlyingMemberDefinition = null; + break; + + case SymbolKind.Property: + case SymbolKind.Event: + // PROTOTYPE(tuples): TODO + underlyingMemberDefinition = null; + break; + + default: + throw ExceptionUtilities.UnexpectedValue(member.Kind); + } + + if ((object)underlyingMemberDefinition != null && underlyingMemberDefinition.ContainingType == underlyingDefinition) + { + map.Add(underlyingMemberDefinition, member); + } + } + + _lazyUnderlyingDefinitionToMemberMap = map; + } + + return _lazyUnderlyingDefinitionToMemberMap; + } + } + + public Symbol GetTupleMemberSymbolForUnderlyingMember(Symbol underlyingMember) + { + underlyingMember = underlyingMember.OriginalDefinition; + if (underlyingMember.ContainingType == _underlyingType.OriginalDefinition) + { + Symbol result; + if (UnderlyingDefinitionToMemberMap.TryGetValue(underlyingMember, out result)) + { + return result; + } + } + + return null; } public override ImmutableArray GetMembers(string name) { - return ImmutableArray.CastUp(_fields).WhereAsArray(field => field.Name == name); + return GetMembers().WhereAsArray(m => m.Name == name); } public override ImmutableArray GetTypeMembers() { + // do not support nested types at the moment + Debug.Assert(!GetMembers().Any(m => m.Kind == SymbolKind.NamedType)); return ImmutableArray.Empty; } public override ImmutableArray GetTypeMembers(string name) { + // do not support nested types at the moment + Debug.Assert(!GetMembers().Any(m => m.Kind == SymbolKind.NamedType)); return ImmutableArray.Empty; } public override ImmutableArray GetTypeMembers(string name, int arity) { + // do not support nested types at the moment + Debug.Assert(!GetMembers().Any(m => m.Kind == SymbolKind.NamedType)); return ImmutableArray.Empty; } + public override NamedTypeSymbol EnumUnderlyingType + { + get + { + return _underlyingType.EnumUnderlyingType; + } + } + + public override ImmutableArray GetAttributes() + { + return _underlyingType.GetAttributes(); + } + public override SymbolKind Kind { get @@ -659,7 +954,7 @@ public override ImmutableArray Locations { get { - return ImmutableArray.Empty; + return _locations; } } @@ -667,33 +962,19 @@ public override ImmutableArray DeclaringSyntaxReferences { get { - return ImmutableArray.Empty; + return GetDeclaringSyntaxReferenceHelper(_locations); } } - internal override TResult Accept(CSharpSymbolVisitor visitor, TArgument argument) - { - return visitor.VisitTupleType(this, argument); - } - - public override void Accept(CSharpSymbolVisitor visitor) - { - visitor.VisitTupleType(this); - } - - public override TResult Accept(CSharpSymbolVisitor visitor) - { - return visitor.VisitTupleType(this); - } - internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiers, bool ignoreDynamic) { if (ignoreDynamic) { if (t2?.IsTupleType == true) { - t2 = ((TupleTypeSymbol)t2).UnderlyingTupleType; + t2 = t2.TupleUnderlyingType; } + return _underlyingType.Equals(t2, ignoreCustomModifiers, ignoreDynamic); } @@ -720,17 +1001,22 @@ private bool Equals(TupleTypeSymbol other, bool ignoreCustomModifiers, bool igno // Make sure field names are the same. if (!ignoreDynamic) { - var fields = this._fields; - var otherFields = other._fields; - var count = fields.Length; - - for (int i = 0; i < count; i++) + if (this._elementNames.IsDefault) { - if (fields[i].Name != otherFields[i].Name) + if (!other._elementNames.IsDefault) { return false; } } + else if (other._elementNames.IsDefault) + { + Debug.Assert(!this._elementNames.IsDefault); + return false; + } + else if (!this._elementNames.SequenceEqual(other._elementNames)) + { + return false; + } } return true; @@ -856,7 +1142,17 @@ public override IEnumerable MemberNames { get { - return _fields.Select(f => f.Name); + var set = PooledHashSet.GetInstance(); + foreach (var member in GetMembers()) + { + var name = member.Name; + if (set.Add(name)) + { + yield return name; + } + } + + set.Free(); } } @@ -876,6 +1172,14 @@ internal override bool IsComImport } } + internal override NamedTypeSymbol ComImportCoClass + { + get + { + return null; + } + } + internal override bool IsWindowsRuntimeImport { get @@ -955,12 +1259,24 @@ internal override AttributeUsageInfo GetAttributeUsageInfo() internal override ImmutableArray GetEarlyAttributeDecodingMembers() { - return this.GetMembers(); + var underlying = _underlyingType.GetEarlyAttributeDecodingMembers(); + if (underlying.IsEmpty) + { + return underlying; + } + + return underlying.SelectAsArray((u, tuple) => tuple.GetTupleMemberSymbolForUnderlyingMember(u), this).WhereAsArray(m => (object)m != null); } internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) { - return this.GetMembers(name); + var underlying = _underlyingType.GetEarlyAttributeDecodingMembers(name); + if (underlying.IsEmpty) + { + return underlying; + } + + return underlying.SelectAsArray((u, tuple) => tuple.GetTupleMemberSymbolForUnderlyingMember(u), this).WhereAsArray(m => (object)m != null); } internal override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) @@ -988,11 +1304,31 @@ internal override IEnumerable GetFieldsToEmit() throw ExceptionUtilities.Unreachable; } + internal override IEnumerable GetEventsToEmit() + { + throw ExceptionUtilities.Unreachable; + } + + internal override IEnumerable GetMethodsToEmit() + { + throw ExceptionUtilities.Unreachable; + } + + internal override IEnumerable GetPropertiesToEmit() + { + throw ExceptionUtilities.Unreachable; + } + internal override ImmutableArray GetInterfacesToEmit() { throw ExceptionUtilities.Unreachable; } + internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + { + throw ExceptionUtilities.Unreachable; + } + #endregion } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleErrorFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleErrorFieldSymbol.cs new file mode 100644 index 0000000000000..04b6b6c0d9c57 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleErrorFieldSymbol.cs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a field of a tuple type (such as (int, byte).Item1) + /// that doesn't have a corresponding backing field within the tuple underlying type. + /// Created in response to an error condition. + /// + internal sealed class TupleErrorFieldSymbol : SynthesizedFieldSymbolBase + { + private readonly TypeSymbol _type; + + /// + /// If this field represents a tuple element (including the name match), + /// id is an index of the element (zero-based). + /// Otherwise, (-1 - [index in members array]); + /// + private readonly int _tupleFieldId; + + private readonly ImmutableArray _locations; + private readonly DiagnosticInfo _useSiteDiagnosticInfo; + + public TupleErrorFieldSymbol(NamedTypeSymbol container, string name, int tupleFieldId, Location location, TypeSymbol type, DiagnosticInfo useSiteDiagnosticInfo) + : base(container, name, isPublic:true, isReadOnly:false, isStatic:false) + { + Debug.Assert(name != null); + _type = type; + _locations = location == null ? ImmutableArray.Empty : ImmutableArray.Create(location); + _useSiteDiagnosticInfo = useSiteDiagnosticInfo; + _tupleFieldId = tupleFieldId; + } + + /// + /// If this field represents a tuple element (including the name match), + /// id is an index of the element (zero-based). + /// Otherwise, (-1 - [index in members array]); + /// + public override bool IsTupleField + { + get + { + return true; + } + } + + public override FieldSymbol TupleUnderlyingField + { + get + { + // Failed to find one + return null; + } + } + + public override ImmutableArray Locations + { + get + { + return _locations; + } + } + + public override ImmutableArray DeclaringSyntaxReferences + { + get + { + return GetDeclaringSyntaxReferenceHelper(_locations); + } + } + + public override bool IsImplicitlyDeclared + { + get + { + return false; + } + } + + internal override bool SuppressDynamicAttribute + { + get + { + return true; + } + } + + internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound) + { + return _type; + } + + internal override DiagnosticInfo GetUseSiteDiagnostic() + { + return _useSiteDiagnosticInfo; + } + + public override sealed int GetHashCode() + { + return Hash.Combine(ContainingType.GetHashCode(), _tupleFieldId.GetHashCode()); + } + + public override bool Equals(object obj) + { + return Equals(obj as TupleErrorFieldSymbol); + } + + public bool Equals(TupleErrorFieldSymbol other) + { + if ((object)other == this) + { + return true; + } + + return (object)other != null && _tupleFieldId == other._tupleFieldId && ContainingType == other.ContainingType; + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs new file mode 100644 index 0000000000000..09a83dca563a8 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs @@ -0,0 +1,203 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Roslyn.Utilities; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a method of a tuple type (such as (int, byte).ToString()) + /// that is backed by a method within the tuple underlying type. + /// + internal sealed class TupleMethodSymbol : WrapperMethodSymbol + { + private readonly TupleTypeSymbol _containingType; + private readonly MethodSymbol _underlyingMethod; + private readonly ImmutableArray _typeParameters; + private ImmutableArray _lazyParameters; + + 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 override bool IsTupleMethod + { + get + { + return true; + } + } + + public override MethodSymbol TupleUnderlyingMethod + { + get + { + return _underlyingMethod.ConstructedFrom; + } + } + + public override MethodSymbol UnderlyingMethod + { + get + { + return _underlyingMethod; + } + } + + public override Symbol AssociatedSymbol + { + get + { + Symbol underlyingAssociated = _underlyingMethod.ConstructedFrom.AssociatedSymbol; + if ((object)underlyingAssociated == null) + { + return null; + } + + return _containingType.GetTupleMemberSymbolForUnderlyingMember(underlyingAssociated); + } + } + + public override Symbol ContainingSymbol + { + get + { + return _containingType; + } + } + + public override ImmutableArray ExplicitInterfaceImplementations + { + get + { + return _underlyingMethod.ConstructedFrom.ExplicitInterfaceImplementations; + } + } + + public override ImmutableArray Parameters + { + get + { + if (_lazyParameters.IsDefault) + { + InterlockedOperations.Initialize(ref _lazyParameters, CreateParameters()); + } + + return _lazyParameters; + } + } + + private ImmutableArray CreateParameters() + { + ImmutableArray underlying = _underlyingMethod.Parameters; + var builder = ArrayBuilder.GetInstance(underlying.Length); + + foreach (var parameter in underlying) + { + builder.Add(new TupleParameterSymbol(this, parameter)); + } + + return builder.ToImmutableAndFree(); + } + + public override bool ReturnsVoid + { + get + { + return _underlyingMethod.ReturnsVoid; + } + } + + public override TypeSymbol ReturnType + { + get + { + return _underlyingMethod.ReturnType; + } + } + + public override ImmutableArray ReturnTypeCustomModifiers + { + get + { + return _underlyingMethod.ReturnTypeCustomModifiers; + } + } + + public override ImmutableArray TypeArguments + { + get + { + return _typeParameters.Cast(); + } + } + + public override ImmutableArray TypeParameters + { + get + { + return _typeParameters; + } + } + + internal override bool IsExplicitInterfaceImplementation + { + get + { + return _underlyingMethod.OriginalDefinition.IsExplicitInterfaceImplementation; + } + } + + public override ImmutableArray GetAttributes() + { + return _underlyingMethod.GetAttributes(); + } + + public override ImmutableArray GetReturnTypeAttributes() + { + return _underlyingMethod.GetReturnTypeAttributes(); + } + + internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) + { + throw ExceptionUtilities.Unreachable; + } + + internal override DiagnosticInfo GetUseSiteDiagnostic() + { + DiagnosticInfo result = base.GetUseSiteDiagnostic(); + MergeUseSiteDiagnostics(ref result, _underlyingMethod.GetUseSiteDiagnostic()); + return result; + } + + public override int GetHashCode() + { + return _underlyingMethod.ConstructedFrom.GetHashCode(); + } + + public override bool Equals(object obj) + { + return Equals(obj as TupleMethodSymbol); + } + + public bool Equals(TupleMethodSymbol other) + { + if ((object)other == this) + { + return true; + } + + return (object)other != null && _containingType == other._containingType && _underlyingMethod.ConstructedFrom == other._underlyingMethod.ConstructedFrom; + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleParameterSymbol.cs new file mode 100644 index 0000000000000..b13b144220497 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleParameterSymbol.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a parameter of a method or a property of a tuple type + /// + internal sealed class TupleParameterSymbol : WrapperParameterSymbol + { + private readonly Symbol _container; + + public TupleParameterSymbol(Symbol container, ParameterSymbol underlyingParameter) + : base(underlyingParameter) + { + Debug.Assert((object)container != null); + _container = container; + } + + public override Symbol ContainingSymbol + { + get + { + return _container; + } + } + + public override int GetHashCode() + { + return _underlyingParameter.GetHashCode(); + } + + public override bool Equals(object obj) + { + return Equals(obj as TupleParameterSymbol); + } + + public bool Equals(TupleParameterSymbol other) + { + if ((object)other == this) + { + return true; + } + + return (object)other != null && _container == other._container && _underlyingParameter == other._underlyingParameter; + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index df73465108992..f2748f3a5bb73 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -554,14 +554,46 @@ public virtual bool IsAnonymousType } /// - /// Is this a symbol for a Tuple + /// Is this a symbol for a Tuple. /// public virtual bool IsTupleType => false; + /// + /// Verify if the given type can be used to back a tuple type and return cardinality of that tuple type in . + /// + /// If method returns true, contains cardinality of the compatible tuple type. + /// + public virtual bool IsTupleCompatible(out int tupleCardinality) + { + tupleCardinality = 0; + return false; + } + + /// + /// Verify if the given type can be used to back a tuple type. + /// + public bool IsTupleCompatible() + { + int countOfItems; + return IsTupleCompatible(out countOfItems); + } + + /// + /// If this is a tuple type symbol, returns the symbol for its underlying type. + /// Otherwise, returns null. + /// + public virtual NamedTypeSymbol TupleUnderlyingType + { + get + { + return null; + } + } + /// /// If this symbol represents a tuple type, get the types of the tuple's elements. /// - public virtual ImmutableArray TupleElementTypes => default(ImmutableArray); + public virtual ImmutableArray TupleElementTypes => default(ImmutableArray); /// /// If this symbol represents a tuple type, get the names of the tuple's elements. @@ -642,6 +674,11 @@ ISymbol ITypeSymbol.FindImplementationForInterfaceMember(ISymbol interfaceMember : null; } + /// + /// Is this a symbol for a Tuple. + /// + bool ITypeSymbol.IsTupleType => this.IsTupleType; + #endregion #region Interface member checks diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index 8fa3309e21ca6..5336edfcc7205 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -464,6 +464,12 @@ public static TypeSymbol VisitType(this TypeSymbol type, Func(this TypeSymbol type, Func internal abstract class WrapperMethodSymbol : MethodSymbol { - /// - /// The underlying MethodSymbol. - /// - protected readonly MethodSymbol _underlyingMethod; - - public WrapperMethodSymbol(MethodSymbol underlyingMethod) + public WrapperMethodSymbol() { - Debug.Assert((object)underlyingMethod != null); - _underlyingMethod = underlyingMethod; } - public MethodSymbol UnderlyingMethod + public abstract MethodSymbol UnderlyingMethod { - get - { - return _underlyingMethod; - } + get; } public override bool IsVararg { get { - return _underlyingMethod.IsVararg; + return UnderlyingMethod.IsVararg; } } @@ -48,7 +38,7 @@ public override bool IsGenericMethod { get { - return _underlyingMethod.IsGenericMethod; + return UnderlyingMethod.IsGenericMethod; } } @@ -56,7 +46,7 @@ public override int Arity { get { - return _underlyingMethod.Arity; + return UnderlyingMethod.Arity; } } @@ -79,7 +69,7 @@ internal override RefKind RefKind { get { - return _underlyingMethod.RefKind; + return UnderlyingMethod.RefKind; } } @@ -95,7 +85,7 @@ internal override RefKind RefKind internal override int ParameterCount { - get { return _underlyingMethod.ParameterCount; } + get { return UnderlyingMethod.ParameterCount; } } public override abstract ImmutableArray Parameters @@ -112,7 +102,7 @@ public override bool IsExtensionMethod { get { - return _underlyingMethod.IsExtensionMethod; + return UnderlyingMethod.IsExtensionMethod; } } @@ -120,7 +110,7 @@ public override bool HidesBaseMethodsByName { get { - return _underlyingMethod.HidesBaseMethodsByName; + return UnderlyingMethod.HidesBaseMethodsByName; } } @@ -133,7 +123,7 @@ public override ImmutableArray Locations { get { - return _underlyingMethod.Locations; + return UnderlyingMethod.Locations; } } @@ -141,7 +131,7 @@ public override ImmutableArray DeclaringSyntaxReferences { get { - return _underlyingMethod.DeclaringSyntaxReferences; + return UnderlyingMethod.DeclaringSyntaxReferences; } } @@ -149,7 +139,7 @@ public override Accessibility DeclaredAccessibility { get { - return _underlyingMethod.DeclaredAccessibility; + return UnderlyingMethod.DeclaredAccessibility; } } @@ -157,7 +147,7 @@ public override bool IsStatic { get { - return _underlyingMethod.IsStatic; + return UnderlyingMethod.IsStatic; } } @@ -165,7 +155,7 @@ public override bool IsVirtual { get { - return _underlyingMethod.IsVirtual; + return UnderlyingMethod.IsVirtual; } } @@ -173,7 +163,7 @@ public override bool IsAsync { get { - return _underlyingMethod.IsAsync; + return UnderlyingMethod.IsAsync; } } @@ -181,7 +171,7 @@ public override bool IsOverride { get { - return _underlyingMethod.IsOverride; + return UnderlyingMethod.IsOverride; } } @@ -189,7 +179,7 @@ public override bool IsAbstract { get { - return _underlyingMethod.IsAbstract; + return UnderlyingMethod.IsAbstract; } } @@ -197,7 +187,7 @@ public override bool IsSealed { get { - return _underlyingMethod.IsSealed; + return UnderlyingMethod.IsSealed; } } @@ -205,7 +195,7 @@ public override bool IsExtern { get { - return _underlyingMethod.IsExtern; + return UnderlyingMethod.IsExtern; } } @@ -213,62 +203,62 @@ public override bool IsImplicitlyDeclared { get { - return _underlyingMethod.IsImplicitlyDeclared; + return UnderlyingMethod.IsImplicitlyDeclared; } } internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) { - return _underlyingMethod.IsMetadataVirtual(ignoreInterfaceImplementationChanges); + return UnderlyingMethod.IsMetadataVirtual(ignoreInterfaceImplementationChanges); } internal override bool IsMetadataFinal { get { - return _underlyingMethod.IsMetadataFinal; + return UnderlyingMethod.IsMetadataFinal; } } internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) { - return _underlyingMethod.IsMetadataNewSlot(ignoreInterfaceImplementationChanges); + return UnderlyingMethod.IsMetadataNewSlot(ignoreInterfaceImplementationChanges); } internal override bool RequiresSecurityObject { get { - return _underlyingMethod.RequiresSecurityObject; + return UnderlyingMethod.RequiresSecurityObject; } } public override DllImportData GetDllImportData() { - return _underlyingMethod.GetDllImportData(); + return UnderlyingMethod.GetDllImportData(); } internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation { get { - return _underlyingMethod.ReturnValueMarshallingInformation; + return UnderlyingMethod.ReturnValueMarshallingInformation; } } internal override bool HasDeclarativeSecurity { - get { return _underlyingMethod.HasDeclarativeSecurity; } + get { return UnderlyingMethod.HasDeclarativeSecurity; } } internal override IEnumerable GetSecurityInformation() { - return _underlyingMethod.GetSecurityInformation(); + return UnderlyingMethod.GetSecurityInformation(); } internal override ImmutableArray GetAppliedConditionalSymbols() { - return _underlyingMethod.GetAppliedConditionalSymbols(); + return UnderlyingMethod.GetAppliedConditionalSymbols(); } public override abstract ImmutableArray GetAttributes(); @@ -280,7 +270,7 @@ internal override ObsoleteAttributeData ObsoleteAttributeData { get { - return _underlyingMethod.ObsoleteAttributeData; + return UnderlyingMethod.ObsoleteAttributeData; } } @@ -288,7 +278,7 @@ public override string Name { get { - return _underlyingMethod.Name; + return UnderlyingMethod.Name; } } @@ -296,20 +286,20 @@ internal override bool HasSpecialName { get { - return _underlyingMethod.HasSpecialName; + return UnderlyingMethod.HasSpecialName; } } public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) { - return _underlyingMethod.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); + return UnderlyingMethod.GetDocumentationCommentXml(preferredCulture, expandIncludes, cancellationToken); } internal override System.Reflection.MethodImplAttributes ImplementationAttributes { get { - return _underlyingMethod.ImplementationAttributes; + return UnderlyingMethod.ImplementationAttributes; } } @@ -317,7 +307,7 @@ public override MethodKind MethodKind { get { - return _underlyingMethod.MethodKind; + return UnderlyingMethod.MethodKind; } } @@ -325,7 +315,7 @@ internal override Microsoft.Cci.CallingConvention CallingConvention { get { - return _underlyingMethod.CallingConvention; + return UnderlyingMethod.CallingConvention; } } @@ -343,7 +333,7 @@ internal override bool IsAccessCheckedOnOverride { get { - return _underlyingMethod.IsAccessCheckedOnOverride; + return UnderlyingMethod.IsAccessCheckedOnOverride; } } @@ -351,7 +341,7 @@ internal override bool IsExternal { get { - return _underlyingMethod.IsExternal; + return UnderlyingMethod.IsExternal; } } @@ -359,7 +349,7 @@ internal override bool HasRuntimeSpecialName { get { - return _underlyingMethod.HasRuntimeSpecialName; + return UnderlyingMethod.HasRuntimeSpecialName; } } @@ -367,7 +357,7 @@ internal override bool ReturnValueIsMarshalledExplicitly { get { - return _underlyingMethod.ReturnValueIsMarshalledExplicitly; + return UnderlyingMethod.ReturnValueIsMarshalledExplicitly; } } @@ -375,7 +365,7 @@ internal override ImmutableArray ReturnValueMarshallingDescriptor { get { - return _underlyingMethod.ReturnValueMarshallingDescriptor; + return UnderlyingMethod.ReturnValueMarshallingDescriptor; } } @@ -383,7 +373,7 @@ internal override bool GenerateDebugInfo { get { - return _underlyingMethod.GenerateDebugInfo; + return UnderlyingMethod.GenerateDebugInfo; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs index 3e10f84f9c112..08ae762746f4e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrappers/WrapperNamedTypeSymbol.cs @@ -133,8 +133,6 @@ public override string GetDocumentationCommentXml(CultureInfo preferredCulture = public override abstract ImmutableArray GetMembers(); - internal override abstract ImmutableArray GetMembersUnordered(); - public override abstract ImmutableArray GetMembers(string name); internal override abstract IEnumerable GetFieldsToEmit(); @@ -149,8 +147,6 @@ public override string GetDocumentationCommentXml(CultureInfo preferredCulture = internal override abstract ImmutableArray GetEarlyAttributeDecodingMembers(string name); - internal override abstract ImmutableArray GetTypeMembersUnordered(); - public override abstract ImmutableArray GetTypeMembers(); public override abstract ImmutableArray GetTypeMembers(string name); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 7f20fee2e980a..19b43f2b5b5d4 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -188,8 +188,13 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 Item7 = item7; Rest = rest; } + + public override string ToString() + { + return base.ToString(); } } +} "; [Fact] @@ -473,18 +478,18 @@ static void Main() var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics( - // (6,22): error CS1729: 'ValueTuple' does not contain a constructor that takes 3 arguments + // (6,22): error CS1729: '(int a, int b)' does not contain a constructor that takes 3 arguments // var x0 = new (int a, int b)(1, 2, 3); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "(int a, int b)").WithArguments("System.ValueTuple", "3").WithLocation(6, 22), - // (9,22): error CS1729: 'ValueTuple' does not contain a constructor that takes 3 arguments + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "(int a, int b)").WithArguments("(int a, int b)", "3").WithLocation(6, 22), + // (9,22): error CS1729: '(int, int)' does not contain a constructor that takes 3 arguments // var x1 = new (int, int)(1, 2, 3); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "(int, int)").WithArguments("System.ValueTuple", "3").WithLocation(9, 22), + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "(int, int)").WithArguments("(int, int)", "3").WithLocation(9, 22), // (12,36): error CS1503: Argument 2: cannot convert from 'string' to 'int' // var x2 = new (int, int)(1, "2"); Diagnostic(ErrorCode.ERR_BadArgType, @"""2""").WithArguments("2", "string", "int").WithLocation(12, 36), - // (15,22): error CS7036: There is no argument given that corresponds to the required formal parameter 'item2' of 'ValueTuple.ValueTuple(int, int)' + // (15,22): error CS7036: There is no argument given that corresponds to the required formal parameter 'item2' of '(int, int).(int, int)' // var x3 = new (int, int)(1); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "(int, int)").WithArguments("item2", "System.ValueTuple.ValueTuple(int, int)").WithLocation(15, 22), + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "(int, int)").WithArguments("item2", "(int, int).(int, int)").WithLocation(15, 22), // (18,40): error CS0117: '(int, int)' does not contain a definition for 'a' // var x4 = new (int, int)(1, 1) {a = 1, Item3 = 2} ; Diagnostic(ErrorCode.ERR_NoSuchMember, "a").WithArguments("(int, int)", "a").WithLocation(18, 40), @@ -1042,6 +1047,177 @@ .maxstack 1 "); } + [Fact] + public void TupleLambdaCapture02() + { + var source = @" +using System; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42)); + } + + public static string Test(T a) + { + var x = (f1: a, f2: a); + + Func f = () => x.ToString(); + + return f(); + } +} +" + trivial2uple; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"{42, 42}"); + comp.VerifyDiagnostics(); + comp.VerifyIL("C.<>c__DisplayClass1_0.b__0()", @" +{ + // Code size 18 (0x12) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ldflda ""(T f1, T f2) C.<>c__DisplayClass1_0.x"" + IL_0006: constrained. ""System.ValueTuple"" + IL_000c: callvirt ""string object.ToString()"" + IL_0011: ret +} +"); + } + + [Fact] + public void TupleLambdaCapture03() + { + var source = @" +using System; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42)); + } + + public static T Test(T a) + { + var x = (f1: a, f2: a); + + Func f = () => x.Test(a); + + return f(); + } +} + +namespace System +{ + // struct with two values + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public U Test(U val) + { + return val; + } + } +} +"; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"42"); + comp.VerifyDiagnostics(); + comp.VerifyIL("C.<>c__DisplayClass1_0.b__0()", @" +{ + // Code size 18 (0x12) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: ldflda ""(T f1, T f2) C.<>c__DisplayClass1_0.x"" + IL_0006: ldarg.0 + IL_0007: ldfld ""T C.<>c__DisplayClass1_0.a"" + IL_000c: call ""T System.ValueTuple.Test(T)"" + IL_0011: ret +} +"); + } + + [Fact] + public void TupleLambdaCapture04() + { + var source = @" +using System; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42)); + } + + public static T Test(T a) + { + var x = (f1: 1, f2: 2); + + Func f = () => x.Test(a); + + return f(); + } +} + +namespace System +{ + // struct with two values + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public U Test(U val) + { + return val; + } + } +} +"; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"42"); + comp.VerifyDiagnostics(); + comp.VerifyIL("C.<>c__DisplayClass1_0.b__0()", @" +{ + // Code size 18 (0x12) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: ldflda ""(int f1, int f2) C.<>c__DisplayClass1_0.x"" + IL_0006: ldarg.0 + IL_0007: ldfld ""T C.<>c__DisplayClass1_0.a"" + IL_000c: call ""T System.ValueTuple.Test(T)"" + IL_0011: ret +} +"); + } + [Fact] public void TupleAsyncCapture01() { @@ -1159,7 +1335,7 @@ .maxstack 3 } [Fact] - public void LongTupleWithSubstitution() + public void TupleAsyncCapture02() { var source = @" using System; @@ -1172,51 +1348,454 @@ static void Main() Console.WriteLine(Test(42).Result); } - public static async Task Test(T a) + public static async Task Test(T a) { - var x = (f1: 1, f2: 2, f3: 3, f4: 4, f5: 5, f6: 6, f7: 7, f8: a); + var x = (f1: a, f2: a); await Task.Yield(); - return x.f8; + return x.ToString(); } } -" + trivial2uple + trivial3uple + trivalRemainingTuples; - - CompileAndVerify(source, expectedOutput: @"42", additionalRefs: new[] { MscorlibRef_v46 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithTuplesFeature()); +" + trivial2uple; + var verifier = CompileAndVerify(source, additionalRefs: new[] { MscorlibRef_v46 }, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"{42, 42}", options: TestOptions.ReleaseExe); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @" +{ + // Code size 197 (0xc5) + .maxstack 3 + .locals init (int V_0, + string V_1, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2, + System.Runtime.CompilerServices.YieldAwaitable V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.d__1.<>1__state"" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0058 + IL_000a: ldarg.0 + IL_000b: ldarg.0 + IL_000c: ldfld ""T C.d__1.a"" + IL_0011: ldarg.0 + IL_0012: ldfld ""T C.d__1.a"" + IL_0017: newobj ""System.ValueTuple..ctor(T, T)"" + IL_001c: stfld ""(T f1, T f2) C.d__1.5__1"" + IL_0021: call ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()"" + IL_0026: stloc.3 + IL_0027: ldloca.s V_3 + IL_0029: call ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()"" + IL_002e: stloc.2 + IL_002f: ldloca.s V_2 + IL_0031: call ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get"" + IL_0036: brtrue.s IL_0074 + IL_0038: ldarg.0 + IL_0039: ldc.i4.0 + IL_003a: dup + IL_003b: stloc.0 + IL_003c: stfld ""int C.d__1.<>1__state"" + IL_0041: ldarg.0 + IL_0042: ldloc.2 + IL_0043: stfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_0048: ldarg.0 + IL_0049: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_004e: ldloca.s V_2 + IL_0050: ldarg.0 + IL_0051: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__1>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.d__1)"" + IL_0056: leave.s IL_00c4 + IL_0058: ldarg.0 + IL_0059: ldfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_005e: stloc.2 + IL_005f: ldarg.0 + IL_0060: ldflda ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_0065: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld ""int C.d__1.<>1__state"" + IL_0074: ldloca.s V_2 + IL_0076: call ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()"" + IL_007b: ldloca.s V_2 + IL_007d: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_0083: ldarg.0 + IL_0084: ldflda ""(T f1, T f2) C.d__1.5__1"" + IL_0089: constrained. ""System.ValueTuple"" + IL_008f: callvirt ""string object.ToString()"" + IL_0094: stloc.1 + IL_0095: leave.s IL_00b0 + } + catch System.Exception + { + IL_0097: stloc.s V_4 + IL_0099: ldarg.0 + IL_009a: ldc.i4.s -2 + IL_009c: stfld ""int C.d__1.<>1__state"" + IL_00a1: ldarg.0 + IL_00a2: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_00a7: ldloc.s V_4 + IL_00a9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" + IL_00ae: leave.s IL_00c4 + } + IL_00b0: ldarg.0 + IL_00b1: ldc.i4.s -2 + IL_00b3: stfld ""int C.d__1.<>1__state"" + IL_00b8: ldarg.0 + IL_00b9: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_00be: ldloc.1 + IL_00bf: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult(string)"" + IL_00c4: ret +} +"); } [Fact] - public void TupleUsageWithoutTupleLibrary() + public void TupleAsyncCapture03() { var source = @" +using System; +using System.Threading.Tasks; + class C { static void Main() { - (int, string) x = (1, ""hello""); + Console.WriteLine(Test(42).Result); + } + + public static async Task Test(T a) + { + var x = (f1: a, f2: a); + + await Task.Yield(); + + return x.Test(a); } } -"; - var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); - comp.VerifyDiagnostics( - // (6,9): error CS0518: Predefined type 'System.ValueTuple`2' is not defined or imported - // (int, string) x = (1, "hello"); - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "(int, string)").WithArguments("System.ValueTuple`2").WithLocation(6, 9), - // (6,27): error CS0518: Predefined type 'System.ValueTuple`2' is not defined or imported - // (int, string) x = (1, "hello"); - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, @"(1, ""hello"")").WithArguments("System.ValueTuple`2").WithLocation(6, 27) - ); - } - [Fact] - public void TupleUsageWithMissingTupleMembers() - { - var source = @" namespace System { - public struct ValueTuple { } -} + // struct with two values + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public U Test(U val) + { + return val; + } + } +} +"; + var verifier = CompileAndVerify(source, additionalRefs: new[] { MscorlibRef_v46 }, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"42", options: TestOptions.ReleaseExe); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @" +{ + // Code size 197 (0xc5) + .maxstack 3 + .locals init (int V_0, + T V_1, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2, + System.Runtime.CompilerServices.YieldAwaitable V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.d__1.<>1__state"" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0058 + IL_000a: ldarg.0 + IL_000b: ldarg.0 + IL_000c: ldfld ""T C.d__1.a"" + IL_0011: ldarg.0 + IL_0012: ldfld ""T C.d__1.a"" + IL_0017: newobj ""System.ValueTuple..ctor(T, T)"" + IL_001c: stfld ""(T f1, T f2) C.d__1.5__1"" + IL_0021: call ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()"" + IL_0026: stloc.3 + IL_0027: ldloca.s V_3 + IL_0029: call ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()"" + IL_002e: stloc.2 + IL_002f: ldloca.s V_2 + IL_0031: call ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get"" + IL_0036: brtrue.s IL_0074 + IL_0038: ldarg.0 + IL_0039: ldc.i4.0 + IL_003a: dup + IL_003b: stloc.0 + IL_003c: stfld ""int C.d__1.<>1__state"" + IL_0041: ldarg.0 + IL_0042: ldloc.2 + IL_0043: stfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_0048: ldarg.0 + IL_0049: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_004e: ldloca.s V_2 + IL_0050: ldarg.0 + IL_0051: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__1>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.d__1)"" + IL_0056: leave.s IL_00c4 + IL_0058: ldarg.0 + IL_0059: ldfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_005e: stloc.2 + IL_005f: ldarg.0 + IL_0060: ldflda ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_0065: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld ""int C.d__1.<>1__state"" + IL_0074: ldloca.s V_2 + IL_0076: call ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()"" + IL_007b: ldloca.s V_2 + IL_007d: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_0083: ldarg.0 + IL_0084: ldflda ""(T f1, T f2) C.d__1.5__1"" + IL_0089: ldarg.0 + IL_008a: ldfld ""T C.d__1.a"" + IL_008f: call ""T System.ValueTuple.Test(T)"" + IL_0094: stloc.1 + IL_0095: leave.s IL_00b0 + } + catch System.Exception + { + IL_0097: stloc.s V_4 + IL_0099: ldarg.0 + IL_009a: ldc.i4.s -2 + IL_009c: stfld ""int C.d__1.<>1__state"" + IL_00a1: ldarg.0 + IL_00a2: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_00a7: ldloc.s V_4 + IL_00a9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" + IL_00ae: leave.s IL_00c4 + } + IL_00b0: ldarg.0 + IL_00b1: ldc.i4.s -2 + IL_00b3: stfld ""int C.d__1.<>1__state"" + IL_00b8: ldarg.0 + IL_00b9: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_00be: ldloc.1 + IL_00bf: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult(T)"" + IL_00c4: ret +} +"); + } + + [Fact] + public void TupleAsyncCapture04() + { + var source = @" +using System; +using System.Threading.Tasks; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42).Result); + } + + public static async Task Test(T a) + { + var x = (f1: 1, f2: 2); + + await Task.Yield(); + + return x.Test(a); + } +} + +namespace System +{ + // struct with two values + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public U Test(U val) + { + return val; + } + } +} +"; + var verifier = CompileAndVerify(source, additionalRefs: new[] { MscorlibRef_v46 }, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"42", options: TestOptions.ReleaseExe); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @" +{ + // Code size 187 (0xbb) + .maxstack 3 + .locals init (int V_0, + T V_1, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2, + System.Runtime.CompilerServices.YieldAwaitable V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld ""int C.d__1.<>1__state"" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_004e + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: ldc.i4.2 + IL_000d: newobj ""System.ValueTuple..ctor(int, int)"" + IL_0012: stfld ""(int f1, int f2) C.d__1.5__1"" + IL_0017: call ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()"" + IL_001c: stloc.3 + IL_001d: ldloca.s V_3 + IL_001f: call ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()"" + IL_0024: stloc.2 + IL_0025: ldloca.s V_2 + IL_0027: call ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get"" + IL_002c: brtrue.s IL_006a + IL_002e: ldarg.0 + IL_002f: ldc.i4.0 + IL_0030: dup + IL_0031: stloc.0 + IL_0032: stfld ""int C.d__1.<>1__state"" + IL_0037: ldarg.0 + IL_0038: ldloc.2 + IL_0039: stfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_003e: ldarg.0 + IL_003f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_0044: ldloca.s V_2 + IL_0046: ldarg.0 + IL_0047: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__1>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.d__1)"" + IL_004c: leave.s IL_00ba + IL_004e: ldarg.0 + IL_004f: ldfld ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_0054: stloc.2 + IL_0055: ldarg.0 + IL_0056: ldflda ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.d__1.<>u__1"" + IL_005b: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_0061: ldarg.0 + IL_0062: ldc.i4.m1 + IL_0063: dup + IL_0064: stloc.0 + IL_0065: stfld ""int C.d__1.<>1__state"" + IL_006a: ldloca.s V_2 + IL_006c: call ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()"" + IL_0071: ldloca.s V_2 + IL_0073: initobj ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter"" + IL_0079: ldarg.0 + IL_007a: ldflda ""(int f1, int f2) C.d__1.5__1"" + IL_007f: ldarg.0 + IL_0080: ldfld ""T C.d__1.a"" + IL_0085: call ""T System.ValueTuple.Test(T)"" + IL_008a: stloc.1 + IL_008b: leave.s IL_00a6 + } + catch System.Exception + { + IL_008d: stloc.s V_4 + IL_008f: ldarg.0 + IL_0090: ldc.i4.s -2 + IL_0092: stfld ""int C.d__1.<>1__state"" + IL_0097: ldarg.0 + IL_0098: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_009d: ldloc.s V_4 + IL_009f: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" + IL_00a4: leave.s IL_00ba + } + IL_00a6: ldarg.0 + IL_00a7: ldc.i4.s -2 + IL_00a9: stfld ""int C.d__1.<>1__state"" + IL_00ae: ldarg.0 + IL_00af: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__1.<>t__builder"" + IL_00b4: ldloc.1 + IL_00b5: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult(T)"" + IL_00ba: ret +} +"); + } + + [Fact] + public void LongTupleWithSubstitution() + { + var source = @" +using System; +using System.Threading.Tasks; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42).Result); + } + + public static async Task Test(T a) + { + var x = (f1: 1, f2: 2, f3: 3, f4: 4, f5: 5, f6: 6, f7: 7, f8: a); + + await Task.Yield(); + + return x.f8; + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + CompileAndVerify(source, expectedOutput: @"42", additionalRefs: new[] { MscorlibRef_v46 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithTuplesFeature()); + } + + [Fact] + public void TupleUsageWithoutTupleLibrary() + { + var source = @" +class C +{ + static void Main() + { + (int, string) x = (1, ""hello""); + } +} +"; + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (6,9): error CS0518: Predefined type 'System.ValueTuple`2' is not defined or imported + // (int, string) x = (1, "hello"); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "(int, string)").WithArguments("System.ValueTuple`2").WithLocation(6, 9), + // (6,27): error CS0518: Predefined type 'System.ValueTuple`2' is not defined or imported + // (int, string) x = (1, "hello"); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, @"(1, ""hello"")").WithArguments("System.ValueTuple`2").WithLocation(6, 27) + ); + } + + [Fact] + public void TupleUsageWithMissingTupleMembers() + { + var source = @" +namespace System +{ + public struct ValueTuple { } +} class C { @@ -1538,6 +2117,57 @@ static void Main() // return (default(T1), default(T2)); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "(default(T1), default(T2))").WithArguments("System.ValueTuple`2").WithLocation(12, 16) ); + + var c = comp.GetTypeByMetadataName("C"); + + var mTuple = (NamedTypeSymbol)c.GetMember("M").ReturnType; + + Assert.True(mTuple.IsTupleType); + Assert.Equal(TypeKind.Error, mTuple.TupleUnderlyingType.TypeKind); + Assert.Equal(SymbolKind.ErrorType, mTuple.TupleUnderlyingType.Kind); + Assert.IsAssignableFrom(mTuple.TupleUnderlyingType); + Assert.Equal(TypeKind.Struct, mTuple.TypeKind); + AssertTupleTypeEquality(mTuple); + Assert.False(mTuple.IsImplicitlyDeclared); + Assert.Equal("Predefined type 'System.ValueTuple`2' is not defined or imported", mTuple.GetUseSiteDiagnostic().GetMessage(CultureInfo.InvariantCulture)); + Assert.Null(mTuple.BaseType); + + var mFirst = (FieldSymbol)mTuple.GetMembers("first").Single(); + + Assert.IsType(mFirst); + + Assert.True(mFirst.IsTupleField); + Assert.Equal("first", mFirst.Name); + Assert.Same(mFirst, mFirst.OriginalDefinition); + Assert.True(mFirst.Equals(mFirst)); + Assert.Null(mFirst.TupleUnderlyingField); + Assert.Null(mFirst.AssociatedSymbol); + Assert.Same(mTuple, mFirst.ContainingSymbol); + Assert.True(mFirst.CustomModifiers.IsEmpty); + Assert.True(mFirst.GetAttributes().IsEmpty); + Assert.Null(mFirst.GetUseSiteDiagnostic()); + Assert.False(mFirst.Locations.IsDefaultOrEmpty); + Assert.Equal("first", mFirst.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(mFirst.IsImplicitlyDeclared); + Assert.Null(mFirst.TypeLayoutOffset); + + var mItem1 = (FieldSymbol)mTuple.GetMembers("Item1").Single(); + + Assert.IsType(mItem1); + + Assert.True(mItem1.IsTupleField); + Assert.Equal("Item1", mItem1.Name); + Assert.Same(mItem1, mItem1.OriginalDefinition); + Assert.True(mItem1.Equals(mItem1)); + Assert.Null(mItem1.TupleUnderlyingField); + Assert.Null(mItem1.AssociatedSymbol); + Assert.Same(mTuple, mItem1.ContainingSymbol); + Assert.True(mItem1.CustomModifiers.IsEmpty); + Assert.True(mItem1.GetAttributes().IsEmpty); + Assert.Null(mItem1.GetUseSiteDiagnostic()); + Assert.True(mItem1.Locations.IsEmpty); + Assert.False(mItem1.IsImplicitlyDeclared); + Assert.Null(mItem1.TypeLayoutOffset); } [Fact] @@ -1805,7 +2435,7 @@ static void Main() var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); var node = nodes.OfType().Where(n => n.ToString() == "x.Rest").First(); - Assert.Equal("System.ValueTuple", model.GetTypeInfo(node).Type.ToTestDisplayString()); + Assert.Equal("(System.String, System.Int32)", model.GetTypeInfo(node).Type.ToTestDisplayString()); }; var verifier = CompileAndVerify(source, expectedOutput: @"Alice 1", additionalRefs: new[] { MscorlibRef, ValueTupleRef, SystemRuntimeFacadeRef }, sourceSymbolValidator: validator, parseOptions: TestOptions.Regular.WithTuplesFeature()); @@ -2015,7 +2645,7 @@ public static void Main() } [Fact] - public void UnderlyingTypeMemberWithWrongSignature() + public void UnderlyingTypeMemberWithWrongSignature_1() { string source = @" class C @@ -2031,57 +2661,231 @@ namespace System { public struct ValueTuple { - public int Item1; // Not T1 + public string Item1; // Not T1 public int Item2; public ValueTuple(T1 item1, T2 item2) { - this.Item1 = 1; + this.Item1 = ""1""; this.Item2 = 2; } } } "; var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp", parseOptions: TestOptions.Regular.WithTuplesFeature()); - comp.VerifyDiagnostics(); - comp.VerifyEmitDiagnostics( - // (7,37): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + comp.VerifyDiagnostics( + // (7,39): error CS0229: Ambiguity between '(string, string).Item1' and '(string, string).Item1' // System.Console.WriteLine($"{x.Item1}"); - Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "x.Item1").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 37) + Diagnostic(ErrorCode.ERR_AmbigMember, "Item1").WithArguments("(string, string).Item1", "(string, string).Item1").WithLocation(7, 39) ); } [Fact] - public void ImplementTupleInterface() + public void UnderlyingTypeMemberWithWrongSignature_2() { string source = @" -public interface I +class C { - (int, int) M((string, string) a); -} + (string, string) M() + { + var x = (""Alice"", ""Bob""); + System.Console.WriteLine($""{x.Item1}""); + return x; + } -class C : I -{ - static void Main() + void M2((int a, int b) y) { - I i = new C(); - var r = i.M((""Alice"", ""Bob"")); - System.Console.WriteLine($""{r.Item1} {r.Item2}""); + System.Console.WriteLine($""{y.Item1}""); + System.Console.WriteLine($""{y.a}""); + System.Console.WriteLine($""{y.Item2}""); + System.Console.WriteLine($""{y.b}""); } +} - public (int, int) M((string, string) a) +namespace System +{ + public struct ValueTuple { - return (a.Item1.Length, a.Item2.Length); + public int Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item2 = 2; + } } } "; + var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp", parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.Item1}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "Item1").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 39), + // (13,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{y.Item1}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "Item1").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 39), + // (14,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{y.a}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "a").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(14, 39), + // (15,39): error CS0229: Ambiguity between '(int a, int b).Item2' and '(int a, int b).Item2' + // System.Console.WriteLine($"{y.Item2}"); + Diagnostic(ErrorCode.ERR_AmbigMember, "Item2").WithArguments("(int a, int b).Item2", "(int a, int b).Item2").WithLocation(15, 39), + // (16,39): error CS8205: Member 'Item2' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{y.b}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "b").WithArguments("Item2", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(16, 39) + ); - var comp = CompileAndVerify(source, expectedOutput: @"5 3", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); - comp.VerifyDiagnostics(); + var mTuple = (NamedTypeSymbol)comp.SourceModule.GlobalNamespace.GetMember("C").GetMember("M").ReturnType; + AssertTupleTypeEquality(mTuple); + + var mItem1 = (FieldSymbol)mTuple.GetMembers("Item1").Single(); + + Assert.IsType(mItem1); + + Assert.True(mItem1.IsTupleField); + Assert.Same(mItem1, mItem1.OriginalDefinition); + Assert.True(mItem1.Equals(mItem1)); + Assert.Equal("Item1", mItem1.Name); + Assert.Null(mItem1.TupleUnderlyingField); + Assert.Null(mItem1.AssociatedSymbol); + Assert.Same(mTuple, mItem1.ContainingSymbol); + Assert.True(mItem1.CustomModifiers.IsEmpty); + Assert.True(mItem1.GetAttributes().IsEmpty); + Assert.Equal("error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.", + mItem1.GetUseSiteDiagnostic().ToString()); + Assert.False(mItem1.Locations.IsDefaultOrEmpty); + Assert.Equal("string", mItem1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(mItem1.IsImplicitlyDeclared); + Assert.Null(mItem1.TypeLayoutOffset); + + AssertTestDisplayString(mTuple.GetMembers(), + "System.Int32 (System.String, System.String).Item2", + "(System.String, System.String)..ctor(System.String item1, System.String item2)", + "(System.String, System.String)..ctor()", + "System.String (System.String, System.String).Item1", + "System.String (System.String, System.String).Item2"); + + var m2Tuple = (NamedTypeSymbol)comp.SourceModule.GlobalNamespace.GetMember("C").GetMember("M2").Parameters[0].Type; + AssertTupleTypeEquality(m2Tuple); + AssertTestDisplayString(m2Tuple.GetMembers(), + "System.Int32 (System.Int32 a, System.Int32 b).Item2", + "(System.Int32 a, System.Int32 b)..ctor(System.Int32 item1, System.Int32 item2)", + "(System.Int32 a, System.Int32 b)..ctor()", + "System.Int32 (System.Int32 a, System.Int32 b).Item1", + "System.Int32 (System.Int32 a, System.Int32 b).a", + "System.Int32 (System.Int32 a, System.Int32 b).Item2", + "System.Int32 (System.Int32 a, System.Int32 b).b" + ); } [Fact] - public void ImplementTupleInterfaceWithDifferentNames() + public void UnderlyingTypeMemberWithWrongSignature_3() + { + string source = @" +class C +{ + static void M() + { + var x = (a: ""Alice"", b: ""Bob""); + System.Console.WriteLine($""{x.a}""); + } +} + +namespace System +{ + public struct ValueTuple + { + public int Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item2 = 2; + } + } +} +"; + var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp", parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.a}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "a").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 39) + ); + } + + [Fact] + public void UnderlyingTypeMemberWithWrongSignature_4() + { + string source = @" +class C +{ + static void M() + { + var x = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9); + System.Console.WriteLine($""{x.a}""); + System.Console.WriteLine($""{x.g}""); + System.Console.WriteLine($""{x.h}""); + System.Console.WriteLine($""{x.i}""); + } +} + +namespace System +{ + public struct ValueTuple + { + } + + public struct ValueTuple + { + } +} +"; + var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp", parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (7,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.a}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "a").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 39), + // (8,39): error CS8205: Member 'Item7' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.g}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "g").WithArguments("Item7", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 39), + // (9,39): error CS8205: Member 'Item1' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.h}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "h").WithArguments("Item1", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(9, 39), + // (10,39): error CS8205: Member 'Item2' was not found on type 'ValueTuple' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // System.Console.WriteLine($"{x.i}"); + Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "i").WithArguments("Item2", "System.ValueTuple", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(10, 39) + ); + } + + [Fact] + public void ImplementTupleInterface() + { + string source = @" +public interface I +{ + (int, int) M((string, string) a); +} + +class C : I +{ + static void Main() + { + I i = new C(); + var r = i.M((""Alice"", ""Bob"")); + System.Console.WriteLine($""{r.Item1} {r.Item2}""); + } + + public (int, int) M((string, string) a) + { + return (a.Item1.Length, a.Item2.Length); + } +} +"; + + var comp = CompileAndVerify(source, expectedOutput: @"5 3", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void ImplementTupleInterfaceWithDifferentNames() { string source = @" public interface I @@ -2576,7 +3380,6 @@ public void CreateTupleTypeSymbol_WithValueTuple() Assert.True(tupleWithoutNames.IsTupleType); Assert.Equal("(System.Int32, System.String)", tupleWithoutNames.ToTestDisplayString()); - Assert.False(((TupleTypeSymbol)tupleWithoutNames).HasFriendlyNames); Assert.True(tupleWithoutNames.TupleElementNames.IsDefault); Assert.Equal(new[] { "System.Int32", "System.String" }, tupleWithoutNames.TupleElementTypes.Select(t => t.ToTestDisplayString())); Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.Kind); @@ -2593,7 +3396,6 @@ public void CreateTupleTypeSymbol_NoNames() Assert.True(tupleWithoutNames.IsTupleType); Assert.Equal("(System.Int32, System.String)", tupleWithoutNames.ToTestDisplayString()); - Assert.False(((TupleTypeSymbol)tupleWithoutNames).HasFriendlyNames); Assert.True(tupleWithoutNames.TupleElementNames.IsDefault); Assert.Equal(new[] { "System.Int32", "System.String" }, tupleWithoutNames.TupleElementTypes.Select(t => t.ToTestDisplayString())); Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.Kind); @@ -2610,7 +3412,6 @@ public void CreateTupleTypeSymbol_WithNames() Assert.True(tupleWithNames.IsTupleType); Assert.Equal("(System.Int32 Alice, System.String Bob)", tupleWithNames.ToTestDisplayString()); - Assert.True(((TupleTypeSymbol)tupleWithNames).HasFriendlyNames); Assert.Equal(new[] { "Alice", "Bob" }, tupleWithNames.TupleElementNames); Assert.Equal(new[] { "System.Int32", "System.String" }, tupleWithNames.TupleElementTypes.Select(t => t.ToTestDisplayString())); Assert.Equal(SymbolKind.NamedType, tupleWithNames.Kind); @@ -2626,7 +3427,6 @@ public void CreateTupleTypeSymbol_WithBadNames() Assert.True(tupleWithNames.IsTupleType); Assert.Equal("(System.Int32 Item2, System.Int32 Item1)", tupleWithNames.ToTestDisplayString()); - Assert.True(((TupleTypeSymbol)tupleWithNames).HasFriendlyNames); Assert.Equal(new[] { "Item2", "Item1" }, tupleWithNames.TupleElementNames); Assert.Equal(new[] { "System.Int32", "System.Int32" }, tupleWithNames.TupleElementTypes.Select(t => t.ToTestDisplayString())); Assert.Equal(SymbolKind.NamedType, tupleWithNames.Kind); @@ -2646,7 +3446,6 @@ public void CreateTupleTypeSymbol_Tuple8NoNames() Assert.Equal("(System.Int32, System.String, System.Int32, System.String, System.Int32, System.String, System.Int32, System.String)", tuple8WithoutNames.ToTestDisplayString()); - Assert.False(((TupleTypeSymbol)tuple8WithoutNames).HasFriendlyNames); Assert.True(tuple8WithoutNames.TupleElementNames.IsDefault); Assert.Equal(new[] { "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String" }, @@ -2667,7 +3466,6 @@ public void CreateTupleTypeSymbol_Tuple8WithNames() Assert.Equal("(System.Int32 Alice1, System.String Alice2, System.Int32 Alice3, System.String Alice4, System.Int32 Alice5, System.String Alice6, System.Int32 Alice7, System.String Alice8)", tuple8WithNames.ToTestDisplayString()); - Assert.True(((TupleTypeSymbol)tuple8WithNames).HasFriendlyNames); Assert.Equal(new[] { "Alice1", "Alice2", "Alice3", "Alice4", "Alice5", "Alice6", "Alice7", "Alice8" }, tuple8WithNames.TupleElementNames); Assert.Equal(new[] { "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String" }, @@ -2688,7 +3486,6 @@ public void CreateTupleTypeSymbol_Tuple9NoNames() Assert.Equal("(System.Int32, System.String, System.Int32, System.String, System.Int32, System.String, System.Int32, System.String, System.Int32)", tuple9WithoutNames.ToTestDisplayString()); - Assert.False(((TupleTypeSymbol)tuple9WithoutNames).HasFriendlyNames); Assert.True(tuple9WithoutNames.TupleElementNames.IsDefault); Assert.Equal(new[] { "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32" }, @@ -2709,7 +3506,6 @@ public void CreateTupleTypeSymbol_Tuple9WithNames() Assert.Equal("(System.Int32 Alice1, System.String Alice2, System.Int32 Alice3, System.String Alice4, System.Int32 Alice5, System.String Alice6, System.Int32 Alice7, System.String Alice8, System.Int32 Alice9)", tuple9WithNames.ToTestDisplayString()); - Assert.True(((TupleTypeSymbol)tuple9WithNames).HasFriendlyNames); Assert.Equal(new[] { "Alice1", "Alice2", "Alice3", "Alice4", "Alice5", "Alice6", "Alice7", "Alice8", "Alice9" }, tuple9WithNames.TupleElementNames); Assert.Equal(new[] { "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32", "System.String", "System.Int32" }, @@ -4494,5 +5290,2000 @@ public override ((int b, int a), (int b, int a)) M(((int a, int b), (int b, int var comp = CompileAndVerify(source, expectedOutput: @"{1, 2} {3, 4}", sourceSymbolValidator: validator, parseOptions: TestOptions.Regular.WithTuplesFeature()); comp.VerifyDiagnostics(); } + + [Fact] + public void DefaultAndFriendlyElementNames_01() + { + var source = @" +using System; +class C +{ + static void Main() + { + var v1 = M1(); + System.Console.WriteLine(v1.Item1); + System.Console.WriteLine(v1.Item2); + + var v2 = M2(); + System.Console.WriteLine(v2.Item1); + System.Console.WriteLine(v2.Item2); + System.Console.WriteLine(v2.a2); + System.Console.WriteLine(v2.b2); + + var v6 = M6(); + System.Console.WriteLine(v6.Item1); + System.Console.WriteLine(v6.Item2); + System.Console.WriteLine(v6.item1); + System.Console.WriteLine(v6.item2); + + System.Console.WriteLine(v1.ToString()); + System.Console.WriteLine(v2.ToString()); + System.Console.WriteLine(v6.ToString()); + } + + static (int, int) M1() + { + return (1, 11); + } + + static (int a2, int b2) M2() + { + return (2, 22); + } + + static (int item1, int item2) M6() + { + return (6, 66); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"1 +11 +2 +22 +2 +22 +6 +66 +6 +66 +{1, 11} +{2, 22} +{6, 66} +"); + + var c = ((CSharpCompilation)comp.Compilation).GetTypeByMetadataName("C"); + + var m1Tuple = (NamedTypeSymbol)c.GetMember("M1").ReturnType; + var m2Tuple = (NamedTypeSymbol)c.GetMember("M2").ReturnType; + var m6Tuple = (NamedTypeSymbol)c.GetMember("M6").ReturnType; + + AssertTestDisplayString(m1Tuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + AssertTestDisplayString(m2Tuple.GetMembers(), + "System.Int32 (System.Int32 a2, System.Int32 b2).Item1", + "System.Int32 (System.Int32 a2, System.Int32 b2).a2", + "System.Int32 (System.Int32 a2, System.Int32 b2).Item2", + "System.Int32 (System.Int32 a2, System.Int32 b2).b2", + "(System.Int32 a2, System.Int32 b2)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32 a2, System.Int32 b2).ToString()", + "(System.Int32 a2, System.Int32 b2)..ctor()"); + + AssertTestDisplayString(m6Tuple.GetMembers(), + "System.Int32 (System.Int32 item1, System.Int32 item2).Item1", + "System.Int32 (System.Int32 item1, System.Int32 item2).item1", + "System.Int32 (System.Int32 item1, System.Int32 item2).Item2", + "System.Int32 (System.Int32 item1, System.Int32 item2).item2", + "(System.Int32 item1, System.Int32 item2)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32 item1, System.Int32 item2).ToString()", + "(System.Int32 item1, System.Int32 item2)..ctor()" + ); + + Assert.Equal("", m1Tuple.Name); + Assert.Equal(SymbolKind.NamedType, m1Tuple.Kind); + Assert.Equal(TypeKind.Struct, m1Tuple.TypeKind); + Assert.False(m1Tuple.IsImplicitlyDeclared); + Assert.True(m1Tuple.IsTupleType); + Assert.Equal("System.ValueTuple", m1Tuple.TupleUnderlyingType.ToTestDisplayString()); + Assert.Same(m1Tuple, m1Tuple.ConstructedFrom); + Assert.Same(m1Tuple, m1Tuple.OriginalDefinition); + AssertTupleTypeEquality(m1Tuple); + Assert.Same(m1Tuple.TupleUnderlyingType.ContainingSymbol, m1Tuple.ContainingSymbol); + Assert.Null(m1Tuple.GetUseSiteDiagnostic()); + Assert.Null(m1Tuple.EnumUnderlyingType); + Assert.Equal(new string[] { "Item1", "Item2", ".ctor", "ToString" }, + m1Tuple.MemberNames.ToArray()); + Assert.Equal(new string[] { "Item1", "a2", "Item2", "b2", ".ctor", "ToString" }, + m2Tuple.MemberNames.ToArray()); + Assert.Equal(0, m1Tuple.Arity); + Assert.True(m1Tuple.TypeParameters.IsEmpty); + Assert.Equal("System.ValueType", m1Tuple.BaseType.ToTestDisplayString()); + Assert.Null(m1Tuple.ComImportCoClass); + Assert.False(m1Tuple.HasTypeArgumentsCustomModifiers); + Assert.False(m1Tuple.IsComImport); + Assert.True(m1Tuple.TypeArgumentsCustomModifiers.IsEmpty); + Assert.True(m1Tuple.TypeArgumentsNoUseSiteDiagnostics.IsEmpty); + Assert.True(m1Tuple.GetAttributes().IsEmpty); + Assert.Equal("System.Int32 (System.Int32 a2, System.Int32 b2).Item1", m2Tuple.GetMembers("Item1").Single().ToTestDisplayString()); + Assert.Equal("System.Int32 (System.Int32 a2, System.Int32 b2).a2", m2Tuple.GetMembers("a2").Single().ToTestDisplayString()); + Assert.True(m1Tuple.GetTypeMembers().IsEmpty); + Assert.True(m1Tuple.GetTypeMembers("C9").IsEmpty); + Assert.True(m1Tuple.GetTypeMembers("C9", 0).IsEmpty); + Assert.True(m1Tuple.Interfaces.IsEmpty); + Assert.Equal(new string[] { "Item1", "Item2", ".ctor", ".ctor", "ToString" }, + m1Tuple.GetEarlyAttributeDecodingMembers().Select(m => m.Name).ToArray()); + Assert.Equal("System.Int32 (System.Int32, System.Int32).Item1", m1Tuple.GetEarlyAttributeDecodingMembers("Item1").Single().ToTestDisplayString()); + Assert.True(m1Tuple.GetTypeMembersUnordered().IsEmpty); + Assert.Equal(1, m1Tuple.Locations.Length); + Assert.Equal("(int, int)", m1Tuple.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("(int a2, int b2)", m2Tuple.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("public struct ValueTuple", m1Tuple.TupleUnderlyingType.DeclaringSyntaxReferences.Single().GetSyntax().ToString().Substring(0, 32)); + + AssertTupleTypeEquality(m2Tuple); + AssertTupleTypeEquality(m6Tuple); + + Assert.False(m1Tuple.Equals(m2Tuple)); + Assert.False(m1Tuple.Equals(m6Tuple)); + Assert.False(m6Tuple.Equals(m2Tuple)); + AssertTupleTypeMembersEquality(m1Tuple, m2Tuple); + AssertTupleTypeMembersEquality(m1Tuple, m6Tuple); + AssertTupleTypeMembersEquality(m2Tuple, m6Tuple); + + var m1Item1 = (FieldSymbol)m1Tuple.GetMembers()[0]; + var m2Item1 = (FieldSymbol)m2Tuple.GetMembers()[0]; + var m2a2 = (FieldSymbol)m2Tuple.GetMembers()[1]; + + Assert.IsType(m1Item1); + Assert.IsType(m2Item1); + Assert.IsType(m2a2); + + Assert.True(m1Item1.IsTupleField); + Assert.Same(m1Item1, m1Item1.OriginalDefinition); + Assert.True(m1Item1.Equals(m1Item1)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m1Item1.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m1Item1.AssociatedSymbol); + Assert.Same(m1Tuple, m1Item1.ContainingSymbol); + Assert.Same(m1Tuple.TupleUnderlyingType, m1Item1.TupleUnderlyingField.ContainingSymbol); + Assert.True(m1Item1.CustomModifiers.IsEmpty); + Assert.True(m1Item1.GetAttributes().IsEmpty); + Assert.Null(m1Item1.GetUseSiteDiagnostic()); + Assert.False(m1Item1.Locations.IsDefaultOrEmpty); + Assert.Equal("int", m1Item1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m1Item1.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m1Item1.IsImplicitlyDeclared); + Assert.Null(m1Item1.TypeLayoutOffset); + + Assert.True(m2Item1.IsTupleField); + Assert.Same(m2Item1, m2Item1.OriginalDefinition); + Assert.True(m2Item1.Equals(m2Item1)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m2Item1.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m2Item1.AssociatedSymbol); + Assert.Same(m2Tuple, m2Item1.ContainingSymbol); + Assert.Same(m2Tuple.TupleUnderlyingType, m2Item1.TupleUnderlyingField.ContainingSymbol); + Assert.True(m2Item1.CustomModifiers.IsEmpty); + Assert.True(m2Item1.GetAttributes().IsEmpty); + Assert.Null(m2Item1.GetUseSiteDiagnostic()); + Assert.False(m2Item1.Locations.IsDefaultOrEmpty); + Assert.Equal("Item1", m2Item1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m2Item1.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal(m2Item1.Locations.Single(), m2Item1.TupleUnderlyingField.Locations.Single()); + Assert.False(m2Item1.IsImplicitlyDeclared); + Assert.Null(m2Item1.TypeLayoutOffset); + + Assert.True(m2a2.IsTupleField); + Assert.Same(m2a2, m2a2.OriginalDefinition); + Assert.True(m2a2.Equals(m2a2)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m2a2.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m2a2.AssociatedSymbol); + Assert.Same(m2Tuple, m2a2.ContainingSymbol); + Assert.Same(m2Tuple.TupleUnderlyingType, m2a2.TupleUnderlyingField.ContainingSymbol); + Assert.True(m2a2.CustomModifiers.IsEmpty); + Assert.True(m2a2.GetAttributes().IsEmpty); + Assert.Null(m2a2.GetUseSiteDiagnostic()); + Assert.False(m2a2.Locations.IsDefaultOrEmpty); + Assert.Equal("a2", m2a2.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m2a2.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m2a2.IsImplicitlyDeclared); + Assert.Null(m2a2.TypeLayoutOffset); + } + + private static void AssertTupleTypeEquality(TypeSymbol tuple) + { + Assert.True(tuple.Equals(tuple)); + Assert.True(tuple.Equals(tuple, false, false)); + Assert.True(tuple.Equals(tuple, false, true)); + Assert.False(tuple.Equals(tuple.TupleUnderlyingType, false, false)); + Assert.False(tuple.TupleUnderlyingType.Equals(tuple, false, false)); + Assert.True(tuple.Equals(tuple.TupleUnderlyingType, false, true)); + Assert.True(tuple.TupleUnderlyingType.Equals(tuple, false, true)); + + var members = tuple.GetMembers(); + + for(int i = 0; i < members.Length; i++) + { + for (int j = 0; j < members.Length; j++) + { + if (i != j) + { + Assert.NotSame(members[i], members[j]); + Assert.False(members[i].Equals(members[j])); + Assert.False(members[j].Equals(members[i])); + } + } + } + + var underlyingMembers = tuple.TupleUnderlyingType.GetMembers(); + foreach(var m in members) + { + Assert.False(underlyingMembers.Any(u => u.Equals(m))); + Assert.False(underlyingMembers.Any(u => m.Equals(u))); + } + } + + private static void AssertTupleTypeMembersEquality(TypeSymbol tuple1, TypeSymbol tuple2) + { + Assert.NotSame(tuple1, tuple2); + + if (tuple1.Equals(tuple2)) + { + Assert.True(tuple2.Equals(tuple1)); + var members1 = tuple1.GetMembers(); + var members2 = tuple2.GetMembers(); + + Assert.Equal(members1.Length, members2.Length); + for (int i = 0; i < members1.Length; i++) + { + Assert.NotSame(members1[i], members2[i]); + Assert.True(members1[i].Equals(members2[i])); + Assert.True(members2[i].Equals(members1[i])); + Assert.Equal(members2[i].GetHashCode(), members1[i].GetHashCode()); + + if (members1[i].Kind == SymbolKind.Method) + { + var parameters1 = ((MethodSymbol)members1[i]).Parameters; + var parameters2 = ((MethodSymbol)members2[i]).Parameters; + Assert.Equal(parameters1.Length, parameters2.Length); + for (int j = 0; j < parameters1.Length; j++) + { + Assert.NotSame(parameters1[j], parameters2[j]); + Assert.True(parameters1[j].Equals(parameters2[j])); + Assert.True(parameters2[j].Equals(parameters1[j])); + Assert.Equal(parameters2[j].GetHashCode(), parameters1[j].GetHashCode()); + } + + var typeParameters1 = ((MethodSymbol)members1[i]).TypeParameters; + var typeParameters2 = ((MethodSymbol)members2[i]).TypeParameters; + Assert.Equal(typeParameters1.Length, typeParameters2.Length); + for (int j = 0; j < typeParameters1.Length; j++) + { + Assert.NotSame(typeParameters1[j], typeParameters2[j]); + Assert.True(typeParameters1[j].Equals(typeParameters2[j])); + Assert.True(typeParameters2[j].Equals(typeParameters1[j])); + Assert.Equal(typeParameters2[j].GetHashCode(), typeParameters1[j].GetHashCode()); + } + } + } + + for (int i = 0; i < members1.Length; i++) + { + for (int j = 0; j < members2.Length; j++) + { + if (i != j) + { + Assert.NotSame(members1[i], members2[j]); + Assert.False(members1[i].Equals(members2[j])); + } + } + } + } + else + { + Assert.False(tuple2.Equals(tuple1)); + var members1 = tuple1.GetMembers(); + var members2 = tuple2.GetMembers(); + foreach (var m in members1) + { + Assert.False(members2.Any(u => u.Equals(m))); + Assert.False(members2.Any(u => m.Equals(u))); + } + } + } + + [Fact] + public void DefaultAndFriendlyElementNames_02() + { + var source = @" +using System; +class C +{ + static void Main() + { + var v3 = M3(); + System.Console.WriteLine(v3.Item1); + System.Console.WriteLine(v3.Item2); + System.Console.WriteLine(v3.Item3); + System.Console.WriteLine(v3.Item4); + System.Console.WriteLine(v3.Item5); + System.Console.WriteLine(v3.Item6); + System.Console.WriteLine(v3.Item7); + System.Console.WriteLine(v3.Item8); + System.Console.WriteLine(v3.Item9); + System.Console.WriteLine(v3.Rest.Item1); + System.Console.WriteLine(v3.Rest.Item2); + + System.Console.WriteLine(v3.ToString()); + } + + static (int, int, int, int, int, int, int, int, int) M3() + { + return (31, 32, 33, 34, 35, 36, 37, 38, 39); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"31 +32 +33 +34 +35 +36 +37 +38 +39 +38 +39 +System.ValueTuple`8[System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.ValueTuple`2[System.Int32,System.Int32]] +"); + + var c = ((CSharpCompilation)comp.Compilation).GetTypeByMetadataName("C"); + + var m3Tuple = c.GetMember("M3").ReturnType; + AssertTupleTypeEquality(m3Tuple); + + AssertTestDisplayString(m3Tuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item2", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item3", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item4", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item5", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item6", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item7", + "(System.Int32, System.Int32) (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Rest", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, (System.Int32, System.Int32) rest)", + "System.String (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor()", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item8", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item9" + ); + + var m3Item8 = (FieldSymbol)m3Tuple.GetMembers("Item8").Single(); + + Assert.IsType(m3Item8); + + Assert.True(m3Item8.IsTupleField); + Assert.Same(m3Item8, m3Item8.OriginalDefinition); + Assert.True(m3Item8.Equals(m3Item8)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m3Item8.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m3Item8.AssociatedSymbol); + Assert.Same(m3Tuple, m3Item8.ContainingSymbol); + Assert.NotEqual(m3Tuple.TupleUnderlyingType, m3Item8.TupleUnderlyingField.ContainingSymbol); + Assert.True(m3Item8.CustomModifiers.IsEmpty); + Assert.True(m3Item8.GetAttributes().IsEmpty); + Assert.Null(m3Item8.GetUseSiteDiagnostic()); + Assert.False(m3Item8.Locations.IsDefaultOrEmpty); + Assert.Equal("int", m3Item8.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m3Item8.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m3Item8.IsImplicitlyDeclared); + Assert.Null(m3Item8.TypeLayoutOffset); + + var m3TupleRestTuple = (NamedTypeSymbol)((FieldSymbol)m3Tuple.GetMembers("Rest").Single()).Type; + AssertTestDisplayString(m3TupleRestTuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + Assert.True(m3TupleRestTuple.IsTupleType); + AssertTupleTypeEquality(m3TupleRestTuple); + Assert.True(m3TupleRestTuple.Locations.IsEmpty); + Assert.True(m3TupleRestTuple.DeclaringSyntaxReferences.IsEmpty); + + foreach (var m in m3TupleRestTuple.GetMembers().OfType()) + { + Assert.True(m.Locations.IsEmpty); + } + } + + [Fact] + public void DefaultAndFriendlyElementNames_03() + { + var source = @" +using System; +class C +{ + static void Main() + { + var v4 = M4 (); + System.Console.WriteLine(v4.Item1); + System.Console.WriteLine(v4.Item2); + System.Console.WriteLine(v4.Item3); + System.Console.WriteLine(v4.Item4); + System.Console.WriteLine(v4.Item5); + System.Console.WriteLine(v4.Item6); + System.Console.WriteLine(v4.Item7); + System.Console.WriteLine(v4.Item8); + System.Console.WriteLine(v4.Item9); + System.Console.WriteLine(v4.Rest.Item1); + System.Console.WriteLine(v4.Rest.Item2); + System.Console.WriteLine(v4.a4); + System.Console.WriteLine(v4.b4); + System.Console.WriteLine(v4.c4); + System.Console.WriteLine(v4.d4); + System.Console.WriteLine(v4.e4); + System.Console.WriteLine(v4.f4); + System.Console.WriteLine(v4.g4); + System.Console.WriteLine(v4.h4); + System.Console.WriteLine(v4.i4); + + System.Console.WriteLine(v4.ToString()); + } + + static (int a4, int b4, int c4, int d4, int e4, int f4, int g4, int h4, int i4) M4() + { + return (41, 42, 43, 44, 45, 46, 47, 48, 49); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"41 +42 +43 +44 +45 +46 +47 +48 +49 +48 +49 +41 +42 +43 +44 +45 +46 +47 +48 +49 +System.ValueTuple`8[System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.ValueTuple`2[System.Int32,System.Int32]] +"); + + var c = ((CSharpCompilation)comp.Compilation).GetTypeByMetadataName("C"); + + var m4Tuple = c.GetMember("M4").ReturnType; + AssertTupleTypeEquality(m4Tuple); + + AssertTestDisplayString(m4Tuple.GetMembers(), + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item1", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".a4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item2", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".b4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item3", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".c4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".d4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item5", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".e4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item6", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".f4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item7", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".g4", + "(System.Int32, System.Int32) (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Rest", + "(System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + "..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, (System.Int32, System.Int32) rest)", + "System.String (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".ToString()", + "(System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + "..ctor()", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item8", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".h4", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".Item9", + "System.Int32 (System.Int32 a4, System.Int32 b4, System.Int32 c4, System.Int32 d4, System.Int32 e4, System.Int32 f4, System.Int32 g4, System.Int32 h4, System.Int32 i4)" + + ".i4" + ); + + var m4Item8 = (FieldSymbol)m4Tuple.GetMembers("Item8").Single(); + + Assert.IsType(m4Item8); + + Assert.True(m4Item8.IsTupleField); + Assert.Same(m4Item8, m4Item8.OriginalDefinition); + Assert.True(m4Item8.Equals(m4Item8)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m4Item8.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m4Item8.AssociatedSymbol); + Assert.Same(m4Tuple, m4Item8.ContainingSymbol); + Assert.NotEqual(m4Tuple.TupleUnderlyingType, m4Item8.TupleUnderlyingField.ContainingSymbol); + Assert.True(m4Item8.CustomModifiers.IsEmpty); + Assert.True(m4Item8.GetAttributes().IsEmpty); + Assert.Null(m4Item8.GetUseSiteDiagnostic()); + Assert.True(m4Item8.Locations.IsDefaultOrEmpty); + Assert.Equal("Item1", m4Item8.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m4Item8.IsImplicitlyDeclared); + Assert.Null(m4Item8.TypeLayoutOffset); + + var m4h4 = (FieldSymbol)m4Tuple.GetMembers("h4").Single(); + + Assert.IsType(m4h4); + + Assert.True(m4h4.IsTupleField); + Assert.Same(m4h4, m4h4.OriginalDefinition); + Assert.True(m4h4.Equals(m4h4)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m4h4.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m4h4.AssociatedSymbol); + Assert.Same(m4Tuple, m4h4.ContainingSymbol); + Assert.NotEqual(m4Tuple.TupleUnderlyingType, m4h4.TupleUnderlyingField.ContainingSymbol); + Assert.True(m4h4.CustomModifiers.IsEmpty); + Assert.True(m4h4.GetAttributes().IsEmpty); + Assert.Null(m4h4.GetUseSiteDiagnostic()); + Assert.False(m4h4.Locations.IsDefaultOrEmpty); + Assert.Equal("h4", m4h4.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m4h4.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m4h4.IsImplicitlyDeclared); + Assert.Null(m4h4.TypeLayoutOffset); + + var m4TupleRestTuple = ((FieldSymbol)m4Tuple.GetMembers("Rest").Single()).Type; + AssertTupleTypeEquality(m4TupleRestTuple); + + AssertTestDisplayString(m4TupleRestTuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + foreach (var m in m4TupleRestTuple.GetMembers().OfType()) + { + Assert.True(m.Locations.IsEmpty); + } + } + + [Fact] + public void DefaultAndFriendlyElementNames_04() + { + var source = @" + +class C +{ + static void Main() + { + var v4 = M4 (); + System.Console.WriteLine(v4.Rest.a4); + System.Console.WriteLine(v4.Rest.b4); + System.Console.WriteLine(v4.Rest.c4); + System.Console.WriteLine(v4.Rest.d4); + System.Console.WriteLine(v4.Rest.e4); + System.Console.WriteLine(v4.Rest.f4); + System.Console.WriteLine(v4.Rest.g4); + System.Console.WriteLine(v4.Rest.h4); + System.Console.WriteLine(v4.Rest.i4); + } + + static (int a4, int b4, int c4, int d4, int e4, int f4, int g4, int h4, int i4) M4() + { + return (41, 42, 43, 44, 45, 46, 47, 48, 49); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (8,42): error CS1061: '(int, int)' does not contain a definition for 'a4' and no extension method 'a4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.a4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "a4").WithArguments("(int, int)", "a4").WithLocation(8, 42), + // (9,42): error CS1061: '(int, int)' does not contain a definition for 'b4' and no extension method 'b4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.b4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "b4").WithArguments("(int, int)", "b4").WithLocation(9, 42), + // (10,42): error CS1061: '(int, int)' does not contain a definition for 'c4' and no extension method 'c4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.c4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "c4").WithArguments("(int, int)", "c4").WithLocation(10, 42), + // (11,42): error CS1061: '(int, int)' does not contain a definition for 'd4' and no extension method 'd4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.d4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "d4").WithArguments("(int, int)", "d4").WithLocation(11, 42), + // (12,42): error CS1061: '(int, int)' does not contain a definition for 'e4' and no extension method 'e4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.e4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "e4").WithArguments("(int, int)", "e4").WithLocation(12, 42), + // (13,42): error CS1061: '(int, int)' does not contain a definition for 'f4' and no extension method 'f4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.f4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "f4").WithArguments("(int, int)", "f4").WithLocation(13, 42), + // (14,42): error CS1061: '(int, int)' does not contain a definition for 'g4' and no extension method 'g4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.g4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "g4").WithArguments("(int, int)", "g4").WithLocation(14, 42), + // (15,42): error CS1061: '(int, int)' does not contain a definition for 'h4' and no extension method 'h4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.h4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "h4").WithArguments("(int, int)", "h4").WithLocation(15, 42), + // (16,42): error CS1061: '(int, int)' does not contain a definition for 'i4' and no extension method 'i4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v4.Rest.i4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "i4").WithArguments("(int, int)", "i4").WithLocation(16, 42) + ); + } + + [Fact] + public void DefaultAndFriendlyElementNames_05() + { + var source = @" +using System; +class C +{ + static void Main() + { + var v5 = M5(); + System.Console.WriteLine(v5.Item1); + System.Console.WriteLine(v5.Item2); + System.Console.WriteLine(v5.Item3); + System.Console.WriteLine(v5.Item4); + System.Console.WriteLine(v5.Item5); + System.Console.WriteLine(v5.Item6); + System.Console.WriteLine(v5.Item7); + System.Console.WriteLine(v5.Item8); + System.Console.WriteLine(v5.Item9); + System.Console.WriteLine(v5.Item10); + System.Console.WriteLine(v5.Item11); + System.Console.WriteLine(v5.Item12); + System.Console.WriteLine(v5.Item13); + System.Console.WriteLine(v5.Item14); + System.Console.WriteLine(v5.Item15); + System.Console.WriteLine(v5.Item16); + System.Console.WriteLine(v5.Rest.Item1); + System.Console.WriteLine(v5.Rest.Item2); + System.Console.WriteLine(v5.Rest.Item3); + System.Console.WriteLine(v5.Rest.Item4); + System.Console.WriteLine(v5.Rest.Item5); + System.Console.WriteLine(v5.Rest.Item6); + System.Console.WriteLine(v5.Rest.Item7); + System.Console.WriteLine(v5.Rest.Item8); + System.Console.WriteLine(v5.Rest.Item9); + System.Console.WriteLine(v5.Rest.Rest.Item1); + System.Console.WriteLine(v5.Rest.Rest.Item2); + + System.Console.WriteLine(v5.ToString()); + } + + static (int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8, + int Item9, int Item10, int Item11, int Item12, int Item13, int Item14, int Item15, int Item16) M5() + { + return (501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +508 +509 +510 +511 +512 +513 +514 +515 +516 +515 +516 +System.ValueTuple`8[System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.ValueTuple`8[System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.ValueTuple`2[System.Int32,System.Int32]]] +"); + + var c = ((CSharpCompilation)comp.Compilation).GetTypeByMetadataName("C"); + + var m5Tuple = c.GetMember("M5").ReturnType; + AssertTupleTypeEquality(m5Tuple); + + AssertTestDisplayString(m5Tuple.GetMembers(), + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item1", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item2", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item3", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item4", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item5", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item6", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item7", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32) " + + "(System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Rest", + "(System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + "..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, " + + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32) rest)", + "System.String (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".ToString()", + "(System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + "..ctor()", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item8", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item9", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item10", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item11", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item12", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item13", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item14", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item15", + "System.Int32 (System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8, " + + "System.Int32 Item9, System.Int32 Item10, System.Int32 Item11, System.Int32 Item12, System.Int32 Item13, System.Int32 Item14, System.Int32 Item15, System.Int32 Item16)" + + ".Item16" + ); + + var m5Item8 = (FieldSymbol)m5Tuple.GetMembers("Item8").Single(); + + Assert.IsType(m5Item8); + + Assert.True(m5Item8.IsTupleField); + Assert.Same(m5Item8, m5Item8.OriginalDefinition); + Assert.True(m5Item8.Equals(m5Item8)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", + m5Item8.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m5Item8.AssociatedSymbol); + Assert.Same(m5Tuple, m5Item8.ContainingSymbol); + Assert.NotEqual(m5Tuple.TupleUnderlyingType, m5Item8.TupleUnderlyingField.ContainingSymbol); + Assert.True(m5Item8.CustomModifiers.IsEmpty); + Assert.True(m5Item8.GetAttributes().IsEmpty); + Assert.Null(m5Item8.GetUseSiteDiagnostic()); + Assert.False(m5Item8.Locations.IsDefaultOrEmpty); + Assert.Equal("Item8", m5Item8.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m5Item8.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m5Item8.IsImplicitlyDeclared); + Assert.Null(m5Item8.TypeLayoutOffset); + + var m5TupleRestTuple = ((FieldSymbol)m5Tuple.GetMembers("Rest").Single()).Type; + AssertTupleTypeEquality(m5TupleRestTuple); + + AssertTestDisplayString(m5TupleRestTuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item2", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item3", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item4", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item5", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item6", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item7", + "(System.Int32, System.Int32) (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Rest", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, (System.Int32, System.Int32) rest)", + "System.String (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor()", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item8", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item9" + ); + + foreach (var m in m5TupleRestTuple.GetMembers().OfType()) + { + if (m.Name != "Rest") + { + Assert.True(m.Locations.IsEmpty); + } + else + { + Assert.Equal("Rest", m.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + } + } + + var m5TupleRestTupleRestTuple = ((FieldSymbol)m5TupleRestTuple.GetMembers("Rest").Single()).Type; + AssertTupleTypeEquality(m5TupleRestTupleRestTuple); + + AssertTestDisplayString(m5TupleRestTupleRestTuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + foreach (var m in m5TupleRestTupleRestTuple.GetMembers().OfType()) + { + Assert.True(m.Locations.IsEmpty); + } + } + + [Fact] + public void DefaultAndFriendlyElementNames_06() + { + var source = @" + +class C +{ + static void Main() + { + var v5 = M5(); + System.Console.WriteLine(v5.Rest.Item10); + System.Console.WriteLine(v5.Rest.Item11); + System.Console.WriteLine(v5.Rest.Item12); + System.Console.WriteLine(v5.Rest.Item13); + System.Console.WriteLine(v5.Rest.Item14); + System.Console.WriteLine(v5.Rest.Item15); + System.Console.WriteLine(v5.Rest.Item16); + + System.Console.WriteLine(v5.Rest.Rest.Item3); + System.Console.WriteLine(v5.Rest.Rest.Item4); + System.Console.WriteLine(v5.Rest.Rest.Item5); + System.Console.WriteLine(v5.Rest.Rest.Item6); + System.Console.WriteLine(v5.Rest.Rest.Item7); + System.Console.WriteLine(v5.Rest.Rest.Item8); + System.Console.WriteLine(v5.Rest.Rest.Item9); + System.Console.WriteLine(v5.Rest.Rest.Item10); + System.Console.WriteLine(v5.Rest.Rest.Item11); + System.Console.WriteLine(v5.Rest.Rest.Item12); + System.Console.WriteLine(v5.Rest.Rest.Item13); + System.Console.WriteLine(v5.Rest.Rest.Item14); + System.Console.WriteLine(v5.Rest.Rest.Item15); + System.Console.WriteLine(v5.Rest.Rest.Item16); + } + + static (int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8, + int Item9, int Item10, int Item11, int Item12, int Item13, int Item14, int Item15, int Item16) M5() + { + return (501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (8,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item10' and no extension method 'Item10' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item10); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item10").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item10").WithLocation(8, 42), + // (9,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item11' and no extension method 'Item11' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item11); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item11").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item11").WithLocation(9, 42), + // (10,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item12' and no extension method 'Item12' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item12); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item12").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item12").WithLocation(10, 42), + // (11,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item13' and no extension method 'Item13' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item13); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item13").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item13").WithLocation(11, 42), + // (12,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item14' and no extension method 'Item14' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item14); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item14").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item14").WithLocation(12, 42), + // (13,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item15' and no extension method 'Item15' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item15); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item15").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item15").WithLocation(13, 42), + // (14,42): error CS1061: '(int, int, int, int, int, int, int, int, int)' does not contain a definition for 'Item16' and no extension method 'Item16' accepting a first argument of type '(int, int, int, int, int, int, int, int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Item16); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item16").WithArguments("(int, int, int, int, int, int, int, int, int)", "Item16").WithLocation(14, 42), + // (16,47): error CS1061: '(int, int)' does not contain a definition for 'Item3' and no extension method 'Item3' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item3); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item3").WithArguments("(int, int)", "Item3").WithLocation(16, 47), + // (17,47): error CS1061: '(int, int)' does not contain a definition for 'Item4' and no extension method 'Item4' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item4); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item4").WithArguments("(int, int)", "Item4").WithLocation(17, 47), + // (18,47): error CS1061: '(int, int)' does not contain a definition for 'Item5' and no extension method 'Item5' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item5); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item5").WithArguments("(int, int)", "Item5").WithLocation(18, 47), + // (19,47): error CS1061: '(int, int)' does not contain a definition for 'Item6' and no extension method 'Item6' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item6); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item6").WithArguments("(int, int)", "Item6").WithLocation(19, 47), + // (20,47): error CS1061: '(int, int)' does not contain a definition for 'Item7' and no extension method 'Item7' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item7); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item7").WithArguments("(int, int)", "Item7").WithLocation(20, 47), + // (21,47): error CS1061: '(int, int)' does not contain a definition for 'Item8' and no extension method 'Item8' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item8); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item8").WithArguments("(int, int)", "Item8").WithLocation(21, 47), + // (22,47): error CS1061: '(int, int)' does not contain a definition for 'Item9' and no extension method 'Item9' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item9); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item9").WithArguments("(int, int)", "Item9").WithLocation(22, 47), + // (23,47): error CS1061: '(int, int)' does not contain a definition for 'Item10' and no extension method 'Item10' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item10); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item10").WithArguments("(int, int)", "Item10").WithLocation(23, 47), + // (24,47): error CS1061: '(int, int)' does not contain a definition for 'Item11' and no extension method 'Item11' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item11); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item11").WithArguments("(int, int)", "Item11").WithLocation(24, 47), + // (25,47): error CS1061: '(int, int)' does not contain a definition for 'Item12' and no extension method 'Item12' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item12); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item12").WithArguments("(int, int)", "Item12").WithLocation(25, 47), + // (26,47): error CS1061: '(int, int)' does not contain a definition for 'Item13' and no extension method 'Item13' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item13); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item13").WithArguments("(int, int)", "Item13").WithLocation(26, 47), + // (27,47): error CS1061: '(int, int)' does not contain a definition for 'Item14' and no extension method 'Item14' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item14); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item14").WithArguments("(int, int)", "Item14").WithLocation(27, 47), + // (28,47): error CS1061: '(int, int)' does not contain a definition for 'Item15' and no extension method 'Item15' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item15); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item15").WithArguments("(int, int)", "Item15").WithLocation(28, 47), + // (29,47): error CS1061: '(int, int)' does not contain a definition for 'Item16' and no extension method 'Item16' accepting a first argument of type '(int, int)' could be found (are you missing a using directive or an assembly reference?) + // System.Console.WriteLine(v5.Rest.Rest.Item16); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Item16").WithArguments("(int, int)", "Item16").WithLocation(29, 47) + ); + } + + [Fact] + public void DefaultAndFriendlyElementNames_07() + { + var source = @" + +class C +{ + static void Main() + { + } + + static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + { + return (701, 702, 703, 704, 705, 706, 707, 708, 709); } } +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,17): error CS8201: Tuple member name 'Item9' is only allowed at position 9. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item9").WithArguments("Item9", "9").WithLocation(9, 17), + // (9,28): error CS8201: Tuple member name 'Item1' is only allowed at position 1. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item1").WithArguments("Item1", "1").WithLocation(9, 28), + // (9,39): error CS8201: Tuple member name 'Item2' is only allowed at position 2. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item2").WithArguments("Item2", "2").WithLocation(9, 39), + // (9,50): error CS8201: Tuple member name 'Item3' is only allowed at position 3. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item3").WithArguments("Item3", "3").WithLocation(9, 50), + // (9,61): error CS8201: Tuple member name 'Item4' is only allowed at position 4. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item4").WithArguments("Item4", "4").WithLocation(9, 61), + // (9,72): error CS8201: Tuple member name 'Item5' is only allowed at position 5. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item5").WithArguments("Item5", "5").WithLocation(9, 72), + // (9,83): error CS8201: Tuple member name 'Item6' is only allowed at position 6. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item6").WithArguments("Item6", "6").WithLocation(9, 83), + // (9,94): error CS8201: Tuple member name 'Item7' is only allowed at position 7. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item7").WithArguments("Item7", "7").WithLocation(9, 94), + // (9,105): error CS8201: Tuple member name 'Item8' is only allowed at position 8. + // static (int Item9, int Item1, int Item2, int Item3, int Item4, int Item5, int Item6, int Item7, int Item8) M7() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item8").WithArguments("Item8", "8").WithLocation(9, 105) + ); + + var c = comp.GetTypeByMetadataName("C"); + + var m7Tuple = c.GetMember("M7").ReturnType; + AssertTupleTypeEquality(m7Tuple); + + AssertTestDisplayString(m7Tuple.GetMembers(), + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item1", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item9", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item2", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item1", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item3", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item2", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item4", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item3", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item5", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item4", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item6", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item5", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item7", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item6", + "(System.Int32, System.Int32) (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Rest", + "(System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + "..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, (System.Int32, System.Int32) rest)", + "System.String (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".ToString()", + "(System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + "..ctor()", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item8", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item7", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item9", + "System.Int32 (System.Int32 Item9, System.Int32 Item1, System.Int32 Item2, System.Int32 Item3, System.Int32 Item4, System.Int32 Item5, System.Int32 Item6, System.Int32 Item7, System.Int32 Item8)" + + ".Item8" + ); + } + + [Fact] + public void DefaultAndFriendlyElementNames_08() + { + var source = @" + +class C +{ + static void Main() + { + } + + static (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int Item1) M8() + { + return (801, 802, 803, 804, 805, 806, 807, 808); + } +} +" + trivial2uple + trivial3uple + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (9,73): error CS8201: Tuple member name 'Item1' is only allowed at position 1. + // static (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int Item1) M8() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item1").WithArguments("Item1", "1").WithLocation(9, 73) + ); + + var c = comp.GetTypeByMetadataName("C"); + + var m8Tuple = c.GetMember("M8").ReturnType; + AssertTupleTypeEquality(m8Tuple); + + AssertTestDisplayString(m8Tuple.GetMembers(), + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item1", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a1", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item2", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a2", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item3", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a3", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item4", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a4", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item5", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a5", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item6", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a6", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item7", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).a7", + "(System.Int32) (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Rest", + "(System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1)" + + "..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, (System.Int32) rest)", + "System.String (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1)" + + ".ToString()", + "(System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1)" + + "..ctor()", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item8", + "System.Int32 (System.Int32 a1, System.Int32 a2, System.Int32 a3, System.Int32 a4, System.Int32 a5, System.Int32 a6, System.Int32 a7, System.Int32 Item1).Item1" + ); + + var m8Item8 = (FieldSymbol)m8Tuple.GetMembers("Item8").Single(); + + Assert.IsType(m8Item8); + + Assert.True(m8Item8.IsTupleField); + Assert.Same(m8Item8, m8Item8.OriginalDefinition); + Assert.True(m8Item8.Equals(m8Item8)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", + m8Item8.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m8Item8.AssociatedSymbol); + Assert.Same(m8Tuple, m8Item8.ContainingSymbol); + Assert.NotEqual(m8Tuple.TupleUnderlyingType, m8Item8.TupleUnderlyingField.ContainingSymbol); + Assert.True(m8Item8.CustomModifiers.IsEmpty); + Assert.True(m8Item8.GetAttributes().IsEmpty); + Assert.Null(m8Item8.GetUseSiteDiagnostic()); + Assert.True(m8Item8.Locations.IsDefaultOrEmpty); + Assert.Equal("Item1", m8Item8.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m8Item8.IsImplicitlyDeclared); + Assert.Null(m8Item8.TypeLayoutOffset); + + var m8Item1 = (FieldSymbol)m8Tuple.GetMembers("Item1").Last(); + + Assert.IsType(m8Item1); + + Assert.True(m8Item1.IsTupleField); + Assert.Same(m8Item1, m8Item1.OriginalDefinition); + Assert.True(m8Item1.Equals(m8Item1)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", + m8Item1.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m8Item1.AssociatedSymbol); + Assert.Same(m8Tuple, m8Item1.ContainingSymbol); + Assert.NotEqual(m8Tuple.TupleUnderlyingType, m8Item1.TupleUnderlyingField.ContainingSymbol); + Assert.True(m8Item1.CustomModifiers.IsEmpty); + Assert.True(m8Item1.GetAttributes().IsEmpty); + Assert.Null(m8Item1.GetUseSiteDiagnostic()); + Assert.False(m8Item1.Locations.IsDefaultOrEmpty); + Assert.Equal("Item1", m8Item1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m8Item1.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.NotEqual(m8Item1.Locations.Single(), m8Item1.TupleUnderlyingField.Locations.Single()); + Assert.False(m8Item1.IsImplicitlyDeclared); + Assert.Null(m8Item1.TypeLayoutOffset); + + var m8TupleRestTuple = ((FieldSymbol)m8Tuple.GetMembers("Rest").Single()).Type; + AssertTupleTypeEquality(m8TupleRestTuple); + + AssertTestDisplayString(m8TupleRestTuple.GetMembers(), + "System.Int32 (System.Int32).Item1", + "(System.Int32)..ctor(System.Int32 item1)", + "System.String (System.Int32).ToString()", + "(System.Int32)..ctor()"); + } + + [Fact] + public void DefaultAndFriendlyElementNames_09() + { + var source = @" +using System; +class C +{ + static void Main() + { + var v1 = (1, 11); + System.Console.WriteLine(v1.Item1); + System.Console.WriteLine(v1.Item2); + + var v2 =(a2: 2, b2: 22); + System.Console.WriteLine(v2.Item1); + System.Console.WriteLine(v2.Item2); + System.Console.WriteLine(v2.a2); + System.Console.WriteLine(v2.b2); + + var v6 = (item1: 6, item2: 66); + System.Console.WriteLine(v6.Item1); + System.Console.WriteLine(v6.Item2); + System.Console.WriteLine(v6.item1); + System.Console.WriteLine(v6.item2); + + System.Console.WriteLine(v1.ToString()); + System.Console.WriteLine(v2.ToString()); + System.Console.WriteLine(v6.ToString()); + } +} +" + trivial2uple; + + var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithTuplesFeature(), expectedOutput: @"1 +11 +2 +22 +2 +22 +6 +66 +6 +66 +{1, 11} +{2, 22} +{6, 66} +"); + + var c = (CSharpCompilation)comp.Compilation; + var tree = c.SyntaxTrees.Single(); + var model = c.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().First(); + + var m1Tuple = (NamedTypeSymbol)model.LookupSymbols(node.SpanStart, name: "v1").OfType().Single().Type; + var m2Tuple = (NamedTypeSymbol)model.LookupSymbols(node.SpanStart, name: "v2").OfType().Single().Type; + var m6Tuple = (NamedTypeSymbol)model.LookupSymbols(node.SpanStart, name: "v6").OfType().Single().Type; + + AssertTestDisplayString(m1Tuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + AssertTestDisplayString(m2Tuple.GetMembers(), + "System.Int32 (System.Int32 a2, System.Int32 b2).Item1", + "System.Int32 (System.Int32 a2, System.Int32 b2).a2", + "System.Int32 (System.Int32 a2, System.Int32 b2).Item2", + "System.Int32 (System.Int32 a2, System.Int32 b2).b2", + "(System.Int32 a2, System.Int32 b2)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32 a2, System.Int32 b2).ToString()", + "(System.Int32 a2, System.Int32 b2)..ctor()"); + + AssertTestDisplayString(m6Tuple.GetMembers(), + "System.Int32 (System.Int32 item1, System.Int32 item2).Item1", + "System.Int32 (System.Int32 item1, System.Int32 item2).item1", + "System.Int32 (System.Int32 item1, System.Int32 item2).Item2", + "System.Int32 (System.Int32 item1, System.Int32 item2).item2", + "(System.Int32 item1, System.Int32 item2)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32 item1, System.Int32 item2).ToString()", + "(System.Int32 item1, System.Int32 item2)..ctor()" + ); + + Assert.Equal("", m1Tuple.Name); + Assert.Equal(SymbolKind.NamedType, m1Tuple.Kind); + Assert.Equal(TypeKind.Struct, m1Tuple.TypeKind); + Assert.False(m1Tuple.IsImplicitlyDeclared); + Assert.True(m1Tuple.IsTupleType); + Assert.Equal("System.ValueTuple", m1Tuple.TupleUnderlyingType.ToTestDisplayString()); + Assert.Same(m1Tuple, m1Tuple.ConstructedFrom); + Assert.Same(m1Tuple, m1Tuple.OriginalDefinition); + AssertTupleTypeEquality(m1Tuple); + Assert.Same(m1Tuple.TupleUnderlyingType.ContainingSymbol, m1Tuple.ContainingSymbol); + Assert.Null(m1Tuple.GetUseSiteDiagnostic()); + Assert.Null(m1Tuple.EnumUnderlyingType); + Assert.Equal(new string[] { "Item1", "Item2", ".ctor", "ToString" }, + m1Tuple.MemberNames.ToArray()); + Assert.Equal(new string[] { "Item1", "a2", "Item2", "b2", ".ctor", "ToString" }, + m2Tuple.MemberNames.ToArray()); + Assert.Equal(0, m1Tuple.Arity); + Assert.True(m1Tuple.TypeParameters.IsEmpty); + Assert.Equal("System.ValueType", m1Tuple.BaseType.ToTestDisplayString()); + Assert.Null(m1Tuple.ComImportCoClass); + Assert.False(m1Tuple.HasTypeArgumentsCustomModifiers); + Assert.False(m1Tuple.IsComImport); + Assert.True(m1Tuple.TypeArgumentsCustomModifiers.IsEmpty); + Assert.True(m1Tuple.TypeArgumentsNoUseSiteDiagnostics.IsEmpty); + Assert.True(m1Tuple.GetAttributes().IsEmpty); + Assert.Equal("System.Int32 (System.Int32 a2, System.Int32 b2).Item1", m2Tuple.GetMembers("Item1").Single().ToTestDisplayString()); + Assert.Equal("System.Int32 (System.Int32 a2, System.Int32 b2).a2", m2Tuple.GetMembers("a2").Single().ToTestDisplayString()); + Assert.True(m1Tuple.GetTypeMembers().IsEmpty); + Assert.True(m1Tuple.GetTypeMembers("C9").IsEmpty); + Assert.True(m1Tuple.GetTypeMembers("C9", 0).IsEmpty); + Assert.True(m1Tuple.Interfaces.IsEmpty); + Assert.Equal(new string[] { "Item1", "Item2", ".ctor", ".ctor", "ToString" }, + m1Tuple.GetEarlyAttributeDecodingMembers().Select(m => m.Name).ToArray()); + Assert.Equal("System.Int32 (System.Int32, System.Int32).Item1", m1Tuple.GetEarlyAttributeDecodingMembers("Item1").Single().ToTestDisplayString()); + Assert.True(m1Tuple.GetTypeMembersUnordered().IsEmpty); + Assert.Equal(1, m1Tuple.Locations.Length); + Assert.Equal("(1, 11)", m1Tuple.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("(a2: 2, b2: 22)", m2Tuple.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("public struct ValueTuple", m1Tuple.TupleUnderlyingType.DeclaringSyntaxReferences.Single().GetSyntax().ToString().Substring(0, 32)); + + AssertTupleTypeEquality(m2Tuple); + AssertTupleTypeEquality(m6Tuple); + + Assert.False(m1Tuple.Equals(m2Tuple)); + Assert.False(m1Tuple.Equals(m6Tuple)); + Assert.False(m6Tuple.Equals(m2Tuple)); + AssertTupleTypeMembersEquality(m1Tuple, m2Tuple); + AssertTupleTypeMembersEquality(m1Tuple, m6Tuple); + AssertTupleTypeMembersEquality(m2Tuple, m6Tuple); + + var m1Item1 = (FieldSymbol)m1Tuple.GetMembers()[0]; + var m2Item1 = (FieldSymbol)m2Tuple.GetMembers()[0]; + var m2a2 = (FieldSymbol)m2Tuple.GetMembers()[1]; + + Assert.IsType(m1Item1); + Assert.IsType(m2Item1); + Assert.IsType(m2a2); + + Assert.True(m1Item1.IsTupleField); + Assert.Same(m1Item1, m1Item1.OriginalDefinition); + Assert.True(m1Item1.Equals(m1Item1)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m1Item1.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m1Item1.AssociatedSymbol); + Assert.Same(m1Tuple, m1Item1.ContainingSymbol); + Assert.Same(m1Tuple.TupleUnderlyingType, m1Item1.TupleUnderlyingField.ContainingSymbol); + Assert.True(m1Item1.CustomModifiers.IsEmpty); + Assert.True(m1Item1.GetAttributes().IsEmpty); + Assert.Null(m1Item1.GetUseSiteDiagnostic()); + Assert.False(m1Item1.Locations.IsDefaultOrEmpty); + Assert.Equal("1", m1Item1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m1Item1.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m1Item1.IsImplicitlyDeclared); + Assert.Null(m1Item1.TypeLayoutOffset); + + Assert.True(m2Item1.IsTupleField); + Assert.Same(m2Item1, m2Item1.OriginalDefinition); + Assert.True(m2Item1.Equals(m2Item1)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m2Item1.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m2Item1.AssociatedSymbol); + Assert.Same(m2Tuple, m2Item1.ContainingSymbol); + Assert.Same(m2Tuple.TupleUnderlyingType, m2Item1.TupleUnderlyingField.ContainingSymbol); + Assert.True(m2Item1.CustomModifiers.IsEmpty); + Assert.True(m2Item1.GetAttributes().IsEmpty); + Assert.Null(m2Item1.GetUseSiteDiagnostic()); + Assert.False(m2Item1.Locations.IsDefaultOrEmpty); + Assert.Equal("Item1", m2Item1.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m2Item1.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal(m2Item1.Locations.Single(), m2Item1.TupleUnderlyingField.Locations.Single()); + Assert.False(m2Item1.IsImplicitlyDeclared); + Assert.Null(m2Item1.TypeLayoutOffset); + + Assert.True(m2a2.IsTupleField); + Assert.Same(m2a2, m2a2.OriginalDefinition); + Assert.True(m2a2.Equals(m2a2)); + Assert.Equal("System.Int32 System.ValueTuple.Item1", m2a2.TupleUnderlyingField.ToTestDisplayString()); + Assert.Null(m2a2.AssociatedSymbol); + Assert.Same(m2Tuple, m2a2.ContainingSymbol); + Assert.Same(m2Tuple.TupleUnderlyingType, m2a2.TupleUnderlyingField.ContainingSymbol); + Assert.True(m2a2.CustomModifiers.IsEmpty); + Assert.True(m2a2.GetAttributes().IsEmpty); + Assert.Null(m2a2.GetUseSiteDiagnostic()); + Assert.False(m2a2.Locations.IsDefaultOrEmpty); + Assert.Equal("a2", m2a2.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.Equal("Item1", m2a2.TupleUnderlyingField.DeclaringSyntaxReferences.Single().GetSyntax().ToString()); + Assert.False(m2a2.IsImplicitlyDeclared); + Assert.Null(m2a2.TypeLayoutOffset); + + var m1ToString = m1Tuple.GetMember("ToString"); + + Assert.True(m1ToString.IsTupleMethod); + Assert.Same(m1ToString, m1ToString.OriginalDefinition); + Assert.Same(m1ToString, m1ToString.ConstructedFrom); + Assert.Equal("System.String System.ValueTuple.ToString()", + m1ToString.TupleUnderlyingMethod.ToTestDisplayString()); + Assert.Same(m1ToString.TupleUnderlyingMethod, m1ToString.TupleUnderlyingMethod.ConstructedFrom); + Assert.Same(m1Tuple, m1ToString.ContainingSymbol); + Assert.Same(m1Tuple.TupleUnderlyingType, m1ToString.TupleUnderlyingMethod.ContainingType); + Assert.Null(m1ToString.AssociatedSymbol); + Assert.False(m1ToString.IsExplicitInterfaceImplementation); + Assert.True(m1ToString.ExplicitInterfaceImplementations.IsEmpty); + Assert.False(m1ToString.ReturnsVoid); + Assert.True(m1ToString.TypeArguments.IsEmpty); + Assert.True(m1ToString.TypeParameters.IsEmpty); + Assert.True(m1ToString.GetAttributes().IsEmpty); + Assert.Null(m1ToString.GetUseSiteDiagnostic()); + Assert.Equal("System.String System.ValueType.ToString()", + m1ToString.OverriddenMethod.ToTestDisplayString()); + Assert.False(m1ToString.Locations.IsDefaultOrEmpty); + Assert.Equal("public override string ToString()", m1ToString.DeclaringSyntaxReferences.Single().GetSyntax().ToString().Substring(0, 33)); + Assert.Equal(m1ToString.Locations.Single(), m1ToString.TupleUnderlyingMethod.Locations.Single()); + } + + [Fact] + public void CustomValueTupleWithStrangeThings_01() + { + var source = @" + +class C +{ + static void Main() + { + var x1 = M9().Item1; + var x2 = M9().Item2; + + var y = (int, int).C9; + + System.ValueTuple.C9 z = null; + System.Console.WriteLine(z); + } + + static (int, int) M9() + { + return (901, 902); + } +} + +namespace System +{ + + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public class C9{} + } +} +"; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics( + // (10,18): error CS1525: Invalid expression term 'int' + // var y = (int, int).C9; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(10, 18), + // (10,23): error CS1525: Invalid expression term 'int' + // var y = (int, int).C9; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(10, 23) + ); + + var c = comp.GetTypeByMetadataName("C"); + + var m9Tuple = c.GetMember("M9").ReturnType; + AssertTupleTypeEquality(m9Tuple); + + AssertTestDisplayString(m9Tuple.GetMembers(), + "System.Int32 (System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32).Item2", + "(System.Int32, System.Int32)..ctor(System.Int32 item1, System.Int32 item2)", + "System.String (System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32)..ctor()"); + + AssertTestDisplayString(m9Tuple.TupleUnderlyingType.GetMembers(), + "System.Int32 System.ValueTuple.Item1", + "System.Int32 System.ValueTuple.Item2", + "System.ValueTuple..ctor(System.Int32 item1, System.Int32 item2)", + "System.String System.ValueTuple.ToString()", + "System.ValueTuple.C9", + "System.ValueTuple..ctor()"); + + Assert.True(m9Tuple.GetTypeMembers().IsEmpty); + Assert.True(m9Tuple.GetTypeMembers("C9").IsEmpty); + Assert.True(m9Tuple.GetTypeMembers("C9", 0).IsEmpty); + Assert.True(m9Tuple.GetTypeMembersUnordered().IsEmpty); + } + + [Fact] + public void CustomValueTupleWithStrangeThings_02() + { + var source = @" +partial class C +{ + static void Main() + { + } + + public static (int, int) M10() + { + return (101, 102); + } + + static (int, int, int, int, int, int, int, int, int) M101() + { + return (1, 1, 1, 1, 1, 1, 1, 1, 1); + } + + I1 Test01() + { + return M10(); + } + + static (int a, int b) M102() + { + return (1, 1); + } + + void Test02() + { + System.Console.WriteLine(M10().Item1); + System.Console.WriteLine(M10().Item20); + System.Console.WriteLine(M102().a); + } + + static (int a, int b, int c, int d, int e, int f, int g, int h, int Item2) M103() + { + return (1, 1, 1, 1, 1, 1, 1, 1, 1); + } +} + +interface I1 +{ + void M1(); +} +namespace System +{ + [Obsolete] + public struct ValueTuple : I1 + { + [Obsolete] + public T1 Item1; + + [System.Runtime.InteropServices.FieldOffsetAttribute(20)] + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + this.Item20 = 0; + this.Item21 = 0; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public class C9{} + + void I1.M1(){} + + [Obsolete] + public byte Item20; + + [System.Runtime.InteropServices.FieldOffsetAttribute(21)] + public byte Item21; + + [Obsolete] + public void M2() {} + } +} + +partial class C +{ + static void Test03() + { + M10().M2(); + } +} +" + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + + var c = comp.GetTypeByMetadataName("C"); + comp.VerifyDiagnostics( + // (8,19): warning CS0612: '(int, int)' is obsolete + // public static (int, int) M10() + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "(int, int)").WithArguments("(int, int)").WithLocation(8, 19), + // (23,12): warning CS0612: '(int a, int b)' is obsolete + // static (int a, int b) M102() + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "(int a, int b)").WithArguments("(int a, int b)").WithLocation(23, 12), + // (35,73): error CS8201: Tuple member name 'Item2' is only allowed at position 2. + // static (int a, int b, int c, int d, int e, int f, int g, int h, int Item2) M103() + Diagnostic(ErrorCode.ERR_TupleReservedMemberName, "Item2").WithArguments("Item2", "2").WithLocation(35, 73), + // (53,10): error CS0636: The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit) + // [System.Runtime.InteropServices.FieldOffsetAttribute(20)] + Diagnostic(ErrorCode.ERR_StructOffsetOnBadStruct, "System.Runtime.InteropServices.FieldOffsetAttribute").WithLocation(53, 10), + // (76,10): error CS0636: The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit) + // [System.Runtime.InteropServices.FieldOffsetAttribute(21)] + Diagnostic(ErrorCode.ERR_StructOffsetOnBadStruct, "System.Runtime.InteropServices.FieldOffsetAttribute").WithLocation(76, 10), + // (30,34): warning CS0612: '(int, int).Item1' is obsolete + // System.Console.WriteLine(M10().Item1); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "M10().Item1").WithArguments("(int, int).Item1").WithLocation(30, 34), + // (31,34): warning CS0612: '(int, int).Item20' is obsolete + // System.Console.WriteLine(M10().Item20); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "M10().Item20").WithArguments("(int, int).Item20").WithLocation(31, 34), + // (32,34): warning CS0612: '(int a, int b).a' is obsolete + // System.Console.WriteLine(M102().a); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "M102().a").WithArguments("(int a, int b).a").WithLocation(32, 34), + // (88,9): warning CS0612: '(int, int).M2()' is obsolete + // M10().M2(); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "M10().M2()").WithArguments("(int, int).M2()").WithLocation(88, 9) + ); + + var m10Tuple = (NamedTypeSymbol)c.GetMember("M10").ReturnType; + AssertTupleTypeEquality(m10Tuple); + + Assert.Equal("System.ObsoleteAttribute", m10Tuple.GetAttributes().Single().ToString()); + Assert.Equal("I1", m10Tuple.Interfaces.Single().ToTestDisplayString()); + + var m102Tuple = (NamedTypeSymbol)c.GetMember("M102").ReturnType; + AssertTupleTypeEquality(m102Tuple); + + var m10Item1 = (FieldSymbol)m10Tuple.GetMembers("Item1").Single(); + var m102Item20 = (FieldSymbol)m102Tuple.GetMembers("Item20").Single(); + var m102a = (FieldSymbol)m102Tuple.GetMembers("a").Single(); + + Assert.IsType(m10Item1); + Assert.IsType(m102Item20); + Assert.IsType(m102a); + + Assert.Equal("System.ObsoleteAttribute", m10Item1.GetAttributes().Single().ToString()); + Assert.Equal("System.ObsoleteAttribute", m102Item20.GetAttributes().Single().ToString()); + Assert.Equal("System.ObsoleteAttribute", m102a.GetAttributes().Single().ToString()); + + var m10Item2 = (FieldSymbol)m10Tuple.GetMembers("Item2").Single(); + var m102Item21 = (FieldSymbol)m102Tuple.GetMembers("Item21").Single(); + var m102Item2 = (FieldSymbol)m102Tuple.GetMembers("Item2").Single(); + var m102b = (FieldSymbol)m102Tuple.GetMembers("b").Single(); + + Assert.IsType(m10Item2); + Assert.IsType(m102Item2); + Assert.IsType(m102Item21); + Assert.IsType(m102b); + + Assert.Equal(20, m10Item2.TypeLayoutOffset); + Assert.Equal(20, m102Item2.TypeLayoutOffset); + Assert.Equal(21, m102Item21.TypeLayoutOffset); + Assert.Null(m102b.TypeLayoutOffset); + Assert.Equal(20, m102b.TupleUnderlyingField.TypeLayoutOffset); + + var m103Tuple = (NamedTypeSymbol)c.GetMember("M103").ReturnType; + AssertTupleTypeEquality(m103Tuple); + + var m103Item2 = (FieldSymbol)m103Tuple.GetMembers("Item2").Last(); + var m103Item9 = (FieldSymbol)m103Tuple.GetMembers("Item9").Single(); + + Assert.IsType(m103Item2); + Assert.IsType(m103Item9); + Assert.Null(m103Item2.TypeLayoutOffset); + Assert.Equal(20, m103Item2.TupleUnderlyingField.TypeLayoutOffset); + Assert.Null(m103Item9.TypeLayoutOffset); + Assert.Equal(20, m103Item9.TupleUnderlyingField.TypeLayoutOffset); + + var m10I1M1 = m10Tuple.GetMember("I1.M1"); + + Assert.True(m10I1M1.IsExplicitInterfaceImplementation); + Assert.Equal("void I1.M1()", m10I1M1.ExplicitInterfaceImplementations.Single().ToTestDisplayString()); + + var m10M2 = m10Tuple.GetMember("M2"); + Assert.Equal("System.ObsoleteAttribute", m10M2.GetAttributes().Single().ToString()); + } + + [Fact] + public void CustomValueTupleWithGenericMethod() + { + var source = @" + +class C +{ + static void Main() + { + M9().Test(""Yes""); + } + + static (int, int) M9() + { + return (901, 902); + } +} + +namespace System +{ + + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public void Test(U val) + { + System.Console.WriteLine(typeof(U)); + System.Console.WriteLine(val); + } + } +} +"; + + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithTuplesFeature()); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: +@"System.String +Yes"); + + var c = comp.GetTypeByMetadataName("C"); + + var m9Tuple = c.GetMember("M9").ReturnType; + AssertTupleTypeEquality(m9Tuple); + + var m9Test = m9Tuple.GetMember("Test"); + Assert.True(m9Test.IsTupleMethod); + Assert.Same(m9Test, m9Test.OriginalDefinition); + Assert.Same(m9Test, m9Test.ConstructedFrom); + Assert.Equal("void System.ValueTuple.Test(U val)", + m9Test.TupleUnderlyingMethod.ToTestDisplayString()); + Assert.Same(m9Test.TupleUnderlyingMethod, m9Test.TupleUnderlyingMethod.ConstructedFrom); + Assert.Same(m9Tuple.TupleUnderlyingType, m9Test.TupleUnderlyingMethod.ContainingType); + Assert.Same(m9Test.TypeParameters.Single(), m9Test.TypeParameters.Single().OriginalDefinition); + Assert.Same(m9Test, m9Test.TypeParameters.Single().ContainingSymbol); + Assert.Same(m9Test, m9Test.Parameters.Single().ContainingSymbol); + Assert.Equal(0, m9Test.TypeParameters.Single().Ordinal); + Assert.Equal(1, m9Test.Arity); + } + + [Fact] + public void CreationOfTupleSymbols_01() + { + var source = @" +class C +{ + static void Main() + { + } + + static (int, int) M1() + { + return (101, 102); + } + + static (int, int, int, int, int, int, int, int, int) M2() + { + return (1, 1, 1, 1, 1, 1, 1, 1, 1); + } + + static (int, int, int) M3() + { + return (101, 102, 103); + } +} + +namespace System +{ + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2, T3 item3) + { + this.Item1 = item1; + this.Item2 = item2; + } + } +} +" + trivial2uple + trivalRemainingTuples; + + var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular.WithTuplesFeature()); + + var c = comp.GetTypeByMetadataName("C"); + comp.VerifyDiagnostics(); + + var m1Tuple = (NamedTypeSymbol)c.GetMember("M1").ReturnType; + { + var t1 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + var t2 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + + Assert.True(t1.Equals(t2)); + AssertTupleTypeMembersEquality(t1, t2); + + var t3 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("a", "b")); + var t4 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("a", "b")); + var t5 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("b", "a")); + + Assert.False(t1.Equals(t3)); + Assert.True(t1.Equals(t3, false, true)); + Assert.True(t3.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t3); + + Assert.True(t3.Equals(t4)); + AssertTupleTypeMembersEquality(t3, t4); + + Assert.False(t5.Equals(t3)); + Assert.True(t5.Equals(t3, false, true)); + Assert.True(t3.Equals(t5, false, true)); + AssertTupleTypeMembersEquality(t5, t3); + + var t6 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item1", "Item2")); + var t7 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item1", "Item2")); + + Assert.True(t6.Equals(t7)); + AssertTupleTypeMembersEquality(t6, t7); + + Assert.False(t1.Equals(t6)); + Assert.True(t1.Equals(t6, false, true)); + Assert.True(t6.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t6); + + var t8 = TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item2", "Item1")); + + Assert.False(t1.Equals(t8)); + Assert.True(t1.Equals(t8, false, true)); + Assert.True(t8.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t8); + + Assert.False(t6.Equals(t8)); + Assert.True(t6.Equals(t8, false, true)); + Assert.True(t8.Equals(t6, false, true)); + AssertTupleTypeMembersEquality(t6, t8); + } + + var m2Tuple = (NamedTypeSymbol)c.GetMember("M2").ReturnType; + { + var t1 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + var t2 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + + Assert.True(t1.Equals(t2)); + AssertTupleTypeMembersEquality(t1, t2); + + var t3 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("a", "b", "c", "d", "e", "f", "g", "h", "i")); + var t4 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("a", "b", "c", "d", "e", "f", "g", "h", "i")); + var t5 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("a", "b", "c", "d", "e", "f", "g", "i", "h")); + + Assert.False(t1.Equals(t3)); + Assert.True(t1.Equals(t3, false, true)); + Assert.True(t3.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t3); + + Assert.True(t3.Equals(t4)); + AssertTupleTypeMembersEquality(t3, t4); + + Assert.False(t5.Equals(t3)); + Assert.True(t5.Equals(t3, false, true)); + Assert.True(t3.Equals(t5, false, true)); + AssertTupleTypeMembersEquality(t5, t3); + + var t6 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")); + var t7 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")); + + Assert.True(t6.Equals(t7)); + AssertTupleTypeMembersEquality(t6, t7); + + Assert.False(t1.Equals(t6)); + Assert.True(t1.Equals(t6, false, true)); + Assert.True(t6.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t6); + + var t8 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item9", "Item8")); + + Assert.False(t1.Equals(t8)); + Assert.True(t1.Equals(t8, false, true)); + Assert.True(t8.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t8); + + Assert.False(t6.Equals(t8)); + Assert.True(t6.Equals(t8, false, true)); + Assert.True(t8.Equals(t6, false, true)); + AssertTupleTypeMembersEquality(t6, t8); + + var t9 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("a", "b", "c", "d", "e", "f", "g", "Item1", "Item2")); + var t10 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType, default(ImmutableArray), + ImmutableArray.Create("a", "b", "c", "d", "e", "f", "g", "Item1", "Item2")); + + Assert.True(t9.Equals(t10)); + AssertTupleTypeMembersEquality(t9, t10); + + var t11 = TupleTypeSymbol.Create(null, m2Tuple.TupleUnderlyingType.OriginalDefinition.Construct( + m2Tuple.TupleUnderlyingType.TypeArgumentsNoUseSiteDiagnostics.RemoveAt(7). + Add(TupleTypeSymbol.Create(null, m1Tuple.TupleUnderlyingType, + default(ImmutableArray), + ImmutableArray.Create("a", "b"))) + ), + default(ImmutableArray), + default(ImmutableArray)); + + Assert.False(t1.Equals(t11)); + AssertTupleTypeMembersEquality(t1, t11); + Assert.True(t1.Equals(t11, false, true)); + Assert.True(t11.Equals(t1, false, true)); + Assert.False(t1.TupleUnderlyingType.Equals(t11.TupleUnderlyingType)); + Assert.True(t1.TupleUnderlyingType.Equals(t11.TupleUnderlyingType, false, true)); + Assert.False(t11.TupleUnderlyingType.Equals(t1.TupleUnderlyingType)); + Assert.True(t11.TupleUnderlyingType.Equals(t1.TupleUnderlyingType, false, true)); + + AssertTestDisplayString(t11.GetMembers(), + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item1", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item2", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item3", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item4", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item5", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item6", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item7", + "(System.Int32 a, System.Int32 b) (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Rest", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor" + + "(System.Int32 item1, System.Int32 item2, System.Int32 item3, System.Int32 item4, System.Int32 item5, System.Int32 item6, System.Int32 item7, " + + "(System.Int32 a, System.Int32 b) rest)", + "System.String (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).ToString()", + "(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)..ctor()", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item8", + "System.Int32 (System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32).Item9" + ); + } + + var m3Tuple = (NamedTypeSymbol)c.GetMember("M3").ReturnType; + { + var t1 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + var t2 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), default(ImmutableArray)); + + Assert.True(t1.Equals(t2)); + AssertTupleTypeMembersEquality(t1, t2); + + var t3 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("a", "b", "c")); + var t4 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("a", "b", "c")); + var t5 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("c", "b", "a")); + + Assert.False(t1.Equals(t3)); + Assert.True(t1.Equals(t3, false, true)); + Assert.True(t3.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t3); + + Assert.True(t3.Equals(t4)); + AssertTupleTypeMembersEquality(t3, t4); + + Assert.False(t5.Equals(t3)); + Assert.True(t5.Equals(t3, false, true)); + Assert.True(t3.Equals(t5, false, true)); + AssertTupleTypeMembersEquality(t5, t3); + + var t6 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item1", "Item2", "Item3")); + var t7 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item1", "Item2", "Item3")); + + Assert.True(t6.Equals(t7)); + AssertTupleTypeMembersEquality(t6, t7); + + Assert.False(t1.Equals(t6)); + Assert.True(t1.Equals(t6, false, true)); + Assert.True(t6.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t6); + + var t8 = TupleTypeSymbol.Create(null, m3Tuple.TupleUnderlyingType, default(ImmutableArray), ImmutableArray.Create("Item2", "Item3", "Item1")); + + Assert.False(t1.Equals(t8)); + Assert.True(t1.Equals(t8, false, true)); + Assert.True(t8.Equals(t1, false, true)); + AssertTupleTypeMembersEquality(t1, t8); + + Assert.False(t6.Equals(t8)); + Assert.True(t6.Equals(t8, false, true)); + Assert.True(t8.Equals(t6, false, true)); + AssertTupleTypeMembersEquality(t6, t8); + } + } + + private static void AssertTestDisplayString(ImmutableArray symbols, params string[] baseLine) + { + int common = Math.Min(symbols.Length, baseLine.Length); + for (int i = 0; i < common; i++) + { + Assert.Equal(baseLine[i], symbols[i].ToTestDisplayString()); + } + + Assert.Equal(new string[] { }, symbols.Skip(common).Select(s => s.ToTestDisplayString()).ToArray()); + Assert.Equal(baseLine.Length, symbols.Length); + } + } +} \ No newline at end of file diff --git a/src/Compilers/Core/SharedCollections/ArrayBuilder.cs b/src/Compilers/Core/SharedCollections/ArrayBuilder.cs index 58031f51c3169..1b3e1999a1648 100644 --- a/src/Compilers/Core/SharedCollections/ArrayBuilder.cs +++ b/src/Compilers/Core/SharedCollections/ArrayBuilder.cs @@ -143,6 +143,11 @@ public int IndexOf(T item) { return _builder.IndexOf(item); } + + public int IndexOf(T item, IEqualityComparer equalityComparer) + { + return _builder.IndexOf(item, 0, _builder.Count, equalityComparer); + } public int IndexOf(T item, int startIndex, int count) { From 1a6fce18a7f664412b946fad6a0fd9d6d5bfa5b8 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sun, 1 May 2016 00:59:43 -0700 Subject: [PATCH 3/3] Move TupleTypeSymbol.cs and TupleFieldSymbol.cs into Tuples folder. --- src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj | 4 ++-- .../CSharp/Portable/Symbols/{ => Tuples}/TupleFieldSymbol.cs | 0 .../CSharp/Portable/Symbols/{ => Tuples}/TupleTypeSymbol.cs | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/Compilers/CSharp/Portable/Symbols/{ => Tuples}/TupleFieldSymbol.cs (100%) rename src/Compilers/CSharp/Portable/Symbols/{ => Tuples}/TupleTypeSymbol.cs (100%) diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index d0a525b838155..a7415741e6803 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -511,11 +511,11 @@ - + - + diff --git a/src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleFieldSymbol.cs similarity index 100% rename from src/Compilers/CSharp/Portable/Symbols/TupleFieldSymbol.cs rename to src/Compilers/CSharp/Portable/Symbols/Tuples/TupleFieldSymbol.cs diff --git a/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs similarity index 100% rename from src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs rename to src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs