private BoundExpression MakePair(CSharpSyntaxNode node, string field1Name, BoundExpression field1Value, string field2Name, BoundExpression field2Value, QueryTranslationState state, DiagnosticBag diagnostics) { if (field1Name == field2Name) { // we will generate a diagnostic elsewhere field2Name = state.TransparentRangeVariableName(); field2Value = new BoundBadExpression(field2Value.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(field2Value), field2Value.Type, true); } AnonymousTypeDescriptor typeDescriptor = new AnonymousTypeDescriptor( ImmutableArray.Create <AnonymousTypeField>( new AnonymousTypeField(field1Name, field1Value.Syntax.Location, TypeSymbolWithAnnotations.Create(TypeOrError(field1Value))), new AnonymousTypeField(field2Name, field2Value.Syntax.Location, TypeSymbolWithAnnotations.Create(TypeOrError(field2Value))) ), node.Location ); AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager; NamedTypeSymbol anonymousType = manager.ConstructAnonymousTypeSymbol(typeDescriptor); return(MakeConstruction(node, anonymousType, ImmutableArray.Create(field1Value, field2Value), diagnostics)); }
internal override TypeSymbol MakeExtendedTypeSymbol(PEModuleSymbol moduleSymbol, TypeSymbol type, TypeAccessModifiers typeAccessModifiers) { switch (type.TypeKind) { case TypeKind.Array: return(new ExtendedArrayTypeSymbol(TypeSymbolWithAnnotations.Create(type), (ArrayTypeSymbol)type, typeAccessModifiers)); case TypeKind.Class: case TypeKind.Interface: case TypeKind.Struct: case TypeKind.Enum: return(new ExtendedNamedTypeSymbol(TypeSymbolWithAnnotations.Create(type), typeAccessModifiers)); case TypeKind.TypeParameter: return(new ExtendedTypeParameterSymbol((TypeParameterSymbol)type, typeAccessModifiers)); case TypeKind.ConstLiteral: case TypeKind.Module: case TypeKind.Submission: case TypeKind.Pointer: default: throw ExceptionUtilities.UnexpectedValue(type.TypeKind); } }
public static TypeSymbolWithAnnotations DecodeTupleTypesIfApplicable( TypeSymbolWithAnnotations metadataType, EntityHandle targetHandle, PEModuleSymbol containingModule) { ImmutableArray <string> elementNames; var hasTupleElementNamesAttribute = containingModule .Module .HasTupleElementNamesAttribute(targetHandle, out elementNames); // If we have the TupleElementNamesAttribute, but no names, that's // bad metadata if (hasTupleElementNamesAttribute && elementNames.IsDefaultOrEmpty) { return(TypeSymbolWithAnnotations.Create(new UnsupportedMetadataTypeSymbol())); } TypeSymbol type = metadataType.TypeSymbol; TypeSymbol decoded = DecodeTupleTypesInternal(type, elementNames, hasTupleElementNamesAttribute); return((object)decoded == (object)type ? metadataType : TypeSymbolWithAnnotations.Create(decoded, metadataType.NullableAnnotation, metadataType.CustomModifiers)); }
public LabelSymbol ProxyReturnIfNeeded( MethodSymbol containingMethod, BoundExpression valueOpt, out SynthesizedLocal returnValue) { returnValue = null; // no need to proxy returns at the root if (this.IsRoot()) { return(null); } var returnProxy = this.returnProxyLabel; if (returnProxy == null) { this.returnProxyLabel = returnProxy = new GeneratedLabelSymbol("returnProxy"); } if (valueOpt != null) { returnValue = this.returnValue; if (returnValue == null) { Debug.Assert(_statementSyntaxOpt != null); this.returnValue = returnValue = new SynthesizedLocal(containingMethod, TypeSymbolWithAnnotations.Create(valueOpt.Type), SynthesizedLocalKind.AsyncMethodReturnValue, _statementSyntaxOpt); } } return(returnProxy); }
public AwaitCatchFrame(SyntheticBoundNodeFactory F, TryStatementSyntax tryStatementSyntax) { this.pendingCaughtException = new SynthesizedLocal(F.CurrentFunction, TypeSymbolWithAnnotations.Create(F.SpecialType(SpecialType.System_Object)), SynthesizedLocalKind.TryAwaitPendingCaughtException, tryStatementSyntax); this.pendingCatch = new SynthesizedLocal(F.CurrentFunction, TypeSymbolWithAnnotations.Create(F.SpecialType(SpecialType.System_Int32)), SynthesizedLocalKind.TryAwaitPendingCatch, tryStatementSyntax); this.handlers = new List <BoundBlock>(); _hoistedLocals = new Dictionary <LocalSymbol, LocalSymbol>(); _orderedHoistedLocals = new List <LocalSymbol>(); }
internal static ImmutableArray <TypeSymbolWithAnnotations> TypeParametersAsTypeSymbolsWithAnnotations(ImmutableArray <TypeParameterSymbol> typeParameters) { return(typeParameters.SelectAsArray((tp) => TypeSymbolWithAnnotations.Create(tp))); }
internal PEEventSymbol( PEModuleSymbol moduleSymbol, PENamedTypeSymbol containingType, EventDefinitionHandle handle, PEMethodSymbol addMethod, PEMethodSymbol removeMethod, MultiDictionary <string, PEFieldSymbol> privateFieldNameToSymbols) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingType != null); Debug.Assert(!handle.IsNil); Debug.Assert((object)addMethod != null); Debug.Assert((object)removeMethod != null); _addMethod = addMethod; _removeMethod = removeMethod; _handle = handle; _containingType = containingType; EventAttributes mdFlags = 0; EntityHandle eventType = default(EntityHandle); try { var module = moduleSymbol.Module; module.GetEventDefPropsOrThrow(handle, out _name, out mdFlags, out eventType); } catch (BadImageFormatException mrEx) { if ((object)_name == null) { _name = string.Empty; } _lazyUseSiteDiagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); if (eventType.IsNil) { _eventType = TypeSymbolWithAnnotations.Create(new UnsupportedMetadataTypeSymbol(mrEx)); } } TypeSymbol originalEventType = _eventType.TypeSymbol; if (_eventType.IsNull) { var metadataDecoder = new MetadataDecoder(moduleSymbol, containingType); originalEventType = metadataDecoder.GetTypeOfToken(eventType); const int targetSymbolCustomModifierCount = 0; var typeSymbol = DynamicTypeDecoder.TransformType(originalEventType, targetSymbolCustomModifierCount, handle, moduleSymbol); // We start without annotation (they will be decoded below) var type = TypeSymbolWithAnnotations.Create(typeSymbol); // Decode nullable before tuple types to avoid converting between // NamedTypeSymbol and TupleTypeSymbol unnecessarily. type = NullableTypeDecoder.TransformType(type, handle, moduleSymbol); type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol); _eventType = type; } // IsWindowsRuntimeEvent checks the signatures, so we just have to check the accessors. bool isWindowsRuntimeEvent = IsWindowsRuntimeEvent; bool callMethodsDirectly = isWindowsRuntimeEvent ? !DoModifiersMatch(_addMethod, _removeMethod) : !DoSignaturesMatch(moduleSymbol, originalEventType, _addMethod, _removeMethod); if (callMethodsDirectly) { _flags |= Flags.CallMethodsDirectly; } else { _addMethod.SetAssociatedEvent(this, MethodKind.EventAdd); _removeMethod.SetAssociatedEvent(this, MethodKind.EventRemove); PEFieldSymbol associatedField = GetAssociatedField(privateFieldNameToSymbols, isWindowsRuntimeEvent); if ((object)associatedField != null) { _associatedFieldOpt = associatedField; associatedField.SetAssociatedEvent(this); } } if ((mdFlags & EventAttributes.SpecialName) != 0) { _flags |= Flags.IsSpecialName; } if ((mdFlags & EventAttributes.RTSpecialName) != 0) { _flags |= Flags.IsRuntimeSpecialName; } }
internal override TypeSymbolWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound) { return(TypeSymbolWithAnnotations.Create(((SourceNamedTypeSymbol)ContainingType).EnumUnderlyingType)); }
private static bool CanUnifyHelper(TypeSymbol t1, TypeSymbol t2, ref MutableTypeMap substitution) { return(CanUnifyHelper(TypeSymbolWithAnnotations.Create(t1), TypeSymbolWithAnnotations.Create(t2), ref substitution)); }
/// <summary> /// If the extension method is applicable based on the "this" argument type, return /// the method constructed with the inferred type arguments. If the method is not an /// unconstructed generic method, type inference is skipped. If the method is not /// applicable, or if constraints when inferring type parameters from the "this" type /// are not satisfied, the return value is null. /// </summary> public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol method, TypeSymbol thisType, Compilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { Debug.Assert(method.IsExtensionMethod); Debug.Assert((object)thisType != null); if (!method.IsGenericMethod || method != method.ConstructedFrom) { return(method); } // We never resolve extension methods on a dynamic receiver. if (thisType.IsDynamic()) { return(null); } var containingAssembly = method.ContainingAssembly; var errorNamespace = containingAssembly.GlobalNamespace; var conversions = new TypeConversions(containingAssembly.CorLibrary); // There is absolutely no plausible syntax/tree that we could use for these // synthesized literals. We could be speculatively binding a call to a PE method. var syntaxTree = CSharpSyntaxTree.Dummy; var syntax = (CSharpSyntaxNode)syntaxTree.GetRoot(); // Create an argument value for the "this" argument of specific type, // and pass the same bad argument value for all other arguments. var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType) { WasCompilerGenerated = true }; var otherArgumentType = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false); var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType) { WasCompilerGenerated = true }; var paramCount = method.ParameterCount; var arguments = new BoundExpression[paramCount]; for (int i = 0; i < paramCount; i++) { var argument = (i == 0) ? thisArgumentValue : otherArgumentValue; arguments[i] = argument; } var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument( conversions, method, arguments.AsImmutable(), useSiteDiagnostics: ref useSiteDiagnostics); if (typeArgs.IsDefault) { return(null); } int firstNullInTypeArgs = -1; // For the purpose of constraint checks we use error type symbol in place of type arguments that we couldn't infer from the first argument. // This prevents constraint checking from failing for corresponding type parameters. var notInferredTypeParameters = PooledHashSet <TypeParameterSymbol> .GetInstance(); var typeParams = method.TypeParameters; var typeArgsForConstraintsCheck = typeArgs; for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++) { if (typeArgsForConstraintsCheck[i].IsNull) { firstNullInTypeArgs = i; var builder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(); builder.AddRange(typeArgsForConstraintsCheck, firstNullInTypeArgs); for (; i < typeArgsForConstraintsCheck.Length; i++) { var typeArg = typeArgsForConstraintsCheck[i]; if (typeArg.IsNull) { notInferredTypeParameters.Add(typeParams[i]); builder.Add(TypeSymbolWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType)); } else { builder.Add(typeArg); } } typeArgsForConstraintsCheck = builder.ToImmutableAndFree(); break; } } // Check constraints. var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var success = method.CheckConstraints(conversions, substitution, typeParams, typeArgsForConstraintsCheck, compilation, diagnosticsBuilder, warningsBuilderOpt: null, ref useSiteDiagnosticsBuilder, ignoreTypeConstraintsDependentOnTypeParametersOpt: notInferredTypeParameters.Count > 0 ? notInferredTypeParameters : null); diagnosticsBuilder.Free(); notInferredTypeParameters.Free(); if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0) { if (useSiteDiagnostics == null) { useSiteDiagnostics = new HashSet <DiagnosticInfo>(); } foreach (var diag in useSiteDiagnosticsBuilder) { useSiteDiagnostics.Add(diag.DiagnosticInfo); } } if (!success) { return(null); } // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument. var typeArgsForConstruct = typeArgs; if (firstNullInTypeArgs != -1) { var builder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(); builder.AddRange(typeArgs, firstNullInTypeArgs); for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++) { var typeArgForConstruct = typeArgsForConstruct[i]; builder.Add(!typeArgForConstruct.IsNull ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i])); } typeArgsForConstruct = builder.ToImmutableAndFree(); } return(method.Construct(typeArgsForConstruct)); }
public BoundDeconstructValuePlaceholder FailInference(Binder binder) { return(SetInferredType(TypeSymbolWithAnnotations.Create(binder.CreateErrorType()), binder, success: false)); }
public void TypeMap() { var source = @" struct S<T> where T : struct { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); var intType = comp.GetSpecialType(SpecialType.System_Int32); var customModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateOptional(intType)); var structType = comp.GlobalNamespace.GetMember <NamedTypeSymbol>("S"); var typeParamType = structType.TypeParameters.Single(); var pointerType = new PointerTypeSymbol(TypeSymbolWithAnnotations.Create(typeParamType, customModifiers: customModifiers)); // NOTE: We're constructing this manually, since it's illegal. var arrayType = ArrayTypeSymbol.CreateCSharpArray(comp.Assembly, TypeSymbolWithAnnotations.Create(typeParamType, customModifiers: customModifiers)); // This is legal, but we're already manually constructing types. var typeMap = new TypeMap(ImmutableArray.Create(typeParamType), ImmutableArray.Create(TypeSymbolWithAnnotations.Create(intType))); var substitutedPointerType = (PointerTypeSymbol)typeMap.SubstituteType(pointerType).AsTypeSymbolOnly(); var substitutedArrayType = (ArrayTypeSymbol)typeMap.SubstituteType(arrayType).AsTypeSymbolOnly(); // The map changed the types. Assert.Equal(intType, substitutedPointerType.PointedAtType.TypeSymbol); Assert.Equal(intType, substitutedArrayType.ElementType.TypeSymbol); // The map preserved the custom modifiers. Assert.Equal(customModifiers, substitutedPointerType.PointedAtType.CustomModifiers); Assert.Equal(customModifiers, substitutedArrayType.ElementType.CustomModifiers); }
private DynamicAnalysisInjector( MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, MethodSymbol createPayloadForMethodsSpanningSingleFile, MethodSymbol createPayloadForMethodsSpanningMultipleFiles, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) : base(previous) { _createPayloadForMethodsSpanningSingleFile = createPayloadForMethodsSpanningSingleFile; _createPayloadForMethodsSpanningMultipleFiles = createPayloadForMethodsSpanningMultipleFiles; _method = method; _methodBody = methodBody; _spansBuilder = ArrayBuilder <SourceSpan> .GetInstance(); TypeSymbol payloadElementType = methodBodyFactory.SpecialType(SpecialType.System_Boolean); _payloadType = ArrayTypeSymbol.CreateCSharpArray(methodBodyFactory.Compilation.Assembly, TypeSymbolWithAnnotations.Create(payloadElementType)); _diagnostics = diagnostics; _debugDocumentProvider = debugDocumentProvider; _methodBodyFactory = methodBodyFactory; // Set the factory context to generate nodes for the current method var oldMethod = methodBodyFactory.CurrentFunction; methodBodyFactory.CurrentFunction = method; _methodPayload = methodBodyFactory.SynthesizedLocal(_payloadType, kind: SynthesizedLocalKind.InstrumentationPayload, syntax: methodBody.Syntax); // The first point indicates entry into the method and has the span of the method definition. SyntaxNode syntax = MethodDeclarationIfAvailable(methodBody.Syntax); if (!method.IsImplicitlyDeclared) { _methodEntryInstrumentation = AddAnalysisPoint(syntax, SkipAttributes(syntax), methodBodyFactory); } // Restore context methodBodyFactory.CurrentFunction = oldMethod; }
public override BoundStatement CreateBlockPrologue(BoundBlock original, out LocalSymbol synthesizedLocal) { BoundStatement previousPrologue = base.CreateBlockPrologue(original, out synthesizedLocal); if (_methodBody == original) { _dynamicAnalysisSpans = _spansBuilder.ToImmutableAndFree(); // In the future there will be multiple analysis kinds. const int analysisKind = 0; ArrayTypeSymbol modulePayloadType = ArrayTypeSymbol.CreateCSharpArray(_methodBodyFactory.Compilation.Assembly, TypeSymbolWithAnnotations.Create(_payloadType)); // Synthesize the initialization of the instrumentation payload array, using concurrency-safe code: // // var payload = PID.PayloadRootField[methodIndex]; // if (payload == null) // payload = Instrumentation.CreatePayload(mvid, methodIndex, fileIndexOrIndices, ref PID.PayloadRootField[methodIndex], payloadLength); BoundStatement payloadInitialization = _methodBodyFactory.Assignment( _methodBodyFactory.Local(_methodPayload), _methodBodyFactory.ArrayAccess( _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method)))); BoundExpression mvid = _methodBodyFactory.ModuleVersionId(); BoundExpression methodToken = _methodBodyFactory.MethodDefIndex(_method); BoundExpression payloadSlot = _methodBodyFactory.ArrayAccess( _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method))); BoundStatement createPayloadCall = GetCreatePayloadStatement( _dynamicAnalysisSpans, _methodBody.Syntax, _methodPayload, _createPayloadForMethodsSpanningSingleFile, _createPayloadForMethodsSpanningMultipleFiles, mvid, methodToken, payloadSlot, _methodBodyFactory, _debugDocumentProvider); BoundExpression payloadNullTest = _methodBodyFactory.Binary( BinaryOperatorKind.ObjectEqual, _methodBodyFactory.SpecialType(SpecialType.System_Boolean), _methodBodyFactory.Local(_methodPayload), _methodBodyFactory.Null(_payloadType)); BoundStatement payloadIf = _methodBodyFactory.If(payloadNullTest, createPayloadCall); Debug.Assert(synthesizedLocal == null); synthesizedLocal = _methodPayload; ArrayBuilder <BoundStatement> prologueStatements = ArrayBuilder <BoundStatement> .GetInstance(previousPrologue == null? 3 : 4); prologueStatements.Add(payloadInitialization); prologueStatements.Add(payloadIf); if (_methodEntryInstrumentation != null) { prologueStatements.Add(_methodEntryInstrumentation); } if (previousPrologue != null) { prologueStatements.Add(previousPrologue); } return(_methodBodyFactory.StatementList(prologueStatements.ToImmutableAndFree())); } return(previousPrologue); }
internal static void AddDelegateMembers( SourceMemberContainerTypeSymbol delegateType, ArrayBuilder <Symbol> symbols, DelegateDeclarationSyntax syntax, DiagnosticBag diagnostics) { var compilation = delegateType.DeclaringCompilation; Binder binder = delegateType.GetBinder(syntax.ParameterList); RefKind refKind = syntax.ReturnType.GetRefKind(); TypeSyntax returnTypeSyntax = syntax.ReturnType; var returnType = binder.BindType(returnTypeSyntax, diagnostics); // reuse types to avoid reporting duplicate errors if missing: var voidType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); // https://github.com/dotnet/roslyn/issues/30079: Should the 'object', IAsyncResult and AsyncCallback parameters be considered nullable or not nullable? var objectType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Object, diagnostics, syntax)); var intPtrType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Int, diagnostics, syntax)); if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.TypeSymbol); } // A delegate has the following members: (see CLI spec 13.6) // (1) a method named Invoke with the specified signature var invoke = new InvokeMethod(delegateType, refKind, returnType, syntax, binder, diagnostics); invoke.CheckDelegateVarianceSafety(diagnostics); symbols.Add(invoke); // (2) a constructor with argument types (object, System.IntPtr) symbols.Add(new Constructor(delegateType, voidType, objectType, intPtrType, syntax)); if (binder.Compilation.GetSpecialType(SpecialType.System_IAsyncResult).TypeKind != TypeKind.Error && binder.Compilation.GetSpecialType(SpecialType.System_AsyncCallback).TypeKind != TypeKind.Error && // WinRT delegates don't have Begin/EndInvoke methods !delegateType.IsCompilationOutputWinMdObj()) { var iAsyncResultType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_IAsyncResult, diagnostics, syntax)); var asyncCallbackType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_AsyncCallback, diagnostics, syntax)); // (3) BeginInvoke symbols.Add(new BeginInvokeMethod(invoke, iAsyncResultType, objectType, asyncCallbackType, syntax)); // and (4) EndInvoke methods symbols.Add(new EndInvokeMethod(invoke, iAsyncResultType, syntax)); } if (delegateType.DeclaredAccessibility <= Accessibility.Private) { return; } HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (!delegateType.IsNoMoreVisibleThan(invoke.ReturnType, ref useSiteDiagnostics)) { // Inconsistent accessibility: return type '{1}' is less accessible than delegate '{0}' diagnostics.Add(ErrorCode.ERR_BadVisDelegateReturn, delegateType.Locations[0], delegateType, invoke.ReturnType.TypeSymbol); } foreach (var parameter in invoke.Parameters) { if (!parameter.Type.IsAtLeastAsVisibleAs(delegateType, ref useSiteDiagnostics)) { // Inconsistent accessibility: parameter type '{1}' is less accessible than delegate '{0}' diagnostics.Add(ErrorCode.ERR_BadVisDelegateParam, delegateType.Locations[0], delegateType, parameter.Type.TypeSymbol); } } diagnostics.Add(delegateType.Locations[0], useSiteDiagnostics); }
/// <remarks> /// These won't be returned by GetAttributes on source methods, but they /// will be returned by GetAttributes on metadata symbols. /// </remarks> internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder <SynthesizedAttributeData> attributes) { base.AddSynthesizedAttributes(moduleBuilder, ref attributes); CSharpCompilation compilation = this.DeclaringCompilation; if (this.ContainsExtensionMethods) { // No need to check if [Extension] attribute was explicitly set since // we'll issue CS1112 error in those cases and won't generate IL. AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor)); } if (this.IsRefLikeType) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsByRefLikeAttribute(this)); var obsoleteData = ObsoleteAttributeData; Debug.Assert(obsoleteData != ObsoleteAttributeData.Uninitialized, "getting synthesized attributes before attributes are decoded"); // If user specified an Obsolete attribute, we cannot emit ours. // NB: we do not check the kind of deprecation. // we will not emit Obsolete even if Deprecated or Experimental was used. // we do not want to get into a scenario where different kinds of deprecation are combined together. // if (obsoleteData == null && !this.IsRestrictedType(ignoreSpanLikeTypes: true)) { AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_ObsoleteAttribute__ctor, ImmutableArray.Create( new TypedConstant(compilation.GetSpecialType(SpecialType.System_String), TypedConstantKind.Primitive, PEModule.ByRefLikeMarker), // message new TypedConstant(compilation.GetSpecialType(SpecialType.System_Boolean), TypedConstantKind.Primitive, true)), // error=true isOptionalUse: true)); } } if (this.IsReadOnly) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } if (this.Indexers.Any()) { string defaultMemberName = this.Indexers.First().MetadataName; // UNDONE: IndexerNameAttribute var defaultMemberNameConstant = new TypedConstant(compilation.GetSpecialType(SpecialType.System_String), TypedConstantKind.Primitive, defaultMemberName); AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute( WellKnownMember.core_runtime_DefaultMemberAttribute__ctor, ImmutableArray.Create(defaultMemberNameConstant))); } NamedTypeSymbol baseType = this.BaseTypeNoUseSiteDiagnostics; if ((object)baseType != null) { if (baseType.ContainsTupleNames()) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(baseType)); } if (baseType.NeedsNullableAttribute()) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttribute(this, TypeSymbolWithAnnotations.Create(baseType))); } } }
/// <summary> /// Returns the better type amongst the two, with some possible modifications (dynamic/object or tuple names). /// </summary> private static TypeSymbol Better( TypeSymbol type1, TypeSymbol type2, ConversionsBase conversions, out bool hadNullabilityMismatch, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { hadNullabilityMismatch = false; // Anything is better than an error sym. if (type1.IsErrorType()) { return(type2); } if ((object)type2 == null || type2.IsErrorType()) { return(type1); } var conversionsWithoutNullability = conversions.WithNullability(false); var t1tot2 = conversionsWithoutNullability.ClassifyImplicitConversionFromType(type1, type2, ref useSiteDiagnostics).Exists; var t2tot1 = conversionsWithoutNullability.ClassifyImplicitConversionFromType(type2, type1, ref useSiteDiagnostics).Exists; if (t1tot2 && t2tot1) { if (type1.IsDynamic()) { return(type1); } if (type2.IsDynamic()) { return(type2); } if (type1.Equals(type2, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)) { return(MethodTypeInferrer.Merge( TypeSymbolWithAnnotations.Create(type1), TypeSymbolWithAnnotations.Create(type2), VarianceKind.Out, conversions, out hadNullabilityMismatch).TypeSymbol); } return(null); } if (t1tot2) { return(type2); } if (t2tot1) { return(type1); } return(null); }
internal AnonymousTypeTemplateSymbol(AnonymousTypeManager manager, AnonymousTypeDescriptor typeDescr) { this.Manager = manager; this.TypeDescriptorKey = typeDescr.Key; _smallestLocation = typeDescr.Location; // Will be set when the type's metadata is ready to be emitted, // <anonymous-type>.Name will throw exception if requested // before that moment. _nameAndIndex = null; int fieldsCount = typeDescr.Fields.Length; // members Symbol[] members = new Symbol[fieldsCount * 3 + 1]; int memberIndex = 0; // The array storing property symbols to be used in // generation of constructor and other methods if (fieldsCount > 0) { AnonymousTypePropertySymbol[] propertiesArray = new AnonymousTypePropertySymbol[fieldsCount]; TypeParameterSymbol[] typeParametersArray = new TypeParameterSymbol[fieldsCount]; // Process fields for (int fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex++) { AnonymousTypeField field = typeDescr.Fields[fieldIndex]; // Add a type parameter AnonymousTypeParameterSymbol typeParameter = new AnonymousTypeParameterSymbol(this, fieldIndex, GeneratedNames.MakeAnonymousTypeParameterName(field.Name)); typeParametersArray[fieldIndex] = typeParameter; // Add a property AnonymousTypePropertySymbol property = new AnonymousTypePropertySymbol(this, field, TypeSymbolWithAnnotations.Create(typeParameter)); propertiesArray[fieldIndex] = property; // Property related symbols members[memberIndex++] = property; members[memberIndex++] = property.BackingField; members[memberIndex++] = property.GetMethod; } _typeParameters = typeParametersArray.AsImmutable(); this.Properties = propertiesArray.AsImmutable(); } else { _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; this.Properties = ImmutableArray <AnonymousTypePropertySymbol> .Empty; } // Add a constructor members[memberIndex++] = new AnonymousTypeConstructorSymbol(this, this.Properties); _members = members.AsImmutable(); Debug.Assert(memberIndex == _members.Length); // fill nameToSymbols map foreach (var symbol in _members) { _nameToSymbols.Add(symbol.Name, symbol); } // special members: Equals, GetHashCode, ToString MethodSymbol[] specialMembers = new MethodSymbol[3]; specialMembers[0] = new AnonymousTypeEqualsMethodSymbol(this); specialMembers[1] = new AnonymousTypeGetHashCodeMethodSymbol(this); specialMembers[2] = new AnonymousTypeToStringMethodSymbol(this); this.SpecialMembers = specialMembers.AsImmutable(); }
/// <summary> /// Determine whether there is any substitution of type parameters that will /// make two types identical. /// </summary> /// <param name="t1">LHS</param> /// <param name="t2">RHS</param> /// <param name="substitution"> /// Substitutions performed so far (or null for none). /// Keys are type parameters, values are types (possibly type parameters). /// Will be updated with new substitutions by the callee. /// Should be ignored when false is returned. /// </param> /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns> /// <remarks> /// Derived from Dev10's BSYMMGR::UnifyTypes. /// Two types will not unify if they have different custom modifiers. /// </remarks> private static bool CanUnifyHelper(TypeSymbolWithAnnotations t1, TypeSymbolWithAnnotations t2, ref MutableTypeMap substitution) { if (t1.IsNull || t2.IsNull) { return(t1.IsSameAs(t2)); } if (TypeSymbol.Equals(t1.TypeSymbol, t2.TypeSymbol, TypeCompareKind.ConsiderEverything2) && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers)) { return(true); } if (substitution != null) { t1 = t1.SubstituteType(substitution); t2 = t2.SubstituteType(substitution); } // If one of the types is a type parameter, then the substitution could make them equal. if (TypeSymbol.Equals(t1.TypeSymbol, t2.TypeSymbol, TypeCompareKind.ConsiderEverything2) && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers)) { return(true); } // We can avoid a lot of redundant checks if we ensure that we only have to check // for type parameters on the LHS if (!t1.TypeSymbol.IsTypeParameter() && t2.TypeSymbol.IsTypeParameter()) { TypeSymbolWithAnnotations tmp = t1; t1 = t2; t2 = tmp; } // If t1 is not a type parameter, then neither is t2 Debug.Assert(t1.TypeSymbol.IsTypeParameter() || !t2.TypeSymbol.IsTypeParameter()); switch (t1.Kind) { case SymbolKind.ArrayType: { if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1.TypeSymbol; ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2.TypeSymbol; return(CanUnifyHelper(at1.ElementType, at2.ElementType, ref substitution)); } case SymbolKind.PointerType: { if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } PointerTypeSymbol pt1 = (PointerTypeSymbol)t1.TypeSymbol; PointerTypeSymbol pt2 = (PointerTypeSymbol)t2.TypeSymbol; return(CanUnifyHelper(pt1.PointedAtType, pt2.PointedAtType, ref substitution)); } case SymbolKind.NamedType: case SymbolKind.ErrorType: { if (t2.TypeKind != t1.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } NamedTypeSymbol nt1 = (NamedTypeSymbol)t1.TypeSymbol; NamedTypeSymbol nt2 = (NamedTypeSymbol)t2.TypeSymbol; if (nt1.IsTupleType) { if (!nt2.IsTupleType) { return(false); } return(CanUnifyHelper(nt1.TupleUnderlyingType, nt2.TupleUnderlyingType, ref substitution)); } if (!nt1.IsGenericType) { return(!nt2.IsGenericType && TypeSymbol.Equals(nt1, nt2, TypeCompareKind.ConsiderEverything2)); } else if (!nt2.IsGenericType) { return(false); } int arity = nt1.Arity; if (nt2.Arity != arity || !TypeSymbol.Equals(nt2.OriginalDefinition, nt1.OriginalDefinition, TypeCompareKind.ConsiderEverything2)) { return(false); } var nt1Arguments = nt1.TypeArgumentsNoUseSiteDiagnostics; var nt2Arguments = nt2.TypeArgumentsNoUseSiteDiagnostics; for (int i = 0; i < arity; i++) { if (!CanUnifyHelper(nt1Arguments[i], nt2Arguments[i], ref substitution)) { return(false); } } // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types // TODO: Calling CanUnifyHelper for the containing type is an overkill, we simply need to go through type arguments for all containers. return((object)nt1.ContainingType == null || CanUnifyHelper(nt1.ContainingType, nt2.ContainingType, ref substitution)); } case SymbolKind.TypeParameter: { // These substitutions are not allowed in C# if (t2.TypeKind == TypeKind.Pointer || t2.SpecialType == SpecialType.System_Void) { return(false); } TypeParameterSymbol tp1 = (TypeParameterSymbol)t1.TypeSymbol; // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above if (Contains(t2.TypeSymbol, tp1)) { return(false); } if (t1.CustomModifiers.IsDefaultOrEmpty) { AddSubstitution(ref substitution, tp1, t2); return(true); } if (t1.CustomModifiers.SequenceEqual(t2.CustomModifiers)) { AddSubstitution(ref substitution, tp1, TypeSymbolWithAnnotations.Create(t2.TypeSymbol)); return(true); } if (t1.CustomModifiers.Length < t2.CustomModifiers.Length && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers.Take(t1.CustomModifiers.Length))) { AddSubstitution(ref substitution, tp1, TypeSymbolWithAnnotations.Create(t2.TypeSymbol, customModifiers: ImmutableArray.Create(t2.CustomModifiers, t1.CustomModifiers.Length, t2.CustomModifiers.Length - t1.CustomModifiers.Length))); return(true); } if (t2.TypeSymbol.IsTypeParameter()) { var tp2 = (TypeParameterSymbol)t2.TypeSymbol; if (t2.CustomModifiers.IsDefaultOrEmpty) { AddSubstitution(ref substitution, tp2, t1); return(true); } if (t2.CustomModifiers.Length < t1.CustomModifiers.Length && t2.CustomModifiers.SequenceEqual(t1.CustomModifiers.Take(t2.CustomModifiers.Length))) { AddSubstitution(ref substitution, tp2, TypeSymbolWithAnnotations.Create(t1.TypeSymbol, customModifiers: ImmutableArray.Create(t1.CustomModifiers, t2.CustomModifiers.Length, t1.CustomModifiers.Length - t2.CustomModifiers.Length))); return(true); } } return(false); } default: { return(false); } } }
private static TypeSymbolWithAnnotations CreateType(TypeSymbol type, ImmutableArray <ModifierInfo <TypeSymbol> > customModifiers) { // NonNullTypesContext is unset because the actual context will // be set when these types are transformed by the caller. return(TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, type, customModifiers: CSharpCustomModifier.Convert(customModifiers))); }
/// <summary> /// For cases where the RHS of a deconstruction-declaration is a tuple literal, we merge type information from both the LHS and RHS. /// For cases where the RHS of a deconstruction-assignment is a tuple literal, the type information from the LHS determines the merged type, since all variables have a type. /// Returns null if a merged tuple type could not be fabricated. /// </summary> private static TypeSymbol MakeMergedTupleType(ArrayBuilder <DeconstructionVariable> lhsVariables, BoundTupleLiteral rhsLiteral, CSharpSyntaxNode syntax, CSharpCompilation compilation, DiagnosticBag diagnostics) { int leftLength = lhsVariables.Count; int rightLength = rhsLiteral.Arguments.Length; var typesBuilder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(leftLength); var locationsBuilder = ArrayBuilder <Location> .GetInstance(leftLength); for (int i = 0; i < rightLength; i++) { BoundExpression element = rhsLiteral.Arguments[i]; TypeSymbol mergedType = element.Type; if (i < leftLength) { var variable = lhsVariables[i]; if (variable.HasNestedVariables) { if (element.Kind == BoundKind.TupleLiteral) { // (variables) on the left and (elements) on the right mergedType = MakeMergedTupleType(variable.NestedVariables, (BoundTupleLiteral)element, syntax, compilation, diagnostics); } else if ((object)mergedType == null) { // (variables) on the left and null on the right Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax); } } else { if ((object)variable.Single.Type != null) { // typed-variable on the left mergedType = variable.Single.Type; } } } else { if ((object)mergedType == null) { // a typeless element on the right, matching no variable on the left Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax); } } typesBuilder.Add(TypeSymbolWithAnnotations.Create(mergedType)); locationsBuilder.Add(element.Syntax.Location); } if (typesBuilder.Any(t => !t.HasType)) { typesBuilder.Free(); locationsBuilder.Free(); return(null); } // The tuple created here is not identical to the one created by // DeconstructionVariablesAsTuple. It represents a smaller // tree of types used for figuring out natural types in tuple literal. return(TupleTypeSymbol.Create( locationOpt: null, elementTypes: typesBuilder.ToImmutableAndFree(), elementLocations: locationsBuilder.ToImmutableAndFree(), elementNames: default(ImmutableArray <string>), compilation: compilation, diagnostics: diagnostics, shouldCheckConstraints: true, includeNullability: false, errorPositions: default(ImmutableArray <bool>), syntax: syntax)); }
/// <summary> /// Generate a thread-safe accessor for a regular field-like event. /// /// DelegateType tmp0 = _event; //backing field /// DelegateType tmp1; /// DelegateType tmp2; /// do { /// tmp1 = tmp0; /// tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -= /// tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1); /// } while ((object)tmp0 != (object)tmp1); /// /// Note, if System.Threading.Interlocked.CompareExchange<T> is not available, /// we emit the following code and mark the method Synchronized (unless it is a struct). /// /// _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -= /// /// </summary> internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics) { CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode; TypeSymbol delegateType = eventSymbol.Type.TypeSymbol; MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod; ParameterSymbol thisParameter = accessor.ThisParameter; TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean); SpecialMember updateMethodId = isAddMethod ? SpecialMember.System_Delegate__Combine : SpecialMember.System_Delegate__Remove; MethodSymbol updateMethod = (MethodSymbol)compilation.GetSpecialTypeMember(updateMethodId); BoundStatement @return = new BoundReturnStatement(syntax, refKind: RefKind.None, expressionOpt: null) { WasCompilerGenerated = true }; if (updateMethod == null) { MemberDescriptor memberDescriptor = SpecialMembers.GetDescriptor(updateMethodId); diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, memberDescriptor.DeclaringTypeMetadataName, memberDescriptor.Name), syntax.Location)); return(BoundBlock.SynthesizedNoLocals(syntax, @return)); } Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax); BoundThisReference fieldReceiver = eventSymbol.IsStatic ? null : new BoundThisReference(syntax, thisParameter.Type.TypeSymbol) { WasCompilerGenerated = true }; BoundFieldAccess boundBackingField = new BoundFieldAccess(syntax, receiver: fieldReceiver, fieldSymbol: eventSymbol.AssociatedField, constantValueOpt: null) { WasCompilerGenerated = true }; BoundParameter boundParameter = new BoundParameter(syntax, parameterSymbol: accessor.Parameters[0]) { WasCompilerGenerated = true }; BoundExpression delegateUpdate; MethodSymbol compareExchangeMethod = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_Interlocked__CompareExchange_T); if ((object)compareExchangeMethod == null) { // (DelegateType)Delegate.Combine(_event, value) delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax, operand: BoundCall.Synthesized(syntax, receiverOpt: null, method: updateMethod, arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundParameter)), conversion: Conversion.ExplicitReference, type: delegateType); // _event = (DelegateType)Delegate.Combine(_event, value); BoundStatement eventUpdate = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundBackingField, right: delegateUpdate, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; return(BoundBlock.SynthesizedNoLocals(syntax, statements: ImmutableArray.Create <BoundStatement>( eventUpdate, @return))); } compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create <TypeSymbol>(delegateType)); Binder.ReportUseSiteDiagnostics(compareExchangeMethod, diagnostics, syntax); GeneratedLabelSymbol loopLabel = new GeneratedLabelSymbol("loop"); const int numTemps = 3; LocalSymbol[] tmps = new LocalSymbol[numTemps]; BoundLocal[] boundTmps = new BoundLocal[numTemps]; for (int i = 0; i < numTemps; i++) { tmps[i] = new SynthesizedLocal(accessor, TypeSymbolWithAnnotations.Create(delegateType), SynthesizedLocalKind.LoweringTemp); boundTmps[i] = new BoundLocal(syntax, tmps[i], null, delegateType); } // tmp0 = _event; BoundStatement tmp0Init = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[0], right: boundBackingField, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // LOOP: BoundStatement loopStart = new BoundLabelStatement(syntax, label: loopLabel) { WasCompilerGenerated = true }; // tmp1 = tmp0; BoundStatement tmp1Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[1], right: boundTmps[0], type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // (DelegateType)Delegate.Combine(tmp1, value) delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax, operand: BoundCall.Synthesized(syntax, receiverOpt: null, method: updateMethod, arguments: ImmutableArray.Create <BoundExpression>(boundTmps[1], boundParameter)), conversion: Conversion.ExplicitReference, type: delegateType); // tmp2 = (DelegateType)Delegate.Combine(tmp1, value); BoundStatement tmp2Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[2], right: delegateUpdate, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1) BoundExpression compareExchange = BoundCall.Synthesized(syntax, receiverOpt: null, method: compareExchangeMethod, arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundTmps[2], boundTmps[1])); // tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1); BoundStatement tmp0Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[0], right: compareExchange, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // tmp0 == tmp1 // i.e. exit when they are equal, jump to start otherwise BoundExpression loopExitCondition = new BoundBinaryOperator(syntax, operatorKind: BinaryOperatorKind.ObjectEqual, left: boundTmps[0], right: boundTmps[1], constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: boolType) { WasCompilerGenerated = true }; // branchfalse (tmp0 == tmp1) LOOP BoundStatement loopEnd = new BoundConditionalGoto(syntax, condition: loopExitCondition, jumpIfTrue: false, label: loopLabel) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, locals: tmps.AsImmutable(), statements: ImmutableArray.Create <BoundStatement>( tmp0Init, loopStart, tmp1Update, tmp2Update, tmp0Update, loopEnd, @return)) { WasCompilerGenerated = true }); }
/// <summary> /// Resolves <see cref="System.Type"/> to a <see cref="TypeSymbol"/> available in this assembly /// its referenced assemblies. /// </summary> /// <param name="type">The type to resolve.</param> /// <param name="includeReferences">Use referenced assemblies for resolution.</param> /// <returns>The resolved symbol if successful or null on failure.</returns> internal TypeSymbol GetTypeByReflectionType(Type type, bool includeReferences) { System.Reflection.TypeInfo typeInfo = type.GetTypeInfo(); Debug.Assert(!typeInfo.IsByRef); // not supported (we don't accept open types as submission results nor host types): Debug.Assert(!typeInfo.ContainsGenericParameters); if (typeInfo.IsArray) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } int rank = typeInfo.GetArrayRank(); if (rank != 1) { throw new NotSupportedException($"An array of rank {rank} is not supported in stark via reflection"); } return(ArrayTypeSymbol.CreateArray(this, TypeSymbolWithAnnotations.Create(symbol))); } else if (typeInfo.IsPointer) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } return(new PointerTypeSymbol(TypeSymbolWithAnnotations.Create(symbol))); } else if (typeInfo.DeclaringType != null) { Debug.Assert(!typeInfo.IsArray); // consolidated generic arguments (includes arguments of all declaring types): Type[] genericArguments = typeInfo.GenericTypeArguments; int typeArgumentIndex = 0; var currentTypeInfo = typeInfo.IsGenericType ? typeInfo.GetGenericTypeDefinition().GetTypeInfo() : typeInfo; var nestedTypes = ArrayBuilder <System.Reflection.TypeInfo> .GetInstance(); while (true) { Debug.Assert(currentTypeInfo.IsGenericTypeDefinition || !currentTypeInfo.IsGenericType); nestedTypes.Add(currentTypeInfo); if (currentTypeInfo.DeclaringType == null) { break; } currentTypeInfo = currentTypeInfo.DeclaringType.GetTypeInfo(); } int i = nestedTypes.Count - 1; var symbol = (NamedTypeSymbol)GetTypeByReflectionType(nestedTypes[i].AsType(), includeReferences); if ((object)symbol == null) { return(null); } while (--i >= 0) { int forcedArity = nestedTypes[i].GenericTypeParameters.Length - nestedTypes[i + 1].GenericTypeParameters.Length; MetadataTypeName mdName = MetadataTypeName.FromTypeName(nestedTypes[i].Name, forcedArity: forcedArity); symbol = symbol.LookupMetadataType(ref mdName); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); if ((object)symbol == null) { return(null); } } nestedTypes.Free(); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } else { AssemblyIdentity assemblyId = AssemblyIdentity.FromAssemblyDefinition(typeInfo.Assembly); MetadataTypeName mdName = MetadataTypeName.FromNamespaceAndTypeName( typeInfo.Namespace ?? string.Empty, typeInfo.Name, forcedArity: typeInfo.GenericTypeArguments.Length); NamedTypeSymbol symbol = GetTopLevelTypeByMetadataName(ref mdName, assemblyId, includeReferences, isWellKnownType: false, conflicts: out var _); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } int typeArgumentIndex = 0; Type[] genericArguments = typeInfo.GenericTypeArguments; symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } }
/// <summary> /// Given a type <paramref name="type"/>, which is either dynamic type OR is a constructed type with dynamic type present in it's type argument tree, /// returns a synthesized DynamicAttribute with encoded dynamic transforms array. /// </summary> /// <remarks>This method is port of AttrBind::CompileDynamicAttr from the native C# compiler.</remarks> internal SynthesizedAttributeData SynthesizeDynamicAttribute(TypeSymbol type, int customModifiersCount, RefKind refKindOpt = RefKind.None) { Debug.Assert((object)type != null); Debug.Assert(type.ContainsDynamic()); if (type.IsDynamic() && refKindOpt == RefKind.None && customModifiersCount == 0) { return(TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctor)); } else { NamedTypeSymbol booleanType = GetSpecialType(SpecialType.System_Boolean); Debug.Assert((object)booleanType != null); var transformFlags = DynamicTransformsEncoder.Encode(type, refKindOpt, customModifiersCount, booleanType); var boolArray = ArrayTypeSymbol.CreateSZArray(booleanType.ContainingAssembly, TypeSymbolWithAnnotations.Create(booleanType)); var arguments = ImmutableArray.Create <TypedConstant>(new TypedConstant(boolArray, transformFlags)); return(TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctorTransformFlags, arguments)); } }
private ImmutableArray <TypeSymbolWithAnnotations> GetDeclaredConstraintTypes() { if (_lazyDeclaredConstraintTypes.IsDefault) { ImmutableArray <TypeSymbolWithAnnotations> declaredConstraintTypes; PEMethodSymbol containingMethod = null; PENamedTypeSymbol containingType; if (_containingSymbol.Kind == SymbolKind.Method) { containingMethod = (PEMethodSymbol)_containingSymbol; containingType = (PENamedTypeSymbol)containingMethod.ContainingSymbol; } else { containingType = (PENamedTypeSymbol)_containingSymbol; } var moduleSymbol = containingType.ContainingPEModule; var metadataReader = moduleSymbol.Module.MetadataReader; GenericParameterConstraintHandleCollection constraints; try { constraints = metadataReader.GetGenericParameter(_handle).GetConstraints(); } catch (BadImageFormatException) { constraints = default(GenericParameterConstraintHandleCollection); Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } bool hasUnmanagedModreqPattern = false; if (constraints.Count > 0) { var symbolsBuilder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(); MetadataDecoder tokenDecoder; if ((object)containingMethod != null) { tokenDecoder = new MetadataDecoder(moduleSymbol, containingMethod); } else { tokenDecoder = new MetadataDecoder(moduleSymbol, containingType); } foreach (var constraintHandle in constraints) { var constraint = metadataReader.GetGenericParameterConstraint(constraintHandle); var typeSymbol = tokenDecoder.DecodeGenericParameterConstraint(constraint.Type, out bool hasUnmanagedModreq); if (typeSymbol.SpecialType == SpecialType.System_ValueType) { // recognize "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" if (hasUnmanagedModreq) { hasUnmanagedModreqPattern = true; } // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. if (((_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)) { continue; } } var type = TypeSymbolWithAnnotations.Create(typeSymbol); type = NullableTypeDecoder.TransformType(type, constraintHandle, moduleSymbol); // Drop 'System.Object?' constraint type. if (type.SpecialType == SpecialType.System_Object && type.NullableAnnotation.IsAnyNullable()) { continue; } type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, constraintHandle, moduleSymbol); symbolsBuilder.Add(type); } declaredConstraintTypes = symbolsBuilder.ToImmutableAndFree(); } else { declaredConstraintTypes = ImmutableArray <TypeSymbolWithAnnotations> .Empty; } // - presence of unmanaged pattern has to be matched with `valuetype` // - IsUnmanagedAttribute is allowed iif there is an unmanaged pattern if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || hasUnmanagedModreqPattern != moduleSymbol.Module.HasIsUnmanagedAttribute(_handle)) { // we do not recognize these combinations as "unmanaged" hasUnmanagedModreqPattern = false; Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState(); ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes); } return(_lazyDeclaredConstraintTypes); }
internal SynthesizedAttributeData SynthesizeTupleNamesAttribute(TypeSymbol type) { Debug.Assert((object)type != null); Debug.Assert(type.ContainsTuple()); var stringType = GetSpecialType(SpecialType.System_String); Debug.Assert((object)stringType != null); var names = TupleNamesEncoder.Encode(type, stringType); Debug.Assert(!names.IsDefault, "should not need the attribute when no tuple names"); var stringArray = ArrayTypeSymbol.CreateSZArray(stringType.ContainingAssembly, TypeSymbolWithAnnotations.Create(stringType)); var args = ImmutableArray.Create(new TypedConstant(stringArray, names)); return(TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames, args)); }
public override BoundNode VisitTryStatement(BoundTryStatement node) { var tryStatementSyntax = node.Syntax; // If you add a syntax kind to the assertion below, please also ensure // that the scenario has been tested with Edit-and-Continue. Debug.Assert( tryStatementSyntax.IsKind(SyntaxKind.TryStatement) || tryStatementSyntax.IsKind(SyntaxKind.UsingStatement) || tryStatementSyntax.IsKind(SyntaxKind.ForEachStatement) || tryStatementSyntax.IsKind(SyntaxKind.ForEachVariableStatement)); BoundStatement finalizedRegion; BoundBlock rewrittenFinally; var finallyContainsAwaits = _analysis.FinallyContainsAwaits(node); if (!finallyContainsAwaits) { finalizedRegion = RewriteFinalizedRegion(node); rewrittenFinally = (BoundBlock)this.Visit(node.FinallyBlockOpt); if (rewrittenFinally == null) { return(finalizedRegion); } var asTry = finalizedRegion as BoundTryStatement; if (asTry != null) { // since finalized region is a try we can just attach finally to it Debug.Assert(asTry.FinallyBlockOpt == null); return(asTry.Update(asTry.TryBlock, asTry.CatchBlocks, rewrittenFinally, asTry.PreferFaultHandler)); } else { // wrap finalizedRegion into a Try with a finally. return(_F.Try((BoundBlock)finalizedRegion, ImmutableArray <BoundCatchBlock> .Empty, rewrittenFinally)); } } // rewrite finalized region (try and catches) in the current frame var frame = PushFrame(node); finalizedRegion = RewriteFinalizedRegion(node); rewrittenFinally = (BoundBlock)this.VisitBlock(node.FinallyBlockOpt); PopFrame(); var exceptionType = _F.SpecialType(SpecialType.System_Object); var pendingExceptionLocal = new SynthesizedLocal(_F.CurrentFunction, TypeSymbolWithAnnotations.Create(exceptionType), SynthesizedLocalKind.TryAwaitPendingException, tryStatementSyntax); var finallyLabel = _F.GenerateLabel("finallyLabel"); var pendingBranchVar = new SynthesizedLocal(_F.CurrentFunction, TypeSymbolWithAnnotations.Create(_F.SpecialType(SpecialType.System_Int32)), SynthesizedLocalKind.TryAwaitPendingBranch, tryStatementSyntax); var catchAll = _F.Catch(_F.Local(pendingExceptionLocal), _F.Block()); var catchAndPendException = _F.Try( _F.Block( finalizedRegion, _F.HiddenSequencePoint(), _F.Goto(finallyLabel), PendBranches(frame, pendingBranchVar, finallyLabel)), ImmutableArray.Create(catchAll)); var syntheticFinally = _F.Block( _F.HiddenSequencePoint(), _F.Label(finallyLabel), rewrittenFinally, _F.HiddenSequencePoint(), UnpendException(pendingExceptionLocal), UnpendBranches( frame, pendingBranchVar, pendingExceptionLocal)); var locals = ArrayBuilder <LocalSymbol> .GetInstance(); var statements = ArrayBuilder <BoundStatement> .GetInstance(); statements.Add(_F.HiddenSequencePoint()); locals.Add(pendingExceptionLocal); statements.Add(_F.Assignment(_F.Local(pendingExceptionLocal), _F.Default(pendingExceptionLocal.Type.TypeSymbol))); locals.Add(pendingBranchVar); statements.Add(_F.Assignment(_F.Local(pendingBranchVar), _F.Default(pendingBranchVar.Type.TypeSymbol))); LocalSymbol returnLocal = frame.returnValue; if (returnLocal != null) { locals.Add(returnLocal); } statements.Add(catchAndPendException); statements.Add(syntheticFinally); var completeTry = _F.Block( locals.ToImmutableAndFree(), statements.ToImmutableAndFree()); return(completeTry); }
private static TypeSymbolWithAnnotations CreateType(TypeSymbol type, ImmutableArray <ModifierInfo <TypeSymbol> > customModifiers) { // The actual annotation will be set when these types are transformed by the caller. return(TypeSymbolWithAnnotations.Create(type, NullableAnnotation.Oblivious, CSharpCustomModifier.Convert(customModifiers))); }
internal override MethodSymbol ConstructMethod(MethodSymbol method, ImmutableArray <TypeParameterSymbol> typeParameters, ImmutableArray <TypeSymbol> typeArguments) { var methodArity = method.Arity; var methodArgumentStartIndex = typeParameters.Length - methodArity; var typeMap = new TypeMap( ImmutableArray.Create(typeParameters, 0, methodArgumentStartIndex), ImmutableArray.CreateRange(typeArguments, 0, methodArgumentStartIndex, t => TypeSymbolWithAnnotations.Create(t))); var substitutedType = typeMap.SubstituteNamedType(method.ContainingType); method = method.AsMember(substitutedType); if (methodArity > 0) { method = method.Construct(ImmutableArray.Create(typeArguments, methodArgumentStartIndex, methodArity)); } return(method); }
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); }