示例#1
0
        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));
        }
示例#2
0
        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));
        }
示例#3
0
        /// <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());
            }
        }