Code Generation › Code Generation Quality

Michael BrenndoerferFebruary 3, 20265 min read
Language AI HandbookAll chapters
Part 47 of 67Code Generation
Chapter 360Code Generation › Code Generation Quality
Reading section 8 of 13 · Code Generation Quality · 5 minSection 8 of 13 · 5 min

Book contents

Section 8 of 13 · 5 min read

Code Generation › Code Generation QualityOne section · Sections in this chapter8 / 13 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Quality in code generation is multi-dimensional, and the dimensions that matter depend on the context. Benchmarks focus on functional correctness because it can be measured automatically. Production deployments care about security, efficiency, and style as well. This section examines the full quality picture and two specific failure modes that are easy to miss.

What Makes Generated Code "Good"?

Evaluating code generation quality requires thinking clearly about what "good" means. The dimensions are:

  • Functional correctness: Does the code compute the right answer for all valid inputs?
  • Robustness: Does it handle edge cases, invalid inputs, and boundary conditions gracefully?
  • Readability: Is the code understandable to a human reviewer?
  • Efficiency: Does it run in reasonable time and space?
  • Style consistency: Does it match the conventions of the surrounding codebase?

These dimensions can trade off against each other. A highly optimized implementation may be harder to read. A highly readable implementation may be less efficient. The right balance depends on the use case.

In benchmarking research, functional correctness is almost exclusively the focus, measured by automated test suites. This is a practical choice: functional correctness can be measured automatically at scale. The other dimensions require human judgment or more sophisticated analysis tools. But dismissing the non-correctness dimensions entirely leads to a distorted picture of code generation utility. Code that is functionally correct but unreadable, inconsistent with the codebase style, or subtly inefficient still imposes maintenance costs.

The Verbosity-Correctness Trade-off

One empirical finding in code generation research is that longer generated code is not necessarily more correct. Models sometimes generate verbose implementations with unnecessary logic, repeated computations, or defensive checks that introduce bugs while appearing thorough. A common failure mode is generating code that handles a specific case the model "worried about" but introduces an error in doing so.

Conversely, overly terse implementations sometimes omit necessary logic. The sweet spot is an implementation that matches the complexity of the problem: simple problems get simple implementations, complex problems get appropriately structured code.

This observation has implications for how we prompt code generation models. Asking for "a robust implementation" may produce verbose, error-prone code. Asking for "a concise implementation" may produce missing edge case handling. Being explicit about the trade-off ("implement this function concisely; edge cases are not needed for this use case") often produces better results.

The verbosity problem becomes more pronounced for longer functions. Research on models generating complete files or modules finds that output quality degrades as length increases, both because the model's effective attention to the specification weakens over distance and because longer generations accumulate more opportunities for individual token errors to compound into logical failures. This is one reason why function-level generation remains the most reliable setting.

Type Correctness and Static Analysis

Language models generate code character by character without maintaining a type environment or symbol table. This means they can produce code that is syntactically valid but type-incorrect, using variables of the wrong type, calling methods that do not exist on an object, or returning values of the wrong type.

Type annotations in the function signature help because they appear in the model's context and constrain the generation. If the signature declares def process(items: list[str]) -> dict[str, int]:, the model has type information to work with. Without annotations, the model must infer types from names and context alone.

Static analysis tools (mypy, pyright) can be used as part of a verification pipeline to detect type errors in generated code before execution. This is particularly valuable in codebases with strict type policies where type errors are unacceptable even if the code would run correctly without type checking.

The deeper issue is that type correctness is only the most formalized dimension of a broader consistency problem. Generated code can be semantically incorrect without any type error: it might return a value in the wrong units, use a dictionary key that was not established elsewhere in the codebase, or violate an invariant that is enforced by convention rather than by type annotations. Catching these semantic consistency failures requires either running tests that cover the specified behavior or reviewing the generated code carefully, and there is no fully automated solution.

Hallucinated API Calls and Library Usage

A failure mode specific to code generation (and largely absent from prose generation) is hallucinated API calls: the model generates syntactically plausible function calls to methods or attributes that do not exist. This happens because the model has learned the statistical patterns of library usage from training data, but its knowledge of specific API versions may be outdated or incomplete.

For example, a model might generate a call to a DataFrame method using a parameter name that was renamed in a version update, or it might generate a call to a utility function from an internal library it has seen referenced in similar contexts without having access to the actual implementation. These errors are difficult to detect from static analysis alone because the method names and parameter patterns look plausible. They typically only surface at runtime.

The practical mitigation is to provide API documentation or type stubs in the model's context for the specific libraries being used. When the model can see the actual method signatures and docstrings, hallucination rates drop substantially. Several production code generation systems build tooling to automatically inject relevant API documentation into the prompt based on the imports in the surrounding code.