-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IDE0001: False Positive for default primary constructor #75026
Comments
I'll try fixing this :) |
Awesome. Thanks! |
This one turned out more complicated than I expected. The issue is with the following code:
Where the generic parameter From what I have seen this case should be taken into account (according to the comments here) however, in the end, the binder that is used is one that contains an I am still not 100% sure about some of the details as well as not knowing which part of the code needs to be changed (guessing it's the binder lookup). @CyrusNajmabadi any chance you (or anyone else) might be able to provide some insight? |
I don't have a suggestion for you. It sounds like a binding issue in teh compiler. You might want to talk to @dotnet/roslyn-compiler to see if htey ahve any ideas. If you make a small repro test that demonstrates the problem when calling into the compiler apis, they may be amenable to fixing it. |
I'm not sure what you mean by "Where the generic parameter E inside the base list is getting incorrectly bound even though members of D are not accessible in this context." This isn't happening from what I can tell. As an example, this test passes: [Fact]
public void QuickTest()
{
var source = """
public abstract class C<T>;
public sealed class D() : C<E>()
{
public class E;
}
""";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (3,29): error CS0246: The type or namespace name 'E' could not be found (are you missing a using directive or an assembly reference?)
// public sealed class D() : C<E>()
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "E").WithArguments("E").WithLocation(3, 29)
);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var classD = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Skip(1).First();
var cBaseList = classD.BaseList.Types[0].Type;
var eArg = ((GenericNameSyntax)cBaseList).TypeArgumentList.Arguments[0];
var e = model.GetSymbolInfo(eArg).Symbol;
Assert.Null(e);
} Could you please clarify what you're seeing? If you're calling |
Is this problem really specific to primary constructors? |
Yes:
Only the PrimaryToBasePrimary creats the IDE0001 suggestion. |
This btw doesn't affect default-primaries only, but all primaries, i.e.:
also has the IDE0001 annotation, but can only be worked around by discarding the primary constructor altogether. |
It is not obvious why IDE is getting confused. If it gets an unexpected result from Compiler's API, we (Compiler team) need more details:
|
The issue can be reproduced with this test: [Fact]
public void Test()
{
var source = """
public abstract class C<T>;
public sealed class D() : C<D.E>() // Starting with working code
{
public class E;
}
""";
var comp = CSharpTestBase.CreateCompilation(source);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var classD = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Skip(1).First();
var cBaseList = classD.BaseList!.Types[0].Type;
var deArg = ((GenericNameSyntax)cBaseList).TypeArgumentList.Arguments[0];
var ceArg = SyntaxFactory.GenericName(SyntaxFactory.Identifier("C"), SyntaxFactory.TypeArgumentList([SyntaxFactory.IdentifierName("E")]));
var simplified = SyntaxFactory.PrimaryConstructorBaseType(ceArg);
model.TryGetSpeculativeSemanticModel(deArg.SpanStart, simplified, out var speculativeModel); // Replace C<D.E>() with C<E>()
var eArg = ((GenericNameSyntax)simplified.Type).TypeArgumentList.Arguments[0];
var e = speculativeModel!.GetSymbolInfo(eArg).Symbol;
Assert.Null(e); // throws, e is D.E here
} I am not 100% sure but I'm assuming that the speculative semantic model is on the IDE side of things, so perhaps there are no issues with |
The used overload of
Or whatever mechanism is used when argument list is not present. |
Thanks for the in depth explanation, now I understand 🙂 |
Version used:
dotnet --info
Steps to Reproduce:
Class, with default constructor:
Record class, with argument:
Diagnostic Id:
IDE0001: Simplify Name
Expected Behavior: No false-positive, just like this does not produce a false-positive:
Actual Behavior: IDE0001 false-positive is emitted for
: Base<Concrete.Impl>()
, where it shouldn't.The text was updated successfully, but these errors were encountered: