protected override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.MustBeInvocableIfMember)) != 0) { return; } Debug.Assert(result.IsClear); var count = parameterMap.GetCountForKey(name); if (count == 1) { ParameterSymbol p; parameterMap.TryGetSingleValue(name, out p); result.MergeEqual(originalBinder.CheckViability(p, arity, options, null, diagnose, ref useSiteDiagnostics)); } else if (count > 1) { var parameters = parameterMap[name]; foreach (var sym in parameters) { result.MergeEqual(originalBinder.CheckViability(sym, arity, options, null, diagnose, ref useSiteDiagnostics)); } } }
internal static ImmutableArray<BoundInitializer> BindFieldInitializers( SourceMemberContainerTypeSymbol containingType, MethodSymbol scriptCtor, ImmutableArray<FieldInitializers> initializers, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList<Imports> firstDebugImports) { if (initializers.IsEmpty) { firstDebugImports = null; return ImmutableArray<BoundInitializer>.Empty; } CSharpCompilation compilation = containingType.DeclaringCompilation; ArrayBuilder<BoundInitializer> boundInitializers = ArrayBuilder<BoundInitializer>.GetInstance(); if ((object)scriptCtor == null) { BindRegularCSharpFieldInitializers(compilation, initializers, boundInitializers, diagnostics, generateDebugInfo, out firstDebugImports); } else { BindScriptFieldInitializers(compilation, scriptCtor, initializers, boundInitializers, diagnostics, generateDebugInfo, out firstDebugImports); } return boundInitializers.ToImmutableAndFree(); }
internal sealed override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly | LookupOptions.LabelsOnly)) != 0) { return; } var local = this.LookupPlaceholder(name); if ((object)local == null) { base.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); } else { result.MergeEqual(this.CheckViability(local, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved)); } }
/// <summary> /// Determine the effective base type, effective interface set, and set of type /// parameters (excluding cycles) from the type parameter constraints. Conflicts /// within the constraints and constraint types are returned as diagnostics. /// 'inherited' should be true if the type parameters are from an overridden /// generic method. In those cases, additional constraint checks are applied. /// </summary> public static TypeParameterBounds ResolveBounds( this TypeParameterSymbol typeParameter, AssemblySymbol corLibrary, ConsList<TypeParameterSymbol> inProgress, ImmutableArray<TypeSymbol> constraintTypes, bool inherited, CSharpCompilation currentCompilation, DiagnosticBag diagnostics) { var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var bounds = typeParameter.ResolveBounds(corLibrary, inProgress, constraintTypes, inherited, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, pair.TypeParameter.Locations[0])); } diagnosticsBuilder.Free(); return bounds; }
internal override TypeSymbol GetFieldType(ConsList<FieldSymbol> fieldsBeingBound) { if ((object)_lazyType == null) { Interlocked.CompareExchange(ref _lazyType, _containingType.TypeSubstitution.SubstituteType(_originalDefinition.GetFieldType(fieldsBeingBound)).Type, null); } return _lazyType; }
private Imports GetImports(ConsList<Symbol> basesBeingResolved) { if (_imports == null) { Interlocked.CompareExchange(ref _imports, Imports.FromSyntax(_declarationSyntax, this, basesBeingResolved, _inUsing), null); } return _imports; }
/// <summary> /// In regular C#, all field initializers are assignments to fields and the assigned expressions /// may not reference instance members. /// </summary> private static void BindRegularCSharpFieldInitializers( CSharpCompilation compilation, ImmutableArray<ImmutableArray<FieldInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList<Imports> firstDebugImports) { firstDebugImports = null; foreach (ImmutableArray<FieldInitializer> siblingInitializers in initializers) { // All sibling initializers share the same parent node and tree so we can reuse the binder // factory across siblings. Unfortunately, we cannot reuse the binder itself, because // individual fields might have their own binders (e.g. because of being declared unsafe). BinderFactory binderFactory = null; foreach (FieldInitializer initializer in siblingInitializers) { FieldSymbol fieldSymbol = initializer.Field; Debug.Assert((object)fieldSymbol != null); // A constant field of type decimal needs a field initializer, so // check if it is a metadata constant, not just a constant to exclude // decimals. Other constants do not need field initializers. if (!fieldSymbol.IsMetadataConstant) { //Can't assert that this is a regular C# compilation, because we could be in a nested type of a script class. SyntaxReference syntaxRef = initializer.Syntax; var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax(); if (binderFactory == null) { binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree); } Binder parentBinder = binderFactory.GetBinder(initializerNode); Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios if (generateDebugInfo && firstDebugImports == null) { firstDebugImports = parentBinder.ImportsList; } BoundInitializer boundInitializer = BindFieldInitializer( new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol), fieldSymbol, (EqualsValueClauseSyntax)initializerNode, diagnostics); boundInitializers.Add(boundInitializer); } } } }
/// <summary> /// Builds a string builder from a cons list /// </summary> /// <param name="s">ConsList of prefix's</param> /// <returns>A stringbuilder with spaces seperating prefixes</returns> private string BuildStringBuilder(ConsList<string> s) { StringBuilder st = new StringBuilder(); while (s != null) { st.Append(s.Head + " "); s = s.Tail; } return st.ToString(); }
/// <summary> /// Checks if 'symbol' is accessible from within type 'within', with /// an qualifier of type "throughTypeOpt". Sets "failedThroughTypeCheck" to true /// if it failed the "through type" check. /// </summary> public static bool IsSymbolAccessible( Symbol symbol, NamedTypeSymbol within, TypeSymbol throughTypeOpt, out bool failedThroughTypeCheck, ref HashSet<DiagnosticInfo> useSiteDiagnostics, ConsList<Symbol> basesBeingResolved = null) { return IsSymbolAccessibleCore(symbol, within, throughTypeOpt, out failedThroughTypeCheck, within.DeclaringCompilation, ref useSiteDiagnostics, basesBeingResolved); }
/// <remarks> /// CONSIDER: in the case of field initializers, it is possible that different parts of a method could have different /// namespace scopes (i.e. if they come from different parts of a partial type). Currently, we're following Dev10's /// approach of using the context of the (possibly synthesized) constructor into which the field initializers are /// inserted. It might be possible to give field initializers their own scopes, assuming the EE supports it. /// </remarks> public ImmutableArray<Cci.NamespaceScope> GetNamespaceScopes(ConsList<Imports> debugImports) { if (debugImports == null) { return ImmutableArray<Cci.NamespaceScope>.Empty; } else { return cache.GetOrAdd(debugImports, buildNamespaceScopes); } }
internal override Imports GetImports(ConsList<Symbol> basesBeingResolved) { Debug.Assert(_lazyImports != null || _computeImports != null, "Have neither imports nor a way to compute them."); if (_lazyImports == null) { Interlocked.CompareExchange(ref _lazyImports, _computeImports(basesBeingResolved), null); } return _lazyImports; }
private static ConsList<FieldSymbol> SubstituteFields(ConsList<FieldSymbol> fields, TypeMap typeMap) { if (!fields.Any()) { return ConsList<FieldSymbol>.Empty; } var head = SubstituteField(fields.Head, typeMap); var tail = SubstituteFields(fields.Tail, typeMap); return tail.Prepend(head); }
private bool CheckStruct(ConsList<NamedTypeSymbol> typesWithMembersOfThisType, NamedTypeSymbol nts) { // Break recursive cycles. If we find a member that contains us, it is considered empty if (!typesWithMembersOfThisType.ContainsReference(nts)) { // Remember that we're in the process of doing this type while checking members. typesWithMembersOfThisType = new ConsList<NamedTypeSymbol>(nts, typesWithMembersOfThisType); return CheckStructInstanceFields(typesWithMembersOfThisType, nts); } return true; }
internal DisplayClassVariable(string name, DisplayClassVariableKind kind, DisplayClassInstance displayClassInstance, ConsList<FieldSymbol> displayClassFields) { Debug.Assert(displayClassFields.Any()); this.Name = name; this.Kind = kind; this.DisplayClassInstance = displayClassInstance; this.DisplayClassFields = displayClassFields; // Verify all type parameters are substituted. Debug.Assert(this.ContainingSymbol.IsContainingSymbolOfAllTypeParameters(this.Type)); }
internal override void LookupSymbolsInSingleBinder(LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { _sourceBinder.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics); var symbols = result.Symbols; for (int i = 0; i < symbols.Count; i++) { // Type parameters requiring mapping to the target type and // should be found by WithMethodTypeParametersBinder instead. var parameter = (ParameterSymbol)symbols[i]; Debug.Assert(parameter.ContainingSymbol == _sourceBinder.ContainingMemberOrLambda); symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset]; } }
internal override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert(result.IsClear); if ((options & LookupOptions.NamespaceAliasesOnly) != 0) { return; } foreach (var parameterSymbol in parameterMap[name]) { result.MergeEqual(originalBinder.CheckViability(parameterSymbol, arity, options, null, diagnose, ref useSiteDiagnostics)); } }
protected override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.MustBeInvocableIfMember)) != 0) { return; } Debug.Assert(result.IsClear); foreach (ParameterSymbol parameter in parameters) { if (parameter.Name == name) { result.MergeEqual(originalBinder.CheckViability(parameter, arity, options, null, diagnose, ref useSiteDiagnostics)); } } }
internal override TypeSymbol GetFieldType(ConsList<FieldSymbol> fieldsBeingBound) { Debug.Assert(fieldsBeingBound != null); if ((object)_lazyType != null) { return _lazyType; } var typeSyntax = TypeSyntax; var compilation = this.DeclaringCompilation; var diagnostics = DiagnosticBag.GetInstance(); TypeSymbol type; var binderFactory = compilation.GetBinderFactory(SyntaxTree); var binder = binderFactory.GetBinder(typeSyntax); bool isVar; type = binder.BindType(typeSyntax, diagnostics, out isVar); Debug.Assert((object)type != null || isVar); if (isVar && !fieldsBeingBound.ContainsReference(this)) { InferFieldType(fieldsBeingBound, binder); Debug.Assert((object)_lazyType != null); } else { if (isVar) { diagnostics.Add(ErrorCode.ERR_RecursivelyTypedVariable, this.ErrorLocation, this); type = binder.CreateErrorType("var"); } SetType(compilation, diagnostics, type); } diagnostics.Free(); return _lazyType; }
internal override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { var hostObjectType = GetHostObjectType(); if (hostObjectType.Kind == SymbolKind.ErrorType) { // The name '{0}' does not exist in the current context (are you missing a reference to assembly '{1}'?) result.SetFrom(new CSDiagnosticInfo( ErrorCode.ERR_NameNotInContextPossibleMissingReference, new object[] { name, ((MissingMetadataTypeSymbol)hostObjectType).ContainingAssembly.Identity }, ImmutableArray<Symbol>.Empty, ImmutableArray<Location>.Empty )); } else { LookupMembersInternal(result, hostObjectType, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); } }
/// <summary> /// Gets the set of interfaces that this type directly implements. This set does not include /// interfaces that are base interfaces of directly implemented interfaces. /// </summary> internal sealed override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<Symbol> basesBeingResolved) { if (_lazyInterfaces.IsDefault) { if (basesBeingResolved != null && basesBeingResolved.ContainsReference(this.OriginalDefinition)) { return ImmutableArray<NamedTypeSymbol>.Empty; } var diagnostics = DiagnosticBag.GetInstance(); var acyclicInterfaces = MakeAcyclicInterfaces(basesBeingResolved, diagnostics); if (ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInterfaces, acyclicInterfaces, default(ImmutableArray<NamedTypeSymbol>)).IsDefault) { AddDeclarationDiagnostics(diagnostics); } diagnostics.Free(); } return _lazyInterfaces; }
internal override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if (!ShouldLookInUsings(options)) { return; } LookupResult tmp = LookupResult.GetInstance(); // usings: Imports.Empty.LookupSymbolInUsings(ConsolidatedUsings, originalBinder, tmp, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics); // if we found a viable result in imported namespaces, use it instead of unviable symbols found in source: if (tmp.IsMultiViable) { result.MergeEqual(tmp); } tmp.Free(); }
/// <summary> /// Determine if the given type is an empty struct type,. "typesWithMembersOfThisType" contains /// a list of types that have members (directly or indirectly) of this type. /// to remove circularity. /// </summary> private bool IsEmptyStructType(TypeSymbol type, ConsList<NamedTypeSymbol> typesWithMembersOfThisType) { var nts = type as NamedTypeSymbol; if ((object)nts == null || !IsTrackableStructType(nts)) { return false; } // Consult the cache. bool result; if (Cache.TryGetValue(nts, out result)) { return result; } result = CheckStruct(typesWithMembersOfThisType, nts); Debug.Assert(!Cache.ContainsKey(nts) || Cache[nts] == result); Cache[nts] = result; return result; }
internal sealed override void LookupSymbolsInSingleBinder( LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly | LookupOptions.LabelsOnly)) != 0) { return; } if (name.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { var valueText = name.Substring(2); ulong address; if (!ulong.TryParse(valueText, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out address)) { // Invalid value should have been caught by Lexer. throw ExceptionUtilities.UnexpectedValue(valueText); } var local = new ObjectAddressLocalSymbol(_containingMethod, name, this.Compilation.GetSpecialType(SpecialType.System_Object), address); result.MergeEqual(this.CheckViability(local, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved)); } else { LocalSymbol lowercaseReturnValueAlias; if (_lowercaseReturnValueAliases.TryGetValue(name, out lowercaseReturnValueAlias)) { result.MergeEqual(this.CheckViability(lowercaseReturnValueAlias, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved)); } else { base.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); } } }
private bool UsesIsNullable(ImmutableArray <TypeSymbolWithAnnotations> types, ConsList <TypeParameterSymbol> inProgress) { return(types.Any(t => UsesIsNullable(t, inProgress))); }
/// <summary> /// Determine if "type" inherits from or implements "baseType", ignoring constructed types, and dealing /// only with original types. /// </summary> private static bool InheritsFromOrImplementsIgnoringConstruction( this TypeSymbol type, NamedTypeSymbol baseType, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { Debug.Assert(type.IsDefinition); Debug.Assert(baseType.IsDefinition); PooledHashSet <NamedTypeSymbol> interfacesLookedAt = null; ArrayBuilder <NamedTypeSymbol> baseInterfaces = null; bool baseTypeIsInterface = baseType.IsInterface; if (baseTypeIsInterface) { interfacesLookedAt = PooledHashSet <NamedTypeSymbol> .GetInstance(); baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); } PooledHashSet <NamedTypeSymbol> visited = null; var current = type; bool result = false; while ((object)current != null) { Debug.Assert(current.IsDefinition); if (baseTypeIsInterface == current.IsInterfaceType() && current == (object)baseType) { result = true; break; } if (baseTypeIsInterface) { getBaseInterfaces(current, baseInterfaces, interfacesLookedAt, basesBeingResolved); } // NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e. // "class Goo : IBar<int>". We must map it back to the 'original' when as we walk up // the base type hierarchy. var next = current.GetNextBaseTypeNoUseSiteDiagnostics(basesBeingResolved, compilation, ref visited); if ((object)next == null) { current = null; } else { current = (TypeSymbol)next.OriginalDefinition; current.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } visited?.Free(); if (!result && baseTypeIsInterface) { Debug.Assert(!result); while (baseInterfaces.Count != 0) { NamedTypeSymbol currentBase = baseInterfaces.Pop(); if (!currentBase.IsInterface) { continue; } Debug.Assert(currentBase.IsDefinition); if (currentBase == (object)baseType) { result = true; break; } getBaseInterfaces(currentBase, baseInterfaces, interfacesLookedAt, basesBeingResolved); } if (!result) { foreach (var candidate in interfacesLookedAt) { candidate.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } } interfacesLookedAt?.Free(); baseInterfaces?.Free(); return(result);
private bool AddIfUsesIsNullable(Symbol symbol, TypeSymbolWithAnnotations type, ConsList <TypeParameterSymbol> inProgress) { if (UsesIsNullable(type, inProgress)) { Add(symbol); return(true); } return(false); }
internal override ImmutableArray <TypeWithAnnotations> GetConstraintTypes(ConsList <TypeParameterSymbol> inProgress) { return(ImmutableArray <TypeWithAnnotations> .Empty); }
internal override bool IsAccessibleHelper(Symbol symbol, TypeSymbol accessThroughType, out bool failedThroughTypeCheck, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved) { failedThroughTypeCheck = false; return(IsSymbolAccessibleConditional(symbol, Compilation.Assembly, ref useSiteDiagnostics)); }
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress) { return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetConstraintTypes(inProgress)); }
internal override NamedTypeSymbol GetDeclaredBaseType(ConsList<Symbol> basesBeingResolved) { return this.Manager.System_Object; }
internal sealed override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<Symbol> basesBeingResolved) { return _unbound ? ImmutableArray<NamedTypeSymbol>.Empty : Map.SubstituteNamedTypes(OriginalDefinition.InterfacesNoUseSiteDiagnostics(basesBeingResolved)); }
internal override ImmutableArray <NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList <Symbol> basesBeingResolved) { throw new NotImplementedException(); }
internal override TypeSymbol GetDeducedBaseType(ConsList <TypeParameterSymbol> inProgress) { return(null); }
internal override NamedTypeSymbol GetEffectiveBaseClass(ConsList <TypeParameterSymbol> inProgress) { return(null); }
internal override ImmutableArray <NamedTypeSymbol> GetInterfaces(ConsList <TypeParameterSymbol> inProgress) { return(ImmutableArray <NamedTypeSymbol> .Empty); }
/// <summary> /// Is a protected symbol inside "originalContainingType" accessible from within "within", /// which much be a named type or an assembly. /// </summary> private static bool IsProtectedSymbolAccessible( NamedTypeSymbol withinType, TypeSymbol throughTypeOpt, NamedTypeSymbol originalContainingType, out bool failedThroughTypeCheck, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { failedThroughTypeCheck = false; // It is not an error to define protected member in a sealed Script class, it's just a // warning. The member behaves like a private one - it is visible in all subsequent // submissions. if (originalContainingType.TypeKind == TypeKind.Submission) { return(true); } if ((object)withinType == null) { // If we're not within a type, we can't access a protected symbol return(false); } // A protected symbol is accessible if we're (optionally nested) inside the type that it // was defined in. // It is helpful to think about 'protected' as *increasing* the // accessibility domain of a private member, rather than *decreasing* that of a public // member. Members are naturally private; the protected, internal and public access // modifiers all increase the accessibility domain. Since private members are accessible // to nested types, so are protected members. // We do this check up front as it is very fast and easy to do. if (IsNestedWithinOriginalContainingType(withinType, originalContainingType)) { return(true); } // Protected is really confusing. Check out 3.5.3 of the language spec "protected access // for instance members" to see how it works. I actually got the code for this from // LangCompiler::CheckAccessCore { var current = withinType.OriginalDefinition; var originalThroughTypeOpt = (object)throughTypeOpt == null ? null : throughTypeOpt.OriginalDefinition as TypeSymbol; while ((object)current != null) { Debug.Assert(current.IsDefinition); if (current.InheritsFromOrImplementsIgnoringConstruction(originalContainingType, compilation, ref useSiteDiagnostics, basesBeingResolved)) { // NOTE(cyrusn): We're continually walking up the 'throughType's inheritance // chain. We could compute it up front and cache it in a set. However, we // don't want to allocate memory in this function. Also, in practice // inheritance chains should be very short. As such, it might actually be // slower to create and check inside the set versus just walking the // inheritance chain. if ((object)originalThroughTypeOpt == null || originalThroughTypeOpt.InheritsFromOrImplementsIgnoringConstruction(current, compilation, ref useSiteDiagnostics)) { return(true); } else { failedThroughTypeCheck = true; } } // NOTE(cyrusn): The container of an original type is always original. current = current.ContainingType; } } return(false); }
internal override ImmutableArray<NamedTypeSymbol> GetInterfaces(ConsList<TypeParameterSymbol> inProgress) { return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetInterfaces(inProgress)); }
static void getBaseInterfaces(TypeSymbol derived, ArrayBuilder <NamedTypeSymbol> baseInterfaces, PooledHashSet <NamedTypeSymbol> interfacesLookedAt, ConsList <TypeSymbol> basesBeingResolved) { if (basesBeingResolved != null && basesBeingResolved.ContainsReference(derived)) { return; } ImmutableArray <NamedTypeSymbol> declaredInterfaces; switch (derived) { case TypeParameterSymbol typeParameter: declaredInterfaces = typeParameter.AllEffectiveInterfacesNoUseSiteDiagnostics; break; case NamedTypeSymbol namedType: declaredInterfaces = namedType.GetDeclaredInterfaces(basesBeingResolved); break; default: declaredInterfaces = derived.InterfacesNoUseSiteDiagnostics(basesBeingResolved); break; } foreach (var @interface in declaredInterfaces) { NamedTypeSymbol definition = @interface.OriginalDefinition; if (interfacesLookedAt.Add(definition)) { baseInterfaces.Add(definition); } } }
internal override TypeSymbol GetDeducedBaseType(ConsList<TypeParameterSymbol> inProgress) { return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetDeducedBaseType(inProgress), RetargetOptions.RetargetPrimitiveTypesByTypeCode); }
/// <summary> /// Is the named type <paramref name="type"/> accessible from within <paramref name="within"/>, /// which must be a named type or an assembly. /// </summary> private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { Debug.Assert(within is NamedTypeSymbol || within is AssemblySymbol); Debug.Assert((object)type != null); var compilation = within.DeclaringCompilation; bool unused; if (!type.IsDefinition) { // All type argument must be accessible. var typeArgs = type.TypeArgumentsWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics); foreach (var typeArg in typeArgs) { // type parameters are always accessible, so don't check those (so common it's // worth optimizing this). if (typeArg.Type.Kind != SymbolKind.TypeParameter && !IsSymbolAccessibleCore(typeArg.Type, within, null, out unused, compilation, ref useSiteDiagnostics, basesBeingResolved)) { return(false); } } } var containingType = type.ContainingType; return((object)containingType == null ? IsNonNestedTypeAccessible(type.ContainingAssembly, type.DeclaredAccessibility, within) : IsMemberAccessible(containingType, type.DeclaredAccessibility, within, null, out unused, compilation, ref useSiteDiagnostics, basesBeingResolved)); }
private static bool IsNonPublicMemberAccessible( NamedTypeSymbol containingType, // the symbol's containing type Accessibility declaredAccessibility, Symbol within, TypeSymbol throughTypeOpt, out bool failedThroughTypeCheck, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { failedThroughTypeCheck = false; var originalContainingType = containingType.OriginalDefinition; var withinType = within as NamedTypeSymbol; var withinAssembly = (object)withinType != null ? withinType.ContainingAssembly : (AssemblySymbol)within; switch (declaredAccessibility) { case Accessibility.NotApplicable: return(true); case Accessibility.Private: // All expressions in the current submission (top-level or nested in a method or // type) can access previous submission's private top-level members. Previous // submissions are treated like outer classes for the current submission - the // inner class can access private members of the outer class. if (containingType.TypeKind == TypeKind.Submission) { return(true); } // private members never accessible from outside a type. return((object)withinType != null && IsPrivateSymbolAccessible(withinType, originalContainingType)); case Accessibility.Internal: // An internal type is accessible if we're in the same assembly or we have // friend access to the assembly it was defined in. return(withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly)); case Accessibility.ProtectedAndInternal: if (!withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly)) { // We require internal access. If we don't have it, then this symbol is // definitely not accessible to us. return(false); } // We had internal access. Also have to make sure we have protected access. return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case Accessibility.ProtectedOrInternal: if (withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly)) { // If we have internal access to this symbol, then that's sufficient. no // need to do the complicated protected case. return(true); } // We don't have internal access. But if we have protected access then that's // sufficient. return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case Accessibility.Protected: return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); default: throw ExceptionUtilities.UnexpectedValue(declaredAccessibility); } }
/// <summary> /// Checks if 'symbol' is accessible from within 'within', which must be a NamedTypeSymbol /// or an AssemblySymbol. /// </summary> /// <remarks> /// Note that NamedTypeSymbol, if available, is the type that is associated with the binder /// that found the 'symbol', not the inner-most type that contains the access to the /// 'symbol'. /// <para> /// If 'symbol' is accessed off of an expression then 'throughTypeOpt' is the type of that /// expression. This is needed to properly do protected access checks. Sets /// "failedThroughTypeCheck" to true if this protected check failed. /// </para> /// <para> /// This function is expected to be called a lot. As such, it avoids memory /// allocations in the function itself (including not making any iterators). This means /// that certain helper functions that could otherwise be called are inlined in this method to /// prevent the overhead of returning collections or enumerators. /// </para> /// </remarks> private static bool IsSymbolAccessibleCore( Symbol symbol, Symbol within, // must be assembly or named type symbol TypeSymbol throughTypeOpt, out bool failedThroughTypeCheck, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { Debug.Assert((object)symbol != null); Debug.Assert((object)within != null); Debug.Assert(within.IsDefinition); Debug.Assert(within is NamedTypeSymbol || within is AssemblySymbol); failedThroughTypeCheck = false; switch (symbol.Kind) { case SymbolKind.ArrayType: return(IsSymbolAccessibleCore(((ArrayTypeSymbol)symbol).ElementType, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case SymbolKind.PointerType: return(IsSymbolAccessibleCore(((PointerTypeSymbol)symbol).PointedAtType, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case SymbolKind.NamedType: return(IsNamedTypeAccessible((NamedTypeSymbol)symbol, within, ref useSiteDiagnostics, basesBeingResolved)); case SymbolKind.Alias: return(IsSymbolAccessibleCore(((AliasSymbol)symbol).Target, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case SymbolKind.Discard: return(IsSymbolAccessibleCore(((DiscardSymbol)symbol).TypeWithAnnotations.Type, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved)); case SymbolKind.ErrorType: // Always assume that error types are accessible. return(true); case SymbolKind.TypeParameter: case SymbolKind.Parameter: case SymbolKind.Local: case SymbolKind.Label: case SymbolKind.Namespace: case SymbolKind.DynamicType: case SymbolKind.Assembly: case SymbolKind.NetModule: case SymbolKind.RangeVariable: // These types of symbols are always accessible (if visible). return(true); case SymbolKind.Method: case SymbolKind.Property: case SymbolKind.Event: case SymbolKind.Field: if (!symbol.RequiresInstanceReceiver()) { // static members aren't accessed "through" an "instance" of any type. So we // null out the "through" instance here. This ensures that we'll understand // accessing protected statics properly. throughTypeOpt = null; } return(IsMemberAccessible(symbol.ContainingType, symbol.DeclaredAccessibility, within, throughTypeOpt, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics)); default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } }
internal override ImmutableArray <NamedTypeSymbol> GetDeclaredInterfaces(ConsList <Symbol> basesBeingResolved) { throw new NotImplementedException(); }
/// <summary> /// Check the parameters of a method or property, but report that method/property rather than /// the parameter itself. /// </summary> private bool AddIfUsesIsNullable(Symbol symbol, ImmutableArray <ParameterSymbol> parameters, ConsList <TypeParameterSymbol> inProgress) { foreach (var parameter in parameters) { if (UsesIsNullable(parameter.Type, inProgress)) { Add(symbol); return(true); } } return(false); }
internal override Imports GetImports(ConsList <TypeSymbol> basesBeingResolved) { return(Imports.Empty); }
internal override NamedTypeSymbol GetEffectiveBaseClass(ConsList<TypeParameterSymbol> inProgress) { return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetEffectiveBaseClass(inProgress), RetargetOptions.RetargetPrimitiveTypesByTypeCode); }
internal override TypeSymbol GetFieldType(ConsList<FieldSymbol> fieldsBeingBound) { return this.type; }
private bool AddIfUsesIsNullable(Symbol symbol, ImmutableArray <NamedTypeSymbol> types, ConsList <TypeParameterSymbol> inProgress) { foreach (var type in types) { if (UsesIsNullable(type, inProgress)) { Add(symbol); return(true); } } return(false); }
internal abstract override TypeSymbolWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound);
internal override NamedTypeSymbol GetDeclaredBaseType(ConsList <Symbol> basesBeingResolved) { return(GetDeclaredBases(basesBeingResolved).Item1); }
internal override NamedTypeSymbol GetDeclaredBaseType(ConsList <TypeSymbol> basesBeingResolved) { return(_baseType); }
internal override NamedTypeSymbol GetDeclaredBaseType(ConsList <Symbol> basesBeingResolved) { throw new NotImplementedException(); }
internal sealed override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList<Symbol> basesBeingResolved) { return _unbound ? ImmutableArray<NamedTypeSymbol>.Empty : Map.SubstituteNamedTypes(OriginalDefinition.GetDeclaredInterfaces(basesBeingResolved)); }
internal override ImmutableArray <NamedTypeSymbol> GetDeclaredInterfaces(ConsList <TypeSymbol> basesBeingResolved) { throw ExceptionUtilities.Unreachable; }
internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<Symbol> basesBeingResolved) { return ImmutableArray<NamedTypeSymbol>.Empty; }
internal override ImmutableArray <NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList <TypeSymbol> basesBeingResolved) { throw ExceptionUtilities.Unreachable; }
internal override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList<Symbol> basesBeingResolved) { return ImmutableArray<NamedTypeSymbol>.Empty; }
internal override TypeSymbol GetFieldType(ConsList <FieldSymbol> fieldsBeingBound) { return(this.RetargetingTranslator.Retarget(_underlyingField.GetFieldType(fieldsBeingBound), RetargetOptions.RetargetPrimitiveTypesByTypeCode)); }
internal override bool IsAccessible(Symbol symbol, TypeSymbol accessThroughType, out bool failedThroughTypeCheck, ref HashSet<DiagnosticInfo> useSiteDiagnostics, ConsList<Symbol> basesBeingResolved = null) { failedThroughTypeCheck = false; return this.IsSymbolAccessibleConditional(symbol, Compilation.Assembly, ref useSiteDiagnostics); }
internal Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > GetDeclaredBases(ConsList <Symbol> basesBeingResolved) { if (ReferenceEquals(_lazyDeclaredBases, null)) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); if (Interlocked.CompareExchange(ref _lazyDeclaredBases, MakeDeclaredBases(basesBeingResolved, diagnostics), null) == null) { AddDeclarationDiagnostics(diagnostics); } diagnostics.Free(); } return(_lazyDeclaredBases); }