Example #1
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
                    }
                }
            }
        }
Example #2
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);
                }
            }
        }