public sealed override ImmutableArray <Symbol> GetMembers() { // Not making this lazy results in new symbols being created every // time we call GetMembers(), which is not only inefficient but // breaks reference equality. if (_members.IsDefault) { var mb = ArrayBuilder <Symbol> .GetInstance(); mb.AddRange(base.GetMembers()); // This is slightly wrong, but we don't have any syntax to // cling onto apart from this... var binder = DeclaringCompilation.GetBinder(_parent.GetNonNullSyntaxNode()); var diagnostics = DiagnosticBag.GetInstance(); MakeMembers(mb, binder, diagnostics); AddDeclarationDiagnostics(diagnostics); ImmutableInterlocked.InterlockedInitialize(ref _members, mb.ToImmutableAndFree()); } return(_members); }
public override ImmutableArray <Symbol> GetMembers() { // @t-mawind // Not making this lazy results in new symbols being created every // time we call GetMembers(), which is not only inefficient but // breaks reference equality. if (_members.IsDefault) { var mb = ArrayBuilder <Symbol> .GetInstance(); mb.AddRange(base.GetMembers()); // @t-mawind // This is slightly wrong, but we don't have any syntax to // cling onto apart from this... var binder = DeclaringCompilation.GetBinder(ContainingType.GetNonNullSyntaxNode()); var diagnostics = DiagnosticBag.GetInstance(); var memberSyntax = _concept.GetConceptDefaultMethods(); foreach (var m in memberSyntax) { var ms = m.GetSyntax() as MethodDeclarationSyntax; if (ms == null) { continue; } mb.Add(SourceMemberMethodSymbol.CreateMethodSymbol(this, binder, ms, diagnostics)); } AddDeclarationDiagnostics(diagnostics); ImmutableInterlocked.InterlockedInitialize(ref _members, mb.ToImmutableAndFree()); } return(_members); }
protected override BoundExpression GenerateCall(SyntheticBoundNodeFactory f, BoundExpression receiver, ImmutableArray <BoundExpression> arguments, ImmutableArray <RefKind> refKinds, DiagnosticBag diagnostics) { // For user-defined operators, the normal shim call approach works // fine. However, we also want to permit shim calls into types // with builtin operators, for which we need to do an actual // lookup as to which operator we're defining, and a quick // jump into part of the operator overload resolution code to see // if we're actually in one of those types. // // This may be incomplete, but is probably(??) sound. // TODO(@MattWindsor91): consider refkinds? if (ImplementingMethod.OriginalDefinition is SourceUserDefinedOperatorSymbol op) { Debug.Assert(receiver.Kind == BoundKind.TypeExpression, "receiver of an operator should always be a type"); var rectype = (BoundTypeExpression)receiver; var opdecl = op.GetSyntax(); Debug.Assert(opdecl != null, "should have operator syntax here"); var opsyn = opdecl.OperatorToken; var opkind = opsyn.Kind(); var binder = DeclaringCompilation.GetBinder(ImplementingMethod.GetNonNullSyntaxNode()).WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.InShim, this); var ovr = new OverloadResolution(binder); var ignore = new HashSet <DiagnosticInfo>(); if (arguments.Length == 1) { (var usuccess, var ukind) = TryGetUnaryOperatorKind(opsyn.Kind()); if (usuccess) { var result = UnaryOperatorOverloadResolutionResult.GetInstance(); ovr.UnaryOperatorOverloadResolution(ukind, arguments[0], result, ref ignore); if (result.SingleValid()) { var bsig = result.Best.Signature; if (bsig.Method == null) { return(f.Unary(bsig.Kind, bsig.ReturnType, arguments[0])); } } } } else if (arguments.Length == 2) { (var bsuccess, var bkind) = TryGetBinaryOperatorKind(opsyn.Kind()); if (bsuccess) { var result = BinaryOperatorOverloadResolutionResult.GetInstance(); ovr.BinaryOperatorOverloadResolution(bkind, arguments[0], arguments[1], result, ref ignore); if (result.SingleValid()) { var bsig = result.Best.Signature; if (bsig.Method == null) { return(f.Binary(bsig.Kind, bsig.ReturnType, arguments[0], arguments[1])); } } } } } return(base.GenerateCall(f, receiver, arguments, refKinds, diagnostics)); }