From cbcd5eb69e3c4b9783e2f379eeff59109961a5ca Mon Sep 17 00:00:00 2001 From: Idan Ben Dror Date: Tue, 7 Jul 2026 10:15:21 +0300 Subject: [PATCH] Fix NullReferenceException in hover for generic methods returning a TypeVar GetReturnDocumentation calls GetSpecificReturnType with a null argument set; for a TypeVar return this reaches CreateSpecificReturnFromTypeVar and calls CreateInstance(null). For the list/dict/tuple specializations CreateInstance dereferences the null argument set and throws. Guard CreateInstance against a null argument set by returning a plain instance; the call-resolution path (non-null args) is unchanged. --- .../Ast/Impl/Types/PythonClassType.cs | 3 +++ src/LanguageServer/Test/HoverTests.cs | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/Analysis/Ast/Impl/Types/PythonClassType.cs b/src/Analysis/Ast/Impl/Types/PythonClassType.cs index 3ba89e2a0..84cd2eba9 100644 --- a/src/Analysis/Ast/Impl/Types/PythonClassType.cs +++ b/src/Analysis/Ast/Impl/Types/PythonClassType.cs @@ -143,6 +143,9 @@ public override string Documentation { // Constructor call public override IMember CreateInstance(IArgumentSet args) { + if (args == null) { + return new PythonInstance(this); + } var builtins = DeclaringModule.Interpreter.ModuleResolution.BuiltinsModule; // Specializations switch (Name) { diff --git a/src/LanguageServer/Test/HoverTests.cs b/src/LanguageServer/Test/HoverTests.cs index 9377e5cc0..8178d8277 100644 --- a/src/LanguageServer/Test/HoverTests.cs +++ b/src/LanguageServer/Test/HoverTests.cs @@ -316,5 +316,32 @@ private static void AssertHover(HoverSource hs, IDocumentAnalysis analysis, Sour hover.range.Should().Be((Range)span.Value); } } + + [TestMethod, Priority(0)] + public async Task GenericMethodReturningTypeVar() { + // Building hover documentation for a generic method whose return type is a + // TypeVar (here resolved to a collection type) must not throw. + const string code = @" +from typing import Generic, Type, TypeVar + +T = TypeVar('T') + +class Container(Generic[T]): + def __init__(self, schema: Type[T]) -> None: + self.schema = schema + + def get(self) -> T: ... + +c = Container(schema=dict) +c.get() +"; + var analysis = await GetAnalysisAsync(code); + var hs = new HoverSource(new PlainTextDocumentationSource()); + + var hover = hs.GetHover(analysis, new SourceLocation(13, 4)); + + hover.Should().NotBeNull(); + hover.contents.value.Should().Contain("get"); + } } }