You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Type parameters named await, file, required, scoped or extension break the imposter #369
A type parameter named await, file, required, scoped or extension makes the generated imposter fail to compile. This holds for a target's type parameter and for a method's, and for interface and class targets alike:
public file x; reads as the file modifier (CS1519, CS9056)
required
C# 11
about 360
public required x; reads as the required modifier (CS1519, CS9029)
scoped
C# 11
44 (92 at C# 14)
CS9062 "Types and aliases cannot be named 'scoped'", CS9048 (scoped x) =>
extension
C# 14
2,076
public extension x; reads as an extension block (CS9281)
The C# 15 preview keywords fail the same way with the Roslyn 5.9 compiler: closed (170 errors) and union (1,145).
The other contextual keywords compile, 38 of them probed (async, dynamic, field, value, when, with, nameof, global, ...). So do var, _, record and partial, which #319 renames.
Cause
Generated code writes a type parameter's name bare. #109 escapes the reserved keywords, and #319 renames var, _, record and partial. These names are contextual keywords that generated code places where they read as a modifier, an extension block or an async lambda's await.
Proposed fix
Add them to the names TypeParameterNames.NameInGeneratedCode renames (NamesGeneratedCodeCantUse), the way #319 handles record and partial. Users never write type parameter names in setups, so the rename is invisible. Include closed and union now, so C# 15 needs no follow-up.
Escaping (@file) would also compile. But generated code takes type names from display strings, which escape only reserved keywords, so it would need a second mechanism next to #319's.
Add a compile test per name for a target's and a method's type parameter at C# 14.
Verdict: real. Probed 49 names as a target type parameter (IKw<@name> with a method, an async method, an indexer and an event) and as a method type parameter (M<@name> sync and async), 98 compilations at LanguageVersion.Preview:
name
target type parameter
method type parameter
await
CS4003 x2
CS4003 x2
file
CS1519, CS9056, CS0106 (58)
CS1519, CS1031, CS8124 (95)
required
CS1519, CS9029, CS0106 (58)
CS1519, CS1031, CS8124 (95)
scoped
CS9062, CS9048 (14)
CS9062, CS9048 (54)
extension
CS9281 and 531 more
Roslyn itself throws Unexpected value 'Extension' of type TypeKind while binding the generated file
the other 44, incl. field, when, with, async, dynamic, nameof, global, yield, init, managed, unmanaged, notnull, nint, nuint, args, the LINQ and accessor words, allows, and/or/not, var, record, partial, value
compile
compile
So the table in the issue is right, and the method-level extension shape is worse than an error count: the output is malformed enough that the compiler's own binder crashes on it. closed and union compile here because the test compiler is not 5.9; I cannot confirm those two rows.
Better fix than a list
NamesGeneratedCodeCantUse is a per-release list, and this issue is its second extension in two days (#319 added four names, this adds five plus two previews). Replace the list with the compiler's own knowledge:
It is future-proof: SyntaxFacts binds at run time to the compiler that is running the generator, so closed and union are covered exactly when the compiler treats them as keywords, with no follow-up release.
It is a superset of today's list (var, record, partial are contextual keywords; _ is not, hence the explicit case) and of the five names here.
The extra renames (field, value, when, from, select, ...) are invisible to users, who pass type arguments positionally, and the probe shows they compile either way, so there is no behavioural cost; snapshot identity will show whether any existing test target uses such a name.
If the list is kept instead, add _ and the C# 15 names as the issue says, but note the test matrix: file/required/scoped only fail from C# 11 and extension from C# 14, so the compile tests must run at C# 14 (Roslyn 4.14 and 5.0 in the matrix), as the issue already states.
Tests
One row per name at both levels, including the async method shape for await (the sync shape compiles). The 44 compiling names are a cheap negative control for the SyntaxFacts route: pick two or three (field, select) to pin that renaming them does no harm.
Activity
themidnightgospel commentedon Oct 13, 2026
Audit on master f4f09b8
Verdict: real. Probed 49 names as a target type parameter (
IKw<@name>with a method, an async method, an indexer and an event) and as a method type parameter (M<@name>sync and async), 98 compilations atLanguageVersion.Preview:awaitfilerequiredscopedextensionUnexpected value 'Extension' of type TypeKindwhile binding the generated filefield,when,with,async,dynamic,nameof,global,yield,init,managed,unmanaged,notnull,nint,nuint,args, the LINQ and accessor words,allows,and/or/not,var,record,partial,valueSo the table in the issue is right, and the method-level
extensionshape is worse than an error count: the output is malformed enough that the compiler's own binder crashes on it.closedandunioncompile here because the test compiler is not 5.9; I cannot confirm those two rows.Better fix than a list
NamesGeneratedCodeCantUseis a per-release list, and this issue is its second extension in two days (#319 added four names, this adds five plus two previews). Replace the list with the compiler's own knowledge:SyntaxFactsbinds at run time to the compiler that is running the generator, soclosedandunionare covered exactly when the compiler treats them as keywords, with no follow-up release.var,record,partialare contextual keywords;_is not, hence the explicit case) and of the five names here.field,value,when,from,select, ...) are invisible to users, who pass type arguments positionally, and the probe shows they compile either way, so there is no behavioural cost; snapshot identity will show whether any existing test target uses such a name.If the list is kept instead, add
_and the C# 15 names as the issue says, but note the test matrix:file/required/scopedonly fail from C# 11 andextensionfrom C# 14, so the compile tests must run at C# 14 (Roslyn 4.14 and 5.0 in the matrix), as the issue already states.Tests
One row per name at both levels, including the async method shape for
await(the sync shape compiles). The 44 compiling names are a cheap negative control for theSyntaxFactsroute: pick two or three (field,select) to pin that renaming them does no harm.Rename type parameters named like contextual keywords (themidnightgos…