protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifiers, ref TypeSymbolWithAnnotations type, AssemblySymbol containingAssembly) { Debug.Assert((object)eventWithCustomModifiers != null); TypeSymbol overriddenEventType = eventWithCustomModifiers.Type.TypeSymbol; // We do an extra check before copying the type to handle the case where the overriding // event (incorrectly) has a different type than the overridden event. In such cases, // we want to retain the original (incorrect) type to avoid hiding the type given in source. if (type.TypeSymbol.Equals(overriddenEventType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic)) { type = type.WithTypeAndModifiers(CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type.TypeSymbol, containingAssembly), eventWithCustomModifiers.Type.CustomModifiers); } }
/// <remarks> /// Out params are updated by assignment. If you require thread-safety, pass temps and then /// CompareExchange them back into shared memory. /// </remarks> internal static void CopyMethodCustomModifiers( MethodSymbol sourceMethod, MethodSymbol destinationMethod, out TypeSymbolWithAnnotations returnType, out ImmutableArray <CustomModifier> customModifiers, out ImmutableArray <ParameterSymbol> parameters, bool alsoCopyParamsModifier) // Last since always named. { Debug.Assert((object)sourceMethod != null); // Assert: none of the method's type parameters have been substituted Debug.Assert((object)sourceMethod == sourceMethod.ConstructedFrom); // For the most part, we will copy custom modifiers by copying types. // The only time when this fails is when the type refers to a type parameter // owned by the overridden method. We need to replace all such references // with (equivalent) type parameters owned by this method. We know that // we can perform this mapping positionally, because the method signatures // have already been compared. MethodSymbol constructedSourceMethod = sourceMethod.ConstructIfGeneric(destinationMethod.TypeArguments); customModifiers = destinationMethod.RefKind != RefKind.None ? constructedSourceMethod.RefCustomModifiers : ImmutableArray <CustomModifier> .Empty; parameters = CopyParameterCustomModifiers(constructedSourceMethod.Parameters, destinationMethod.Parameters, alsoCopyParamsModifier); returnType = destinationMethod.ReturnType; // Default value - in case we don't copy the custom modifiers. TypeSymbol returnTypeSymbol = returnType.TypeSymbol; var sourceMethodReturnType = constructedSourceMethod.ReturnType; // We do an extra check before copying the return type to handle the case where the overriding // method (incorrectly) has a different return type than the overridden method. In such cases, // we want to retain the original (incorrect) return type to avoid hiding the return type // given in source. TypeSymbol returnTypeWithCustomModifiers = sourceMethodReturnType.TypeSymbol; if (returnTypeSymbol.Equals(returnTypeWithCustomModifiers, TypeCompareKind.AllIgnoreOptions)) { returnType = returnType.WithTypeAndModifiers(CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnTypeSymbol, destinationMethod.ContainingAssembly), sourceMethodReturnType.CustomModifiers); } }
protected override void MethodChecks(DiagnosticBag diagnostics) { // These values may not be final, but we need to have something set here in the // event that we need to find the overridden accessor. _lazyParameters = ComputeParameters(diagnostics); _lazyReturnType = ComputeReturnType(diagnostics); _lazyRefCustomModifiers = ImmutableArray <CustomModifier> .Empty; if (_explicitInterfaceImplementations.Length > 0) { Debug.Assert(_explicitInterfaceImplementations.Length == 1); MethodSymbol implementedMethod = _explicitInterfaceImplementations[0]; CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: false); } else if (this.IsOverride) { // This will cause another call to SourceMethodSymbol.LazyMethodChecks, // but that method already handles reentrancy for exactly this case. MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: true); } } else if (_lazyReturnType.SpecialType != SpecialType.System_Void) { PropertySymbol associatedProperty = _property; var type = associatedProperty.Type; _lazyReturnType = _lazyReturnType.WithTypeAndModifiers( CustomModifierUtils.CopyTypeCustomModifiers(type.TypeSymbol, _lazyReturnType.TypeSymbol, this.ContainingAssembly), type.CustomModifiers); _lazyRefCustomModifiers = associatedProperty.RefCustomModifiers; } }
private PEParameterSymbol( PEModuleSymbol moduleSymbol, Symbol containingSymbol, int ordinal, bool isByRef, TypeSymbolWithAnnotations type, ImmutableArray <bool> extraAnnotations, ParameterHandle handle, int countOfCustomModifiers, out bool isBad) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); Debug.Assert(!type.IsNull); isBad = false; _moduleSymbol = moduleSymbol; _containingSymbol = containingSymbol; _ordinal = (ushort)ordinal; _handle = handle; RefKind refKind = RefKind.None; if (handle.IsNil) { refKind = isByRef ? RefKind.Ref : RefKind.None; type = TupleTypeSymbol.TryTransformToTuple(type.TypeSymbol, out TupleTypeSymbol tuple) ? TypeSymbolWithAnnotations.Create(tuple) : type; if (!extraAnnotations.IsDefault) { // https://github.com/dotnet/roslyn/issues/29821 any external annotation is taken to imply a `[NonNullTypes(true)]` context type = NullableTypeDecoder.TransformType(type, extraAnnotations, nonNullTypesContext: NonNullTypesTrueContext.Instance); } _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyDefaultValue = ConstantValue.NotAvailable; _lazyIsParams = ThreeState.False; } else { try { moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags); } catch (BadImageFormatException) { isBad = true; } if (isByRef) { ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In); if (inOutFlags == ParameterAttributes.Out) { refKind = RefKind.Out; } else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { refKind = RefKind.In; } else { refKind = RefKind.Ref; } } // CONSIDER: Can we make parameter type computation lazy? var typeSymbol = DynamicTypeDecoder.TransformType(type.TypeSymbol, countOfCustomModifiers, handle, moduleSymbol, refKind); type = type.WithTypeAndModifiers(typeSymbol, type.CustomModifiers); // Decode nullable before tuple types to avoid converting between // NamedTypeSymbol and TupleTypeSymbol unnecessarily. type = NullableTypeDecoder.TransformType(type, handle, moduleSymbol, nonNullTypesContext: this, extraAnnotations); type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol); } _type = type; bool hasNameInMetadata = !string.IsNullOrEmpty(_name); if (!hasNameInMetadata) { // As was done historically, if the parameter doesn't have a name, we give it the name "value". _name = "value"; } _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata); Debug.Assert(refKind == this.RefKind); Debug.Assert(hasNameInMetadata == this.HasNameInMetadata); }