/// <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; }
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); } }
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); } } }
/// <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 } } } }
/// <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); } } }
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); }
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); }