Files
carbon-lang/toolchain/check/testdata/impl/lookup/access.carbon
T
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

85 lines
2.8 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/lookup/access.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/access.carbon
// --- fail_todo_impl_witness_access_in_impl_type_structure.carbon
library "[[@TEST_NAME]]";
interface X(T: type) {}
interface Y {
let Y1: type;
}
interface Z {
let Z1: type;
}
// There's 2 ImplWitnessAccess instructions in the type, but they together
// resolve to a symbolic type value, so the type structure is: `? as X(?)`
impl forall [T: Z where .Z1 impls Y] T as X(T.Z1.(Y.Y1)) {}
class C(W: type) {
impl as Y where .Y1 = W {}
}
fn F(generic V: Z where .Z1 = C({})) {
// The type stucture is `? as X({})` which will match the impl's less specific
// `? as X(?)`, then the impl will deduce the parameter of `X` to be `{}` from
// the type of `V`. This would fail if ImplWitnessAccess instructions were
// treated as Concrete in the type structure, since the impl would have a
// different concrete value (an ImplWitnessAccess) than the query (a
// StructValue).
V as X({});
}
fn G(generic V: Z where .Z1 impls Y) {
// The type structure is `? as X(?)`, also built from ImplWitnessAccess insts,
// which will match the impl's `? as X(?)`.
V as X(V.(Z.Z1).(Y.Y1));
}
fn H(generic U: type, generic V: Z where .Z1 = C(U)) {
// The type structure is `? as X(?)`, without using an ImplWitnessAccess,
// which will match the impl's `? as X(?)`. This would fail if
// ImplWitnessAccess instructions were treated as Concrete in the type
// structure, since the impl's type structure would be more specific than the
// query's.
//
// TODO: This should pass.
// CHECK:STDERR: fail_todo_impl_witness_access_in_impl_type_structure.carbon:[[@LINE+2]]:3-11: error: cannot convert type `V` that implements `Z where .(Z.Z1) = C(U)` into type implementing `X(U)` [ConversionFailureFacetToFacet]
// CHECK:STDERR:
V as X(U);
}
// --- lookup_query_self_is_access_with_witness_from_nested_facet.carbon
library "[[@TEST_NAME]]";
interface HasNested {
let Nested: type;
}
interface Z {}
constraint ProvideZ {
require impls Z;
}
constraint NeedZ(T: Z) {}
constraint N {
extend require impls HasNested;
require Self.(Nested) impls ProvideZ;
// This performs an impl lookup `Self.(Nested) as Z`. When we identify
// the facet type of `Self` to find witnesses, we find a witness that
// `Self.(Nested)` impls `Z`.
require impls NeedZ(Self.(Nested));
}