internal MethodSymbol Construct(ImmutableArray <TypeWithAnnotations> typeArguments) { if (!ReferenceEquals(this, ConstructedFrom) || this.Arity == 0) { throw new InvalidOperationException(); } if (typeArguments.IsDefault) { throw new ArgumentNullException(nameof(typeArguments)); } if (typeArguments.Any(NamedTypeSymbol.TypeWithAnnotationsIsNullFunction)) { throw new ArgumentException(CSharpResources.TypeArgumentCannotBeNull, nameof(typeArguments)); } if (typeArguments.Length != this.Arity) { throw new ArgumentException(CSharpResources.WrongNumberOfTypeArguments, nameof(typeArguments)); } if (ConstructedNamedTypeSymbol.TypeParametersMatchTypeArguments(this.TypeParameters, typeArguments)) { return(this); } return(new ConstructedMethodSymbol(this, typeArguments)); }
internal NamedTypeSymbol Construct(ImmutableArray <TypeSymbol> arguments, bool unbound) { if (!ReferenceEquals(this, ConstructedFrom) || this.Arity == 0) { throw new InvalidOperationException(); } if (arguments.IsDefault) { throw new ArgumentNullException("typeArguments"); } if (arguments.Any(NamedTypeSymbol.TypeSymbolIsNullFunction)) { throw new ArgumentException(CSharpResources.TypeArgumentCannotBeNull, "typeArguments"); } if (arguments.Length != this.Arity) { throw new ArgumentException(CSharpResources.WrongNumberOfTypeArguments, "typeArguments"); } Debug.Assert(!unbound || arguments.All(NamedTypeSymbol.TypeSymbolIsErrorType)); if (ConstructedNamedTypeSymbol.TypeParametersMatchTypeArguments(this.TypeParameters, arguments)) { return(this); } return(this.ConstructCore(arguments, unbound)); }
/// <summary> /// </summary> /// <param name="namedTypeSymbol"> /// </param> /// <param name="map"> /// </param> /// <returns> /// </returns> private static ConstructedNamedTypeSymbol ConstructGenericTypeSymbol(NamedTypeSymbol namedTypeSymbol, IDictionary<IType, IType> map) { var mapFilteredByTypeParameters = namedTypeSymbol.TypeArguments != null ? SelectGenericsFromArguments(namedTypeSymbol, map) : SelectGenericsFromParameters(namedTypeSymbol, map); if (mapFilteredByTypeParameters == null) { return null; } var newType = new ConstructedNamedTypeSymbol(namedTypeSymbol.ConstructedFrom, ImmutableArray.Create(mapFilteredByTypeParameters)); return newType; }
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) { var concept = ImplementingMethod.ContainingType; var conceptLoc = concept.Locations.IsEmpty ? Location.None : concept.Locations[0]; // TODO: wrong location? Debug.Assert(concept.IsConcept, "Tried to synthesise default struct implementation on a non-concept interface"); var instance = ContainingType; var instanceLoc = instance.Locations.IsEmpty ? Location.None : instance.Locations[0]; // TODO: wrong location? Debug.Assert(instance.IsInstance, "Tried to synthesise default struct implementation for a non-instance"); SyntheticBoundNodeFactory F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics); F.CurrentMethod = OriginalDefinition; try { // Now try to find the default struct using the instance's scope... var binder = new BinderFactory(compilationState.Compilation, instance.GetNonNullSyntaxNode().SyntaxTree).GetBinder(instance.GetNonNullSyntaxNode()); var ignore = new HashSet <DiagnosticInfo>(); var defs = concept.GetDefaultStruct(binder, false, ref ignore); if (defs == null) { diagnostics.Add(ErrorCode.ERR_ConceptMethodNotImplementedAndNoDefault, instanceLoc, instance.Name, concept.Name, ImplementingMethod.ToDisplayString()); F.CloseMethod(F.ThrowNull()); return; } // Suppose the target concept is Foo<A, B>. // Then, the default must take type parameters <A, B, FooAB>, // where FooAB : Foo<A, B>. Thus, the arity is one higher than // the concept. if (defs.Arity != concept.Arity + 1) { // Don't use the default struct's location: it is an // implementation detail and may not actually exist. diagnostics.Add(ErrorCode.ERR_DefaultStructBadArity, conceptLoc, concept.Name, defs.Arity, concept.Arity + 1); F.CloseMethod(F.ThrowNull()); return; } // Due to above, arity must be at least 1. var witnessPar = defs.TypeParameters[defs.Arity - 1]; if (!witnessPar.IsConceptWitness) { diagnostics.Add(ErrorCode.ERR_DefaultStructNoWitnessParam, conceptLoc, concept.Name); F.CloseMethod(F.ThrowNull()); return; } var newTypeArguments = GenerateDefaultTypeArguments(); Debug.Assert(newTypeArguments.Length == concept.TypeArguments.Length + 1, "Conversion from concept type parameters to default struct lost or gained some entries."); // Now make the receiver for the call. As usual, it's a default(). var recvType = new ConstructedNamedTypeSymbol(defs, newTypeArguments); var receiver = F.Default(recvType); var arguments = GenerateInnerCallArguments(F); Debug.Assert(arguments.Length == ImplementingMethod.Parameters.Length, "Conversion from parameters to arguments lost or gained some entries."); var call = F.MakeInvocationExpression(BinderFlags.None, F.Syntax, receiver, ImplementingMethod.Name, arguments, diagnostics, ImplementingMethod.TypeArguments); if (call.HasErrors) { F.CloseMethod(F.ThrowNull()); return; } // If whichever call we end up making returns void, then we // can't just return its result; instead, we have to do the // call on its own _then_ return. BoundBlock block; if (call.Type.SpecialType == SpecialType.System_Void) { block = F.Block(F.ExpressionStatement(call), F.Return()); } else { block = F.Block(F.Return(call)); } F.CloseMethod(block); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); F.CloseMethod(F.ThrowNull()); } }