Beispiel #1
0
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(SingleLookupResult other)
 {
     _kind = other.Kind;
     _symbolList.Clear();
     _symbolList.Add(other.Symbol);
     _error = other.Error;
 }
Beispiel #2
0
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(SingleLookupResult other)
 {
     this.kind = other.Kind;
     this.symbolList.Clear();
     this.symbolList.Add(other.Symbol);
     this.error = other.Error;
 }
Beispiel #3
0
 internal void MergeEqual(SingleLookupResult result)
 {
     if (Kind > result.Kind)
     {
         // existing result is better
     }
     else if (result.Kind > Kind)
     {
         this.SetFrom(result);
     }
     else if ((object)result.Symbol != null)
     {
         // Same goodness. Include all symbols
         _symbolList.Add(result.Symbol);
     }
 }
Beispiel #4
0
        internal virtual void LookupConceptMethodsInSingleBinder(LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConceptSearchOptions coptions)
        {
            var conceptBuilder = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            GetConcepts(coptions, conceptBuilder, originalBinder, ref useSiteDiagnostics);
            var concepts = conceptBuilder.ToImmutableAndFree();

            foreach (var concept in concepts)
            {
                var methodBuilder = ArrayBuilder <MethodSymbol> .GetInstance();

                AddConceptMethods(concept, methodBuilder, name, arity, options, coptions);
                foreach (var method in methodBuilder.ToImmutableAndFree())
                {
                    SingleLookupResult resultOfThisMethod = originalBinder.CheckViability(method, arity, options, concept, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                    result.MergeEqual(resultOfThisMethod);
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Tries to look up symbols inside a witness type parameter.
        /// <para>
        /// This lookup checks all of the concepts this witness implements
        /// to see if any contain a viable method matching the symbol.
        /// </para>
        /// <para>
        /// This lookup approach only works for methods and properties, and
        /// returns members whose parents are type parameters.  We rely on
        /// later stages to detect this and resolve it back to a proper
        /// statement.
        /// </para>
        /// </summary>
        /// <param name="witness">
        /// The type witness into which we are looking.
        /// </param>
        /// <param name="result">
        /// The lookup result to populate.
        /// </param>
        /// <param name="name">
        /// The name of the member being looked-up.
        /// </param>
        /// <param name="arity">
        /// The arity of the member being looked up.
        /// </param>
        /// <param name="basesBeingResolved">
        /// The set of bases being resolved.
        /// </param>
        /// <param name="options">
        /// The lookup options in effect.
        /// </param>
        /// <param name="originalBinder">
        /// The top-level binder.
        /// </param>
        /// <param name="diagnose">
        /// Whether or not we are diagnosing.
        /// </param>
        /// <param name="useSiteDiagnostics">
        /// Diagnostics set at the use-site.
        /// </param>
        internal void LookupSymbolsInWitness(
            TypeParameterSymbol witness, LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(witness.IsConceptWitness);

            var concepts = witness.ProvidedConcepts;

            if (concepts.IsDefaultOrEmpty)
            {
                return;
            }
            foreach (var c in concepts)
            {
                var members = GetCandidateMembers(c, name, options, originalBinder);
                foreach (var member in members)
                {
                    switch (member.Kind)
                    {
                    case SymbolKind.Method:
                        var method = (MethodSymbol)member;
                        // Suppose our witness is W : C<A>, and this finds C<A>.M(x).
                        // We need to return that we found W.M(x), but W is a type
                        // parameter!  While we can handle this later on in binding,
                        // the main issue is changing C<A> to W, for which we use
                        // a synthesized method symbol.
                        var witnessMethod = new SynthesizedWitnessMethodSymbol(method, witness);
                        SingleLookupResult resultOfThisMethod = originalBinder.CheckViability(witnessMethod, arity, options, witness, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                        result.MergeEqual(resultOfThisMethod);
                        break;

                    case SymbolKind.Property:
                        var prop        = (PropertySymbol)member;
                        var witnessProp = new SynthesizedWitnessPropertySymbol(prop, witness);
                        SingleLookupResult resultOfThisProp = originalBinder.CheckViability(witnessProp, arity, options, witness, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                        result.MergeEqual(resultOfThisProp);
                        break;
                        // We don't allow other types to be fields of a witness
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Tries to look up symbols inside a witness type parameter.
        /// <para>
        /// This lookup checks all of the concepts this witness implements
        /// to see if any contain a viable method matching the symbol.
        /// </para>
        /// <para>
        /// This lookup approach only works for methods, and returns a
        /// method whose parent is a type parameter.  We rely on later
        /// binder stages to detect this and resolve it back to a proper
        /// statement.
        /// </para>
        /// </summary>
        /// <param name="witness">
        /// The type witness into which we are looking.
        /// </param>
        /// <param name="result">
        /// The lookup result to populate.
        /// </param>
        /// <param name="name">
        /// The name of the member being looked-up.
        /// </param>
        /// <param name="arity">
        /// The arity of the member being looked up.
        /// </param>
        /// <param name="basesBeingResolved">
        /// The set of bases being resolved.
        /// </param>
        /// <param name="options">
        /// The lookup options in effect.
        /// </param>
        /// <param name="originalBinder">
        /// The top-level binder.
        /// </param>
        /// <param name="diagnose">
        /// Whether or not we are diagnosing.
        /// </param>
        /// <param name="useSiteDiagnostics">
        /// Diagnostics set at the use-site.
        /// </param>
        internal void LookupSymbolsInWitness(
            TypeParameterSymbol witness, LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(witness.IsConceptWitness);

            // Concepts are just interfaces, so we look at every possible
            // interface this witness has been constrained to implement.
            foreach (var iface in witness.AllEffectiveInterfacesNoUseSiteDiagnostics)
            {
                if (!iface.IsConcept)
                {
                    continue;
                }

                // We're assuming that the above handles inheritance for us.
                // This may be a mistake.
                var members = GetCandidateMembers(iface, name, options, originalBinder);
                foreach (var member in members)
                {
                    // Don't bother trying to resolve non-methods:
                    // concepts can't have them, and we only have shims for
                    // dealing with methods later on anyway.
                    if (member.Kind != SymbolKind.Method)
                    {
                        continue;
                    }
                    var method = member as MethodSymbol;
                    Debug.Assert(method != null);

                    // Suppose our witness is W : C<A>, and this finds C<A>.M(x).
                    // We need to return that we found W.M(x), but W is a type
                    // parameter!  While we can handle this later on in binding,
                    // the main issue is changing C<A> to W, for which we use
                    // a synthesized method symbol.
                    var witnessMethod = new SynthesizedWitnessMethodSymbol(method, witness);
                    SingleLookupResult resultOfThisMember = originalBinder.CheckViability(witnessMethod, arity, options, witness, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                    result.MergeEqual(resultOfThisMember);
                }
            }
        }
Beispiel #7
0
        private static void MergeReducedAndFilteredMethodGroupSymbol(
            ArrayBuilder<MethodSymbol> methods,
            ArrayBuilder<MethodSymbol> filteredMethods,
            SingleLookupResult singleResult,
            ImmutableArray<TypeSymbol> typeArguments,
            TypeSymbol receiverType,
            ref LookupResultKind resultKind)
        {
            Debug.Assert(singleResult.Kind != LookupResultKind.Empty);
            Debug.Assert((object)singleResult.Symbol != null);
            Debug.Assert(singleResult.Symbol.Kind == SymbolKind.Method);

            var singleKind = singleResult.Kind;
            if (resultKind > singleKind)
            {
                return;
            }
            else if (resultKind < singleKind)
            {
                methods.Clear();
                filteredMethods.Clear();
                resultKind = LookupResultKind.Empty;
            }

            var method = (MethodSymbol)singleResult.Symbol;
            if (AddReducedAndFilteredMethodGroupSymbol(methods, filteredMethods, method, typeArguments, receiverType))
            {
                Debug.Assert(methods.Count > 0);
                if (resultKind < singleKind)
                {
                    resultKind = singleKind;
                }
            }

            Debug.Assert((methods.Count == 0) == (resultKind == LookupResultKind.Empty));
            Debug.Assert(methods.Count == filteredMethods.Count);
        }
Beispiel #8
0
 internal void MergeEqual(SingleLookupResult result)
 {
     if (Kind > result.Kind)
     {
         // existing result is better
     }
     else if (result.Kind > Kind)
     {
         this.SetFrom(result);
     }
     else if ((object)result.Symbol != null)
     {
         // Same goodness. Include all symbols
         _symbolList.Add(result.Symbol);
     }
 }
Beispiel #9
0
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(SingleLookupResult other)
 {
     _kind = other.Kind;
     _symbolList.Clear();
     _symbolList.Add(other.Symbol);
     _error = other.Error;
 }
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(SingleLookupResult other)
 {
     this.kind = other.Kind;
     this.symbolList.Clear();
     this.symbolList.Add(other.Symbol);
     this.error = other.Error;
 }
Beispiel #11
0
        private Binder XSLookupSymbolsInternal(
            LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);
            Debug.Assert(options.AreValid());

            // X# looks for functions first
            //if (Compilation.Options.HasRuntime)
            {
                // check for function calls method calls outside the current class
                bool check = (options.HasFlag(LookupOptions.MustNotBeInstance) && !options.HasFlag(LookupOptions.MustNotBeMethod));
                if (check)
                {
                    var funcOptions = options;
                    funcOptions |= LookupOptions.MustBeInvocableIfMember;
                    Binder scope = this;
                    while (scope != null)
                    {
                        if (scope is InContainerBinder && scope.ContainingType == null) // at the namespace level, so outside of all types
                        {
                            scope.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, funcOptions, this, diagnose, ref useSiteDiagnostics);
                            FilterResults(result, options);
                            if (!result.IsClear)
                            {
                                break;
                            }
                        }
                        scope = scope.Next;
                    }
                }
            }
            LookupResult functionResults = LookupResult.GetInstance();

            if (!result.IsClear)
            {
                foreach (var symbol in result.Symbols)
                {
                    if (symbol is MethodSymbol)
                    {
                        var ms = symbol as MethodSymbol;
                        if (ms.IsStatic && ms.ContainingType.Name.EndsWith("Functions", XSharpString.Comparison))
                        {
                            SingleLookupResult single = new SingleLookupResult(LookupResultKind.Viable, ms, null);
                            functionResults.MergeEqual(single);
                        }
                    }
                }
                result.Clear();
            }
            Binder binder = null;

            for (var scope = this; scope != null && !result.IsMultiViable; scope = scope.Next)
            {
                if (binder != null)
                {
                    var tmp = LookupResult.GetInstance();
                    scope.LookupSymbolsInSingleBinder(tmp, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics);
                    FilterResults(tmp, options);
                    result.MergeEqual(tmp);
                    tmp.Free();
                }
                else
                {
                    scope.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics);
                    FilterResults(result, options);
                    if (!result.IsClear)
                    {
                        binder = scope;
                    }
                }
            }
            if (!functionResults.IsClear)
            {
                // compare the function results with the overall results found
                // create a list of functions and methods
                // function first and then the methods
                LookupResult mergedResults = LookupResult.GetInstance();
                mergedResults.MergeEqual(functionResults);
                // now add the symbols from result that do not exist
                for (int j = 0; j < result.Symbols.Count; j++)
                {
                    var sym   = result.Symbols[j];
                    var found = false;
                    for (int i = 0; i < mergedResults.Symbols.Count; i++)
                    {
                        if (sym == mergedResults.Symbols[i])
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        SingleLookupResult single = new SingleLookupResult(LookupResultKind.Viable, sym, null);
                        mergedResults.MergeEqual(single);
                    }
                }
                result.Clear();
                result.MergeEqual(mergedResults);
            }
            // C563 Make sure the error is generated for Inaccessible types.
            if (!result.IsClear && result.Kind == LookupResultKind.Inaccessible && result.Error != null)
            {
                // we only want to add this for internal fields (globals)
                if (result.Symbols[0].Kind == SymbolKind.Field)
                {
                    if (useSiteDiagnostics == null)
                    {
                        useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                    }
                    useSiteDiagnostics.Add(result.Error);
                }
            }
            return(binder);
        }