Commit Graph
11 Commits
Author SHA1 Message Date
Chandler Carruth d0badecd2a Switch tests to use the rendered form of diagnostics (#8070)
Historically, we disabled the rendered form in tests outside of
`toolchain/diagnostics`. The idea was to keep tests shorter and avoid
very long chains of autoupdate before stabilizing due to all the line
numbers and other artifacts in the rendered form.

This PR adds `--diagnostic-line-numbers=[all|first]` and defaults to
`first` in tests. This keeps the rendered form so that we can easily
code review that form and the visual cues it does or doesn't provide.
But it removes all but the first location's line numbers to provide
significantly more stability in tests.

By default, tests get the full unicode line-drawing form of diagnostics
so we can ensure all of the artifacts there make sense with the specific
case being diagnosed, but we do retain some focused ASCII-rendering
tests to ensure that fallback remains usable.

There are some issues here that will be fixed in subsequent PRs.
Notably, we try to keep the frame together in the check lines, and so
force some parts to use the first location. This largely works, but
fails in some edge cases, causing the entire frame to be located
incorrectly. There is a TODO about this that we need to fix, and it only
occurs 6 times across the test suite, so it didn't seem worth
front-loading a fix for here.

Assisted-by: Claude Code
2026-11-05 07:19:59 +00:00
Richard Smith d87891f3a6 Fix diagnostic style issues (#7982)
Remove trailing `.`s and leading capitalization from diagnostics, and
separate clauses with `;` rather than `.`, per
https://docs.carbon-lang.dev/toolchain/docs/diagnostics.html#diagnostic-message-style-guide
2026-10-15 20:15:28 +00:00
Chandler Carruth 2c9739799b Render diagnostics through the terminal library (#7683)
Diagnostic rendering was part of the data model: `Loc::FormatLocation`
and
`Loc::FormatSnippet` wrote plain text to a stream, so no capability,
color, or
terminal width could reach them.

A diagnostic is now one message with labels, contexts, and location
information
attached, and `Diagnostics::Renderer` draws it into a
`Terminal::Buffer`. The
design is in `toolchain/docs/diagnostics_rendering.md` (#7668),
authoring in
`toolchain/docs/diagnostics.md`.

Before:

```
example.carbon:6:3: error: 1 argument passed to function expecting 0 arguments
  Run0(1);
  ^~~~~~~
example.carbon:3:1: note: calling function declared here
fn Run0() {}
^~~~~~~~~~~
```

After:

```
error: 1 argument passed to function expecting 0 arguments
       ╭─┤ example.carbon:6:3
       ┆
     3 │ fn Run0() {}
       · ─────┬─────
       ·      ╰──┤ calling function declared here
       ┆
->   6 │   Run0(1);
       ·   ───────
       ╰────────────
```

`--no-diagnostic-snippets` gives a compact form, `example.carbon:6:3-9`.
File
tests use it; the rendering tests under `toolchain/diagnostics/testdata`
ask for
snippets.

C++ interop diagnostics are data now rather than text Clang drew:
`SemIR::ClangSourceLocId` names a `clang::SourceRange`, and a Clang
location is
marked as the point it names.

`StreamConsumer` moves to a `:renderer` target that `:emitter` does not
depend
on, keeping `common/terminal` out of `consumer.h`. Capabilities come
from the
file behind the error stream, so tests get plain ASCII.

`renderer_fuzzer` draws diagnostics built from fuzzer bytes with every
capability combination, since a shape the renderer doesn't expect must
never be
why the compiler dies while reporting a problem.

TODOs mark the follow-ups: line weights and crossing lines, wrapping
that keeps
a quoted type whole, and ordering diagnostics that share a byte offset.

Also: `IncorrectExtension`'s hint moves into its message, since its note
had no
location of its own, and `strip_noise` in `check_diagnostics.py` blanks
multi-line `#define`s instead of deleting them.

Assisted-by: Claude Code
2026-10-15 06:08:57 +00:00
Dana Jansens 24766e213e Defer evaluation of witnesses substituted while identifying a facet type (#7930)
When identifying a facet type, defer evaluation of LookupImplWitnesses
by redirecting them to evaluate into IdentifiedWitness. Then the caller
of identify will need to substitute the IdentifiedWitnesses, either with
witnesses of their own, or with LookupImplWitness to cause a lookup
operation.

This allows:
- An `impl as` on a named constraint can subst the witnesses in
designators from the named constraint with a witness to the impl itself.
This prevents them from looking for and finding some other overlapping
impl. (This PR)
- Impl lookup to collect rewrite/equality requirements from all named
constraints and then use the impls it has already found to evaluate any
designators in those requirements instead of performing impl lookup
again (creating a cycle). (Done in
https://github.com/carbon-language/carbon-lang/pull/7944)
- Similarly, an `impl as` can collect impls and equality requirements
from all named constraints and verify them correctly by replacing
witnesses that should refer to the impl with the correct witness instead
of performing a lookup and finding an overlapping impl. (Done in
https://github.com/carbon-language/carbon-lang/pull/7937)
- ImplWitnessAccess to be able to find rewrites from a named constraint,
not just from the initial DeclaredFacetType. (TBD)

To do this we need to introduce the concept of "identified" specifics.
In order to identify a facet type, we must construct a specific for each
require decl in a named constraint. These specifics will have
IdentifiedWitnesses inside them, but their args would otherwise match a
specific for the require decl constructed in another context. To avoid
polluting the canonical specific namespace, we introduce a second
namespace of specifics that are "identified" since they are created by
identifying.

As we have introduced a new global state that modifies eval behaviour,
we must disable that state when resolving a specific (as per
https://github.com/carbon-language/carbon-lang/pull/7923). But inside an
"identified" specific, we preserve the behaviour so that the witnesses
modified by identify (through SubstPeriodSelf or through evaluating a
require specific) have their evaluation deferred.
2026-10-14 14:12:56 +00:00
Lucile Rose Nihlen 1579d4ec7e Fix canonicalization and simplify default value patterns. (#7837)
Removes support for unspecified default values. Fixes canonicalization
of the `DefaultValuePattern` instruction by making them immutable after
they are issued, and by removing the `DefaultValueId` operand which
wasn't being canonicalized.
2026-09-25 22:59:55 +00:00
Dana Jansens fcae9610bd Make SemIR::TypeType be an empty FacetType instruction (#7813)
The type `type` is now a `FacetType` inst with no constraints. This
brings the model implemented in the toolchain into better alignment with
the language design. The `SemIR::TypeType` struct remains as a scope for
holding the `TypeInstId`, `ConstantId`, and `TypeId` constants, but is
not an `InstKind` anymore.

The `TypeType` inst looks a lot like singletons, but there are many
`FacetType` insts so it doesn't quite fit that model. So we put it
alongside singletons with a fixed inst id but refer to it as a more
general "builtin" inst that is not a singleton.
`Namespace::PackageInstId` is similar, and we group it with `TypeType`
conceptually as another builtin instruction with a fixed id.

No conversion is needed anymore to use a `type` as a facet, since types
also have a `FacetType` type. This simplifies and removes a number of
helpers and branches throughout the code.

The `TypeType` inst is now part of the constant store, so we end up
printing it in the constants block in every test. But it's also named
`type` rather than `%type` to preserve the majority of existing
formatting behaviour, though this does look different from other
constants.

Assisted-by: Opus 5 was used to generate a first draft and validate the
refactoring. Though nearly everything non-trivial the tool wrote has
been modified or rewritten.
2026-09-22 15:04:40 +00:00
Lucile Rose Nihlen 83ca5b71e3 Move default value inst ids to a dedicated value store. (#7810)
Per #7737 we move the default value `InstId` storage from
a block in the `SemIR::Function` data structure to a
`SemIR::File` scoped `ValueStore`.

Moves the default value consistency checking to the general
merge argument pattern matching logic, which changes the
error message issued to the generic one.
2026-09-21 18:27:01 +00:00
Lucile Rose Nihlen 994bad5143 Use non-canonical instructions in default values. (#7737)
Per feedback on #7665, this PR switches the default value
table storage from canonical constant inst_ids to
non-canonical.

Furthermore, this PR simplifies the default value support in
check by requiring that the first owned declaration of a
function completely specify all of its default values.
Updates the diagnostic code and tests to reflect this new
stricter requirement.
2026-09-17 22:04:43 +00:00
Lucile Rose Nihlen ca9e985fa8 Reconcile function default values between decl and def (#7665)
Updates the pattern matching code to support unspecified default values.
Adds logic to decl and def merge code to diagnose mismatches in defaults
if specified in both places, or if let entirely unspecified.

Per https://github.com/carbon-language/carbon-lang/pull/7521.
2026-09-08 20:41:58 +00:00
Lucile Rose Nihlen 2952ec9c10 Fix a crash when checking a nested tuple-pattern (#7716)
Adds a virtual node to `DefaultValuePattern` to end the
`ExprRegionForPattern` before checking the expression
for the default value.

When checking the default value expression, the context
was still configured to interpret expressions as patterns,
which caused some corruption of state with tuple-pattern
subpatterns.

Corrects an assertion failure I found while working on
feedback from #7665.
2026-09-04 01:22:16 +00:00
Lucile Rose Nihlen 3e64670122 Transform pattern default values to SemIR (#7649)
Adds check functionality to transform the parse node to SemIR. Only
supported for single declarations of functions, re-declaration and
imports to come in a subsequent PR.

Per #7521.
2026-09-01 16:12:34 +00:00