Repository: dotnet/roslyn
File: src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs (C#)

Code before:
        {
            if (parameters.Length > 0 && compilation.ShouldEmitNullableAttributes(container))
            {
                foreach (var parameter in parameters)
                {
                    if (parameter.TypeWithAnnotations.NeedsNullableAttribute())
                    {
                        if (moduleBuilder is { })
                        {
                            moduleBuilder.EnsureNullableAttributeExists();
                        }
                        else
                        {
                            compilation.EnsureNullableAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation);
                        }
                    }
                }
            }
        }

        internal static void CheckUnderspecifiedGenericExtension(Symbol extensionMember, ImmutableArray<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(extensionMember.GetIsNewExtensionMember());

            NamedTypeSymbol extension = extensionMember.ContainingType;
            if (extension.ExtensionParameter is not { } extensionParameter || extension.ContainingType?.Arity != 0)
            {
                // error cases, already reported elsewhere
                return;
            }

            if (extension.Arity == 0)
            {
                return;
            }

            var usedTypeParameters = PooledHashSet<TypeParameterSymbol>.GetInstance();
            reportUnusedExtensionTypeParameters(extensionMember, parameters, diagnostics, extension, extensionParameter, usedTypeParameters);

            usedTypeParameters.Free();
            return;

            static void reportUnusedExtensionTypeParameters(Symbol extensionMember, ImmutableArray<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics, NamedTypeSymbol extension, ParameterSymbol extensionParameter, PooledHashSet<TypeParameterSymbol> usedTypeParameters)
            {
                int extensionArity = extension.Arity;
                int extensionMemberArity = extensionMember.GetMemberArity();
                Debug.Assert(extensionMemberArity == 0); // we currently only apply the check for members which may not be generic

                extensionParameter.Type.VisitType(collectTypeParameters, arg: usedTypeParameters);

                if (usedTypeParameters.Count == extensionArity && extensionMemberArity == 0)

Review comment (suggestion):
>ContainingType [](http://example.com/codeflow?start=88&length=14)

I think we should check for other places in code where we unconditionally accessing `ContainingType` on an extension type.  #Closed

Code after:
        {
            if (parameters.Length > 0 && compilation.ShouldEmitNullableAttributes(container))
            {
                foreach (var parameter in parameters)
                {
                    if (parameter.TypeWithAnnotations.NeedsNullableAttribute())
                    {
                        if (moduleBuilder is { })
                        {
                            moduleBuilder.EnsureNullableAttributeExists();
                        }
                        else
                        {
                            compilation.EnsureNullableAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation);
                        }
                    }
                }
            }
        }

        internal static void CheckUnderspecifiedGenericExtension(Symbol extensionMember, ImmutableArray<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(extensionMember.IsExtensionBlockMember());

            NamedTypeSymbol extension = extensionMember.ContainingType;
            if (extension.ExtensionParameter is not { } extensionParameter || extension.ContainingType?.Arity != 0)
            {
                // error cases, already reported elsewhere
                return;
            }

            if (extension.Arity == 0)
            {
                return;
            }

            var usedTypeParameters = PooledHashSet<TypeParameterSymbol>.GetInstance();
            reportUnusedExtensionTypeParameters(extensionMember, parameters, diagnostics, extension, extensionParameter, usedTypeParameters);

            usedTypeParameters.Free();
            return;

            static void reportUnusedExtensionTypeParameters(Symbol extensionMember, ImmutableArray<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics, NamedTypeSymbol extension, ParameterSymbol extensionParameter, PooledHashSet<TypeParameterSymbol> usedTypeParameters)
            {
                int extensionArity = extension.Arity;
                int extensionMemberArity = extensionMember.GetMemberArity();
                Debug.Assert(extensionMemberArity == 0); // we currently only apply the check for members which may not be generic

                extensionParameter.Type.VisitType(collectTypeParameters, arg: usedTypeParameters);

                if (usedTypeParameters.Count == extensionArity && extensionMemberArity == 0)