Skip to content

C#: a constant local with a non-literal initial value is emitted as const, which fails to compile with CS0133 #110

Description

@matt-edmondson

What's wrong

CSharpGenerator (Coder/Languages/CSharpGenerator.cs ~line 894) writes const for every VariableDeclaration with IsConstant whose type isn't var, whatever its InitialValue is. C# only allows compile-time constants in a const local, so an expression, a parameter reference or a call produces code that doesn't compile.

Other generators get this right:

  • The README describes a constant as one "with a literal InitialValue".
  • Go already checks the initial value: GoGenerator.IsCompileTimeValue (~line 1318) falls back to var with a note.
  • C++, Rust, JS and C are unaffected, because their immutable bindings accept runtime values.

Repro

var f = new FunctionDeclaration("Twice") { ReturnType = "int", IsStatic = true };
f.Parameters.Add(new Parameter("n", "int"));
f.Body.Add(new VariableDeclaration("doubled", "int",
    new BinaryExpression(new VariableReference("n"), BinaryOperator.Multiply, Literal.Number(2))) { IsConstant = true });
var call = new CallExpression("Math.Abs"); call.Arguments.Add(new VariableReference("doubled"));
f.Body.Add(new VariableDeclaration("size", "int", call) { IsConstant = true });
f.Body.Add(new ReturnStatement(new VariableReference("size")));
// placed inside a ClassDeclaration("Sample") and generated with CSharpGenerator
  • Actual: const int doubled = (n * 2); and const int size = Math.Abs(doubled);. dotnet build reports error CS0133: The expression being assigned to 'doubled' must be constant, and the same for size.
  • Expected: int doubled = (n * 2); and int size = Math.Abs(doubled);. C# has no readonly locals, which is also how the generator already handles an inferred (var) constant.

Suggested fix

Write const only when the initial value is a compile-time value. Moving Go's IsCompileTimeValue into LanguageGeneratorBase would let both generators share the same rule. Add a test that compiles the output with a non-literal constant.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions