100 Commits
Author SHA1 Message Date
Dana Jansens c832d7c11c Skill file for reviewing filetest output changes (#7815)
When an LLM tool is used to prototype a change, one of the major tasks
it must undertake is validating filetest output changes. This skill
helps to ground that validation in some best practices and explain what
sorts of changes should or should not be expected, and how to judge
STDOUT vs STDERR changes.

Assisted-by: Opus 5
2026-09-23 19:18:59 +00:00
Dana Jansens 15e3eeaca9 Only look in facet types for name scopes when they have constraints (#7819)
This falls back to diagnosing that values of type `type` can not be used
for name lookup more consistently.
2026-09-23 17:50:34 +00:00
Dana Jansens 795729bb4a Fix git path globs in summarize testdata changes SKILL (#7818)
When there's a wildcard in a path, git treats the path as matching
exactly, unless the path also ends in a wildcard. So
`toolchain/*/testdata` only matches the testdata directory names,
whereas `toolchain/*/testdata/*` matches all the files under them.
2026-09-22 17:23:11 +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
Dana Jansens fa12d9ded2 Skill file docs about how to write prose, names, and to prioritize the data model (#7814)
Largely about writing less, and defining what is worth talking about and
what is not.
2026-09-21 17:48:35 +00:00
Dana Jansens 413ac55d4f Add rules for working with jj history and prek (#7808)
Add rules to not overwrite git/jj history without asking, since this
destroys the reviewer's view of things. And some information on dealing
with stacks of commits within a single bookmark/PR.

Prek can make fixes for whatever caused a failure, and then pass when
you run it again, even though the user didn't change anything, and that
is now explained.

Assisted-by: Opus 5
2026-09-18 18:36:58 +00:00
Dana Jansens d84387f8b8 Add --build-mode to autoupdate script (#7809)
Allow the user to specify a build mode instead of detecting the last
used one.
2026-09-18 15:15:26 +00:00
Dana Jansens bfebb7cb42 Pass SpecificInterface through custom and C++ witness generation (#7784)
We were passing a SpecificInterfaceId which just makes code have to do a
lookup to get the actual SpecificInterface. The caller already has the
SpecificInterface, so plumb that around.

SpecificInterfaceId really only exists when we need to stick a
SpecificInterface into an instruction as an operand.
2026-09-15 21:23:28 +00:00
Dana Jansens 4416f3525b Canonicalize generated functions for Core witnesses (#7729)
Use a single `SemIR::Function` per `Core` interface method, whether it's
generated locally or imported. This prevents generating duplicate
functions, which lead to different types when the witness appears in a
`FacetValue` as part of a specific for a class.

We use a `CanonicalValueStore` of `GeneratedFunction` objects that allow
finding an existing FunctionId for a `Generated` special function before
(re-)generating it. Mangling for `Generated` functions is also moved to
use the values from the `GeneratedFunction`'s canonicalization key, so
that we have a consistent source of truth for the unique ID of a
`Generated` function across all files.

New tests are in
`toolchain/check/testdata/impl/custom_witness/destroy.carbon`.
2026-09-15 16:02:13 +00:00
Dana Jansens 4081848d65 Disable new clang-tidy rules with google- prefixed aliases (#7778)
Some `google-` prefixed rules have been renamed to rules without the
prefix. The `google-` prefix still remains as an alias to these new
rules. Since we turn on the `google-` prefix rules and use those in
NOLINT expressions, disable the new aliased names. Otherwise we have to
put both names in NOLINT expressions.
2026-09-12 09:35:03 +00:00
Dana Jansens 648ccc5f9b NOLINT a cycle in semir formatting (#7774)
Add a TODO that we should address this cycle.
2026-09-11 22:29:17 +00:00
Dana Jansens 0d9560c049 Disable readability-redundant-nested-if in clang tidy (#7776)
This is a style choice we often agree with, and call out in code review.
But there are many cases where we do want to split apart nested ifs,
such as when working with LLVM apis like `dyn_cast`:
```
if (auto* thing = dyn_cast<Thing>(other)) {
  if (thing->foo()) {
    ...
  }
}
```

Or we may have TODOs or other comments in the scope of the outer if,
which the tidy check ignores.

Since this doesn't lead to bugs, we disable the check and leave this to
reviews and authors for their discretion.
2026-09-11 19:51:41 +00:00
Dana Jansens 09feee7534 Remove empty lambda parameters in handle_function (#7777)
These are marked as redundant by clang-tidy 23
2026-09-11 18:22:33 +00:00
Dana Jansens 111ec69b65 NOLINT an assignment in a complex boolean statement (#7775)
We use a complex fold statement over `operator=`, with an assignment to
a variable earlier in the folded-over expression, which is intentional.
2026-09-11 17:04:40 +00:00
Dana Jansens c45efd625f Move to clang 21 as mininum version and use it in CI (#7779)
Clang 21 is now the latest version available in Ubuntu LTS, so we can
move to it.
2026-09-11 16:58:59 +00:00
Dana Jansens 49345352d6 Remove redundant use of typename (#7751)
clang-tidy 24 warns about these
2026-09-11 00:22:27 +00:00
Dana Jansens f819fafa12 NOLINT the use of sizeof() on a pointer if a pointer is hashed (#7765)
The hashing code is generic over the type of the value being given to
sizeof() so ideally this warning would not happen at all, but it does.
Possibly because the value is the return of an overload set, so it's not
obvious that it's the templated type. One of those overloads returns
`const void*` but change that to an integer does not remove the warning
still.
2026-09-10 23:54:11 +00:00
Dana Jansens dd43b50310 NOLINT an initializer list construction that clang-tidy warns on (#7759)
Clang is synthesizing a cast when using an enum value from a template
parameter, and then clang-tidy is finding and reporting that cast.
Upstream bug: https://github.com/llvm/llvm-project/issues/222793
2026-09-10 23:49:07 +00:00
Dana Jansens 981a0e9445 NOLINT the cycle through HandleAction and pattern matching (#7767)
Leave TODOs on all the places that needed to be silenced
2026-09-10 22:33:50 +00:00
Dana Jansens 656026f630 Move diagnostic emit functions to protected to match their base class (#7764)
The emit functions are inherited from a base class as protected, and
clang-tidy warns if we then expose them as public.
2026-09-10 22:29:52 +00:00
Dana Jansens 03bd40c398 Disable clang-tidy forbidding forward decls of classes with the same name in another namespace (#7766) 2026-09-10 22:14:25 +00:00
Dana Jansens e87831373f NOLINT and document use of StringLiteral::data() which subclasses StringRef (#7757)
StringRef::data() is problematic to call, but StringLiteral is always
NUL-terminated, so data() gives a valid C string.
2026-09-10 22:00:36 +00:00
Dana Jansens 8732bd9de1 Replace C-style variadic with a concept (#7761)
clang-tidy 24 warns on C-style variadics, and we don't need to use one
here anymore. Instead of a function call with an argument list, use a
concept to determine if a type can be list initialized.
2026-09-10 21:26:37 +00:00
Dana Jansens eca38a90e1 Remove empty lambda parameter lists (#7760)
clang-tidy 24 warns about these being redundant
2026-09-10 20:10:36 +00:00
Dana Jansens 52e28c02c3 Disable readability-identifier-naming in clang-tidy 24 (#7752)
This check allows styles that we don't use so it's not really useful for
enforcing our style guide. And prevents the use of `_1` or similar in
destructuring declarations where want to use `_` for multiple variables,
such as `auto [_1, _2, foo] = bar()`.
2026-09-10 20:03:26 +00:00
Dana Jansens 3942eca83f Disable the bugprone-crtp-constructor-accessibility warning in clang-tidy 24 (#7758)
The warning wants all classes inherited as CRTP base classes to hide all
their constrcuctors and friend all uses of them. We use CRTP quite a lot
and across different components of the toolchain, which would make
maintaining friend lists frustrating.
2026-09-10 19:53:15 +00:00
Dana Jansens 6f1ae86ce4 Disable -Wunused-template in clangd-tidy (#7750)
This is firing on some of our _used_ templates in eval.cpp in clang-tidy
24

It was coming to `-Wall` for clang as well
(https://github.com/llvm/llvm-project/issues/202945) but was reverted
due to issues like false positives
(https://github.com/llvm/llvm-project/pull/218638). Some fixes were
applied to try enable in `-Wall` in clang 23
(https://github.com/llvm/llvm-project/pull/222336) but it still remains
disabled by default for clang.
2026-09-10 19:28:25 +00:00
Dana Jansens dbcae83784 Passthrough the StringRef to mapRequired instead of just the data() pointer (#7756)
The StringRef represents a bounded region of a string, but using data()
drops the end bound, and makes LLVM construct a new StringRef starting
in the same position and going until a nul terminator. If this worked
correctly before, it was because the StringRef was always pointing to a
full `std::string` or the tail of one.
2026-09-10 19:19:56 +00:00
Dana Jansens 804dc3baaf Disable readability-use-concise-preprocessor-directives in clang-tidy 24 (#7754)
While we do adhere to its expectations most of the time, we don't
always. This is a low value check, and it's a stylistic choice to use
`#if defined(...)` when paired with `#elif defined(...)`.
2026-09-10 19:12:54 +00:00
Dana Jansens 76f52e0abb Move reserveExtraSpace to public (#7755)
The method it overrides in the base class is public, so it's already
accessible publicly. This is warned against in clang-tidy 24.
2026-09-10 19:12:00 +00:00
Dana Jansens bf8c997581 Disable bugprone-return-const-ref-from-parameter in clang tidy 24 (#7753)
We intentionally return const references from stable containers like
value stores.
2026-09-10 19:01:47 +00:00
Dana Jansens 4985e35695 Exclude .clang-tidy from rumdl checks (#7749)
Basically the whole file is an error and the formatting is not how we
want to write the file, so just exclude it.
2026-09-10 18:20:45 +00:00
Dana Jansens dd50e88168 Disable bugprone-derived-method-shadowing-base-method in clang-tidy 24 (#7748)
This fires on methods that we shadow, such as Print for a Printable<T>
subclass.
2026-09-10 17:04:10 +00:00
Dana Jansens c6c40cc444 Avoid using string operator += for a single character (#7747)
This is flagged as a mistake by clang-tidy 24. String's operator `+=` is
pretty bad in general, this moves a few uses to push_back.
2026-09-10 16:39:08 +00:00
Dana Jansens eabc7f78b2 Show the errors that occurred, if any, when executing a dump command in lldb (#7743) 2026-09-10 12:47:28 +00:00
Dana Jansens 2aeecef17a Gracefully handle member access on a runtime type value (#7744)
Avoid CHECK failure when performing member access on a runtime type
value. We will just fail to find the CanonicalFacetOrTypeValue and then
fail lookup.
2026-09-09 23:05:48 +00:00
Dana Jansens 386327ed4c Disable clang-tidy misc-multiple-inheritance for clang 24 (#7724)
We use multiple inheritance extensively, such as with our
EntityWithParamsBase subclasses. But we don't do this for
vtables/virtual, we do it for composing fields.
2026-09-05 06:25:30 +00:00
Dana Jansens efb7ca9b90 Include ASTContext where it's used in mangler.cpp (#7723) 2026-09-04 16:52:16 +00:00
Dana Jansens 8626d6653d Disable readability-inconsistent-ifelse-braces (#7719)
This produces a warning on every use of CARBON_KIND() with clang 24.

I tried putting NOLINT comments into the macro on the else to no avail.
It seems that comments are stripped from the macro output when it's
performing the check.

We already require {} on every if/else (outside of these weird macro
cases) so this doesn't seem like a problem to disable.
2026-09-04 01:35:46 +00:00
Dana Jansens 1b969c292b Remove a comment that looks to be left behind from a refactoring (#7718)
The GetFacetTypeForQuerySpecificInterface function has two comments on
top of it. The second one actually refers to what the function does.
2026-09-03 19:56:34 +00:00
Dana Jansens 48671bffe2 Use match_first and remove some workarounds in prelude float.carbon (#7713)
The float.carbon conversions for int->float, uint->float and
float->float were using various workarounds through extra indirections
in order to avoid the impls overlapping. Now we can write them all as
`impl From as ImplicitAs(Float(To))`, which makes them all appear to
overlap, though any given type will only match at most one of them. We
use `match_first` to give them an ordering regardless so that they are
allowed to overlap in type structure.
2026-09-03 14:58:27 +00:00
Dana Jansens 2299b94b20 Use match_first to make the same_self_and_interface.carbon test pass again (#7711) 2026-09-03 14:58:13 +00:00
Dana Jansens 1740b24879 Use a consistent SDK version on MacOS (#7704)
The SDK returned by `xcrun --show-sdk-path` does not always match the
SDK
that is used by clang under homebrew, because homebrew has its own
configurations per target that specify an SDK path to `-isysroot`. And
on
Darwin, the `-isysroot` flag supercedes the `--sysroot` flag entirely
when
present.

To override homebrew, and ensure we use the SDK we expect to be using
from
`xcrun`, specify `-isysroot` ourselves on the command line, both when
finding
the include paths and when building.

The compiler ends up taking a dependency on a JSON file at the root of
the
SDK as well, so add that to our allowlist of non-hermetic files,
along-side
the SDK include paths.
2026-09-03 14:58:01 +00:00
Dana Jansens b6ba4ecdbb Use match_first to make the impl_recurse_with_simpler_type_in_generic_param_bidirectional_no_cycle.carbon test pass again (#7712) 2026-09-02 21:56:12 +00:00
Dana Jansens 95897201ee Avoid disk cache on MacOS by default since it breaks debugging (#7702)
There's no way for the user to override and disable the disk cache once
a path is specified in our current version of bazel. Later versions
would allow the user to specify `--nodisk-cache`. If the user really
wants a disk cache anyway, they can specify as such in their
`user.bazelrc` file.
2026-09-02 21:12:48 +00:00
Dana Jansens f2ca6f6d4a Document installing SSL certificates for Python on MacOS (#7707) 2026-09-02 20:33:54 +00:00
Dana Jansens ed074e85ab Include StringSet where it is used (#7708) 2026-09-02 19:38:23 +00:00
Dana Jansens a460ce931e Document that match_first may contain a fourth declaration of an impl. (#7709)
The declarations in a `match_first` must always be in the same file as
the first owning declaration, in order to maintain a consistent view of
impl lookup across all files.
2026-09-02 19:38:12 +00:00
Dana Jansens b8eca6a6da Include the ASTContext header where it's used (#7701) 2026-09-02 17:35:31 +00:00
a9cc7bf490 File concatenation principle (#6031)
We propose a principle that it's always possible to inline the import of
a library from within the same package without changing the meaning of
or diagnostics applied to the code. This is similar to the textual
inlining of an `#include` statement in C++, but is slightly less
general. Cross-package imports place the imported names inside the name
scope of the package, so inlining those necessarily changes the paths
for name lookup.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2026-08-03 17:20:59 +00:00
Dana Jansens 2f58185c44 Find the current impl from accesses in a named constraint being implemented (#7592)
When implementing a named constraint, like `impl as N`, any accesses
through `Self` in the named constraint need to get the value of the
associated constant from the impl's witness table. This isn't possible
immediately, since the impl does not even exist until the declaration is
complete. We use the same model as for accesses found directly in the
impl declaration, but applied to the point where accesses in the named
constraint are substituted during identify to point at the impl's self
type. To get there, we need LookupImplWitness instructions in the named
constraint, when re-evaluated during construction of their enclosing
specific, to evaluate to ImplSelfWitness when they are a reference to
the type and interface being implemented.
2026-07-31 20:17:06 +00:00
Dana Jansens db88edfa1e Disable RTTI in the toolchain (#7552)
This reduces object sizes which is desirable for linking speed.

zygoloid did some analysis to determine if any of our code requires RTTI
for `dynamic_cast` here:
https://github.com/carbon-language/carbon-lang/pull/7532#discussion_r3611196721:
> The only thing I found is that libc++ requires dynamic_cast in order
for std::print to correctly write Unicode to terminals on Windows

We use `llvm::print` functionality, not `std::print`, so this doesn't
affect our toolchain.

Note that libc++ and libc++abi are built with RTTI enabled. It is
explicitly allowed to use different compiler flags when building these
libraries even though they share some headers with users of the
libraries, so this does not cause ODR violations.
2026-07-31 20:09:48 +00:00
Dana Jansens 9b8a2124b9 Don't require non-class types to be complete to convert from them (#7590)
In Convert, we require the source value's type to be compete so that we
can look for `base` classes and `adapt` relationships. However these can
only be present in a `ClassType`, so we only need `ClassType`s to be
complete.

Reduce the requirement in Convert to not complete types that are not a
`ClassType`, and which can not contain a `ClassType` as part of their
class.

Ideally we would only _only_ require the `ClassType` itself to be
complete, and only if we're looking for a base or adapt. However lower
depends on us completing all Convert source types that contain a class.
This seems to suggest we're lacking checks for complete types somewhere
else and Convert is making up for it. A TODO has been added. The
`toolchain/driver/testdata/compile/optimize/optimize_debug.carbon` test
is an example that CHECKs due to failing to verify the LLVM module if we
do not compute the complete type of all class-containing types in
Convert.

The critical step this PR is doing is to stop trying to complete a
`FacetType` when converting from a facet. This avoids trying to complete
a named constraint when converting `Self` inside that named constraint.
Doing so causes a cycle when the conversion of `Self` is performed in
eval of an `extend require` decl, since requiring the named constraint
to be complete re-evaluates the `extend require` decl again. A test is
added that crashed in an infinite loop before this change.

It also depends on #7584, which was intended to be an optimization but
is now load bearing. Because converting `Self` leaves an impl lookup
inst behind, and if that inst is re-evaluated inside impl lookup (by
forming a specific of a `require` decl through identify) then we have a
similar cycle.
2026-07-31 17:35:21 +00:00
Dana Jansens 239ad9fe8b Disable C++ exceptions in the toolchain (#7532)
Pass `-fno-exceptions` when building the toolchain. We do not use
exceptions, so we do not have any try/catch in main, so uncaught
exceptions just unwind and exit. They do not hit our signal handler and
we do not print the stack trace.

Instead of adding a try/catch in main, and redirecting that, we can
build with `-fno-exceptions`. This turns any throw into an `abort()`.
And indeed with that flag, the following code crashes and prints a stack
trace:
```cpp
  std::variant<int, bool> a = {1};
  std::get<bool>(a);
```

Note that libc++ and libc++abi need to be built with exceptions enabled.
It is explicitly allowed to use different compiler flags when building
these libraries even though they share some headers with users of the
libraries, so this does not cause ODR violations.

Fixes #5225
2026-07-30 20:15:03 +00:00
Dana Jansens a5ba0a0f45 Use GetConstantValueInSpecific to get the impl's specific interface after deduction (#7584)
During impl lookup, for each (generic) impl candidate, we form a
specific for that impl by deducing its generic arguments. Then we
compare the query interface against the impl's specific interface. That
comparison needs the deduced arguments applied to the impl's specific
interface. Previously we were doing this by getting the impl's
constraint facet type with the impl's specific applied (via
`GetConstantValueInSpecific()`) and then identifying that facet type
with the impl's deduced self.

Identify is a fairly expensive operation. It runs subst, trying to
replace `.Self` references. It walks named constraints. It collects
require declarations. We're looking at making it do _more_ in the future
too, including rewrite constraint resolution and collecting rewrite and
same-type constraints. For this reason we have a cache to make it cheap
on the second run, but it's still a very heavyweight operation to
involve in impl lookup, when all we want is to apply the impl's specific
to its target interface.

We almost have all the information we need to avoid the identification
step. We have the impl's specific after deduction. And we have the
SpecificInterface that the impl is targeting in the `Impl` struct. When
we form the specific for the impl itself, we resolve the declaration
block and form new constant values for all instructions in there, but
that does not cover the SpecificInterface that we're storing in the
`Impl` struct. So we add a new instruction to the impl's eval block,
which will be symbolic when the impl is generic and the target interface
depends on a generic parameter. And we store the `InstId` in the `Impl`
struct. This allows us to gets its constant value later with the impl's
specific applied. From that constant value we can then pull out the
SpecificInterface that the impl is targeting.
2026-07-30 19:59:10 +00:00
Dana Jansens f51c075f8b Avoid symbolic witnesses for .Self in an impl decl (#7564)
Point symbolic witnesses into `.Self` written inside an impl decl at the
impl that is being declared. This is tricky because the impl does not
yet exist. So we use a new instruction `ImplSelfWitness` which _will_ be
replaced by the `ImplWitness` once it becomes available. The
`ImplSelfWitness` acts like a symbolic witness, except it does not
perform lookup, since we know which impl we will get a witness from.

This prevents us from finding other impls when performing lookups into
`.Self` in an impl decl, which produces incorrect/incoherent results.
2026-07-29 16:25:23 +00:00
Dana Jansens 8ac0edb280 Add a failing test where frozen .Self is passed in generic argument and never thawed (#7582) 2026-07-29 15:18:43 +00:00
Dana Jansens 48a03e6a1c Remove TODO to check for orphan impls (#7562)
Orphan impls are found at the end of checking the file, in
`ValidateImplsInFile()`.
2026-07-24 19:11:21 +00:00
Dana Jansens 8c42d383c7 Use SubstOperandsSkipType to allow using SubstPeriodSelf on a facet type (#7556)
This makes SubstPeriodSelf more generally useful, with one less gotcha.
Previously calling it with a facet type would just do nothing.

This is possible now because we
- Have SubstOperandsSkipType to make use of
- Have banned constructs which introduce ambiguous .Self, so we don't
need to try avoid finding undesired .Self insts in facet types in other
positions (like in specifics).
2026-07-23 18:31:46 +00:00
Dana Jansens 453b5474e4 CHECK that the self is a symbolic type when looking for a Destroy and its type is a facet (#7553)
As a follow up to #7546 (and see the discussion there), verify our
assumptions that you can't have an object of type facet where the facet
is not symbolic, and then need to find a Destroy witness for the object.
2026-07-22 18:08:35 +00:00
Dana Jansens 9796b7bc78 Add tests (mostly failing) that rewrites in an impl can satisfy required constraints (#7547)
A rewrite's RHS value should be used when checking that the rewritten
associated constant impls an interface.
2026-07-22 17:00:53 +00:00
Dana Jansens d2ac9b3933 Diagnose where in a binding that introduces a .Self that does not refer to the binding (#7517)
This is in addition to finding a `where` on the RHS of another `where`.
Since a generic binding introduces `.Self`, any `where` expression that
isn't part of a facet type modifying the binding itself would introduce
an ambiguous `.Self`.

Add virtual parse nodes for let, var, and form bindings, which goes
before the type. This allows us to track if `where` appears in the
binding's type. We only need to look for an invalid `where` if any
appeared in the type. We combine these three nodes together into a
single node kind, which requires us to remove the name from it as a
child. We move it up to the Pattern node again, and rename the
PatternStart nodes to PatternTypeStart as they are now located in the
middle of the Pattern nodes, just before the type.

And we only need to thaw `.Self` in generic bindings. Non-generic
bindings can only have `.Self` through a `where` expression, since the
name is not provided otherwise to non-generic bindings. And `where`
expressions thaw their `.Self` independently. So the binding only needs
to thaw a `.Self` that it introduced, which is only for generic
bindings.
2026-07-22 16:45:00 +00:00
Dana Jansens 21dc5cde04 Ensure where requirements in named constraints are visible to lookups (#7299)
Require rewrite and same-type constraints that do not depend on `.Self`
to be satisfied when a facet type is identified, since those constraints
may not be found later.
2026-07-22 16:18:57 +00:00
Dana Jansens f8f50cb167 Don't try produce a custom witness for a symbolic value of type facet (#7546)
For a symbolic value with a type being a facet, we need to find a
witness either from the facet's type or from an impl. Custom witness is
for producing a concrete final witness, but there is no such witness in
this case. We should fail to find a witness, and defer to impl lookup to
find the Destroy witness.

Currently it tries to find a witness from the facet type, but it ignores
named constraints, which means it's incomplete at best. But there's no
value in trying to say that the value is trivially destroyable, when it
has a type that impls Destroy. It may not be trivial, and we can't
actually make a witness for it while symbolic.
2026-07-21 19:39:31 +00:00
Dana Jansens 63757d281e Require all impls constraints in impl as to be satisfied (#7531)
We checked that requirements inside the impl-as target interface were
satisfied. But we also need to check that requirements coming from the
constraint facet type, or named constraints that it targets, are
satisfied.
2026-07-21 19:31:54 +00:00
Dana Jansens 4b46e63b41 Move IdentifiedFacetType to its own file (#7542)
I wanted to move it to check but there'd still be an
IdentifiedFacetTypeId and we keep all Ids in sem_ir. So leaving it in
sem_ir, but moving it to its own file. This more clearly separates
DeclaredFacetTypes and IdentifiedFacetTypes.
2026-07-20 21:45:17 +00:00
Dana Jansens 085e45093e Avoid consuming a token after an invalid match_first opening (#7538)
If the `match_first` is not followed by `{` avoid consuming whatever
comes after it. Recover by leaving whatever comes next alone. It could
even be the `FileEnd` token, and then we would crash when we read off
the end of the token stream looking for `FileEnd`.
2026-07-20 19:09:16 +00:00
Dana Jansens 2d9e3fee67 Use identified facet type to get impl-as target (#7519)
This supports impl lookup choosing an impl that targets a generic
interface through a named constraint, without crashing.

Instead of assuming the impl's target is a facet type containing an
interface, we use the identified facet type to find the specific
interface it targets.
2026-07-16 19:11:23 +00:00
Dana Jansens 0848cf941d Look outside constant values for designators in where constraints (#7367)
The constant value may lose the designator during eval, such as an
`ImplWitnessAccess` that resolves to some concrete type. Look in the
non-canonical instructions instead.
2026-07-16 19:00:06 +00:00
Dana Jansens b3e9dd3ea2 Consolidate checking for and rejecting other_requirements in impl lookup (#7518)
Since the introduction of `other_requirements`, we now have a dedicated
step in impl lookup for checking that the requirements of the query
facet type are satisfied. That is the place where we will be checking
same-type constraints, which `other_requirements` signals the presence
of.

Consolidate all checking of `other_requirements` to that step, which
reduces our use of `FacetTypeInfo` (as opposed to the
`IdentifiedFacetType`) and removes interest in same-type constraints
from code that is not related to them.
2026-07-16 18:09:46 +00:00
Dana Jansens 81e495ee53 Impls in final match_first block aren't always final (#7512)
If an earlier impl may match a more specific query, then later impls can
not be treated as final for the given query.

See
https://github.com/carbon-language/carbon-lang/blob/de8b03faa3178ae683d8e7124fbcba81eb88e00c/proposals/p005337-interface-extension-and-final-impl-update.md#using-associated-constants-from-impls-in-a-final-match_first
2026-07-16 13:10:09 +00:00
Dana Jansens cda1f256bb Use match_first to prioritize impls (#7492)
Allow (don't diagnose) impls that have the same type structure if they
are associated with the same match_first block. Similarly, allow final
impls (made final by their enclosing match_first block) that overlap in
type structure when they are associated with the same match_first block.

If the type structures are the same, choose the first impl from the
match_first block.same.

If the type structures overlap but are not the same, and share a
match_first block, then we should choose the first overlapping impl from
the match_first block. This is true both for final and non-final impls.
See
https://github.com/carbon-language/carbon-lang/blob/de8b03faa3178ae683d8e7124fbcba81eb88e00c/proposals/p005337-interface-extension-and-final-impl-update.md#impl-selection-algorithm

But in the non-final case if there is an overlapping impl outside the
match_first, it can win if it's more specific.
2026-07-15 21:25:25 +00:00
Dana Jansens 168420f805 Allow impl redecl in match_first after a definition (#7491)
Previously the last decl had to be the definition. Now we allow a
declaration after a definition, so that the user can write a match_first
block last, and put (re-)declarations of impls in it, after the
definitions have already been written elsewhere.

We track the location of the decl that was associated with a match_first
block so that we can correctly point to it in diagnostics when an impl
is written twice in match_first blocks. Since impls may not be
redeclared across an import boundary, we will never have a `SemIR::Impl`
with a match_first from a different file in a redeclaration, so we don't
need to import the location of a previous decl that was in a match_first
for diagnostics. As such we just store a LocId on the `SemIR::Impl`
struct.
2026-07-15 14:12:37 +00:00
Dana Jansens d47de6443e Freeze the .Self type and make non-extend constraints available after where (#7501)
The type of `.Self` introduced by `where` may contain a `.Self` inside
it. Freeze the type so that we have a consistent view of `.Self` inside
the facet type, where they are all frozen.

The type of `.Self` only has extend constraints from the LHS of the
`where`. So we need to copy any non-extend constraints into the
`where_stack` so they are available as early-impls and can be used for
impl lookups on the RHS of the where. We need to freeze any `.Self`
references in these just as we do for rewrite constraints.
2026-07-14 19:04:33 +00:00
Dana Jansens 8ea32187d4 Disallow impl in match_first twice (#7493)
Prevent dead code by diagnosing putting the same `impl` in a
`match_first` block more than once.
2026-07-13 21:58:06 +00:00
Dana Jansens d46b040290 Connect impls to their containing match_first block (#7486)
When we check an `impl` decl, find the containing `match_first` block,
if any, and store a connection to it in the `SemIR::Impl` structure,
along with the impl's position in that `match_first` block so that we
can sort/prioritize the `SemIR::Impl`s later.

Also, update the `is_final` flag if the `match_first` block is modified
as `final`. But ensure we diagnose trying to put a `final impl`, or a
redeclaration of one, in a `match_first` block. Also diagnose if an impl
is attached to a `match_first` block more than once - either in two
different blocks or in the same block at different positions.

Putting the `match_first` connection on the `SemIR::Impl` structure
means we have to import it, so implement import and add a smoke test for
that, which ensures nothing explodes.

Drop the `scope_stack` entry for the `match_first` block, as it was not
needed. Once we started tracking the `match_first` size on the `Context`
class, it became more straightforward to just store the `match_first`
decl `InstId` in the same place. The `match_first` block is not supposed
to act like a different scope for the purpose of redecls anyhow, so it's
a bit simpler this way.
2026-07-13 19:14:38 +00:00
Dana Jansens d6f9559cfb Diagnose if match_first is not in a valid scope (#7482)
It must be in a namespace, function, or class. In particular, it can't
be in another match_first, doing so immediately associates any impl
inside with two different match_first scopes, but we only want them
associated with one for prioritization.
2026-07-11 14:54:42 +00:00
Dana Jansens a46f4863db Basic checking for match_first blocks (#7481)
Push a scope_stack entry for match_first blocks, and handle impls being
inside those scope entries. An impl should not use the `match_first`
block as its "enclosing scope" for the purpose of deciding if the impl
is a redecl of another impl. We should look through it to the class or
namespace the impl (and match_first) are located inside.

We don't yet store the relationship between the impl and its match_first
block, nor then can we use it in impl lookup for prioritization.
2026-07-11 14:01:38 +00:00
Dana Jansens bf106c3b4b Handle missing curlies after match_first without crashing in parse (#7480) 2026-07-11 00:03:31 +00:00
Dana Jansens 783f1601fd Include whether the impl is final in textual semir (#7485)
When formatting an impl definition, include in the textual output if the
impl is final. Since we (mostly) write them as `final impl` in the code,
use the same notation in the textual semir.
2026-07-10 21:09:10 +00:00
Dana Jansens 69433a1834 Remove the ImplicitOnly option from SubstPeriodSelf (#7461)
The implicit/explicit `.Self` concept is a heuristic at best, so we
should avoid relying on it. The ImplicitOnly option is no longer used,
as it was used to remove/disambiguate `.Self` in nested facet types, but
we have banned nesting `where` on the RHS of a `where`. So we no longer
have to worry about ambiguous `.Self`.

We can remove all the designator tracking heuristics in `.Self`
substitution as well now, as they were used for the now-removed
ExplicitOnly (removed in
https://github.com/carbon-language/carbon-lang/pull/7460) and
ImplicitOnly options.
2026-07-10 17:58:33 +00:00
Dana Jansens 55dcf66584 Remove extra SubstPeriodSelf and canonicalization (#7474)
The self and interface given to TryFindMatchingWitnessFromImplLookup
come from the output of SubstPeriodSelf, so there is no need to do the
substitution again. And the self came from a LookupImplWitness
instruction so it is already fully canonicalized.
2026-07-09 22:12:18 +00:00
Dana Jansens 7b0da12696 Remove the ExplicitOnly option from SubstPeriodSelf (#7460)
The implicit/explicit `.Self` concept is a heuristic at best, so we
should avoid relying on it. We now only have one value of `.Self` in a
facet type (we have banned nested `where` on the RHS of a `where`). So
we don't need to preserve any `.Self` for the purpose of disambiguation,
and we can subst all `.Self` on the the RHS of a rewrite constraint.
2026-07-09 21:31:52 +00:00
Dana Jansens c74bb933d2 Avoid impl lookup cycles from evaluating lookup instructions inside an impl decl (#7454)
`LookupImplWitness` instructions inside the impl declaration can't use
the impl they are apart of. Previously we had an heuristic in eval which
would try to prevent finding the impl for a lookup from inside that
impl. But it breaks when the `.Self` is replaced in a generic impl with
a symbolic, and then that symbolic is replaced in a specific. The
specific's decl block contains that `LookupImplWitness` instruction and
it tries to use the impl it came from. This causes the same specific to
be formed again, but now it exists, so it's used as-is but it has no
decl block yet, and so we crash.

Now we ban an impl while we resolve its specific, both deduction of its
arguments and from any other substitution. The prevents instructions
from inside the impl (which are evaluated when resolving the specific)
from finding their own impl. We do so by adding the ImplId to a stack on
the Context, and then skipping such impls when looking for candidates
during eval.

This fixes a crash, which was demonstrated by the new test being added.
It also makes another todo test pass.

There's a whole lot of other semir churn, which seems to be mostly
reordering of constants. There are some fingerprint changes in
constants, but it appears they are the same canonical instructions, so
they don't represent a behaviour change. For example in
`toolchain/check/testdata/for/actual.carbon` the `%N.patt` constant has
been given its fingerprint suffix now as `%N.patt.aa5`. But they are
both this instruction, so it is just a formatting change:

```
inst6100001A: {kind: SymbolicBindingPattern, arg0: entity_name61000002, type: type(inst61000018)}
  - name: `N`
  - type: type(inst61000018): <pattern for Core.IntLiteral>; {kind: PatternType, arg0: inst(IntLiteralType), type: type(TypeType)} (concrete)
  - value: symbolic_constant61000001
```
2026-07-09 20:38:56 +00:00
Dana Jansens 06e31437b9 Some slight tweaks to comments in/on WitnessQueryMatchesInterface (#7475)
I attempted the TODO as stated but we can't remove the `.Self` from the
LHS of a rewrite right now, without causing evaluation to run and
potentially find a concrete value to replace the access with, which then
breaks the association with the associated constant. There's a separate
TODO about that in SubstPeriodSelfInFacetType.
2026-07-09 19:34:55 +00:00
Dana Jansens b1c7e585f9 Diagnose .Self being used in a type that is not a facet type (#7471)
`.Self` will only be replaced in a facet type, as the facet type
constrains a facet. If it's part of a (non-facet) type, then the object
of that type is not a facet, and we can never replace that `.Self`.
2026-07-09 19:09:06 +00:00
Dana Jansens 11901b1a59 Parse match_first blocks (#7478)
`match_first` is a declaration followed by a curly-brace block of
declarations.

The check phase will ensure only impl decls (or defns) are inside the
block.
2026-07-09 15:34:52 +00:00
Dana Jansens bb0d74ba39 Remove an extra canonicalization of a self that is already canonicalized (#7477)
Clarify that the functions that search for a witness in a facet type no
longer take inputs from the query directly, but now take them from an
identified facet type constructed from the query. That means the self
type is already canonicalized.
2026-07-09 13:59:51 +00:00
Dana Jansens 4261bb2dd2 Track and don't replace active .Self (#7443)
In #7436 we stopped substituting `.Self` when collecting witnesses out
of a facet type. While this was correct, it did not capture all the
cases that need to avoid substituting `.Self`. And it poisoned the
`IdentifiedFacetType` cache by not replacing `.Self` but storing the
result in the cache. This led to incoherent behaviour, where the result
of an impl lookup would change depending on which ones had been done
previously.

Now we use a flag to track for each `.Self` if we're currently
type-checking inside the scope where it was introduced in a facet type.
While inside that scope, identify should not replace the `.Self`. Any
use of it should remain as-is since we don't yet know what value will
replace it. We call this state "frozen" since it should not be modified
by identify. This requires a substitution step when we leave the scope
that introduced the `.Self`, to remove the flag. The flag is set in the
`EntityName` of the `SymbolicBinding`, and is part of the canonical
value, since `.Self` can become part of types, which are constants, and
the flag needs to follow it for correct behaviour.

We also have to ensure the flag is the same when doing comparison with
constants from inside a facet type and constants from outside. For
instance in `(Z where .Z1 = ()) where .Z2 = .Z1`, when we arrive at the
second `.Z1` its `.Self` will be frozen, while the `.Z1 = ()` contains a
non-frozen `.Self`. So we add the frozen flag to the first when storing
it in `where_stack` in order to compare the constant values of the two
`.Z1`.

The `WhereExpr` requirement inst kinds now have an `InstConstantKind` of
`AlwaysUnique` instead of `Never`. This allows us to add them to the
usual InstBlocks, and in an `eval fn` body they have a constant value,
so eval does not fail when trying to call that function. We have to be
careful to not consider `AlwaysUnique` as being actually concrete
though, since their constant value erases `.Self`-dependence. This
allows us to stop special casing them when thawing the requirements
block in a `WhereExpr`, and we can just thaw each `InstId` in the block
in a straightforward manner.

We add the new flag to the instruction's fingerprint and name in
formatted semir.
2026-07-08 18:04:56 +00:00
Dana Jansens bd3ca2b72b Subst the whole facet type to replace .Self in identify (#7449)
This performs `.Self` substitution in a single step, for the whole facet
type, instead of doing it individually for each constraint visited in
the top-level facet type. Then we don't need to track state to avoid
subst in constraints that come from other named constraints.

The semir changes are because we now generate a whole other FacetType
from the substitution.
2026-07-07 13:30:53 +00:00
Dana Jansens 11dca8f227 Add SubstResult::SubstOperandsSkipType to not subst the type_id (#7452)
Add a result for Subst() to return when you want to recurse into the
instructions operands but not the type_id. This comes up when recursing
and looking for facet types written in an instruction, but not
referenced indirectly through a type_id.

We can't skip adding the instruction to the worklist entirely, since we
need to pop it back off to rebuild the containing instruction later. So
we just mark it with a skip flag, and don't call Subst() on it.

The suggestion for a change to Subst was made in
https://github.com/carbon-language/carbon-lang/pull/7367#discussion_r3423446839.
2026-07-07 13:23:47 +00:00
Dana Jansens e7771c2f6d During identify replace .Self only in the initial facet type (#7436)
When we find a named constraint during identity, we recurse into it. The
specific args of the named constraint may contain references to `.Self`
which can then make `.Self` appear inside the named constraint, which
was making us replace `.Self` at multiple levels and incorrectly. The
first specific argument replaces `Self` in the named constraint, and we
pass in the self-type of the identify operation. This may contain
`.Self` and we should _not_ be replacing the `.Self` references with the
self-type that they are contained within. This led to infinite cycles.

In the meantime, we have made the toolchain reject any ambiguous `.Self`
from being constructed. So we know there is only one value of `.Self`
around in a facet type.

So now we replace `.Self` only in the top level facet type during
identity. That means replacing `.Self` in the specifics of the named
constraints that we recurse into. But we do _not_ replace `.Self`
anymore inside those named constraints. This resolves the infinite loop.

At the same time, when we are identifying an `impls` constraint from
earlier in the same facet type, like `C impls Z(.Self)` we are
identifying with a self-type of `C`. We want the output to use `C` as
the self-type since we should get back an identified facet type that
says `C impls Z(.Self)`. But we do _not_ want to replace the `.Self`
there since we're inside a facet type and the `.Self` does not refer to
`C`. So we parameterize `TryToIdentifyFacetType` to not replace `.Self`
when identifying an `impls` constraint from the `where_stack()`. This
resolves a large number of `fail_todo_` tests.
2026-06-30 23:33:30 +00:00
Dana Jansens 8928268a95 Add script that pulls review stats from Github (#7444)
The script grabs all PRs and dumps them into CSV format
2026-06-30 23:11:46 +00:00
Dana Jansens a068806f67 Test and mitigate infinite cycles in impl lookup (#7428)
Impl lookup identifies the types of facets in the query, replacing
`.Self` in each type with the facet. This allows references using the
facet from outside the facet type to match similar structures inside the
facet type.

However replacing `.Self` with the facet can re-evaluate symbolic impl
lookups inside the facet type. These can perform deduction in generic
`final impl`s, which can attempt to convert the facet. Convert does an
impl lookup with that facet in the query, which causes us to form an
infinite recursion cycle.

Add tests that caused such a cycle, to demonstrate we no longer crash.
Some of these tests fail impl lookups using concrete values in the query
that match values from a `final impl`, with TODOs to address them.
2026-06-30 06:03:33 +00:00
Dana Jansens 7a7aefe486 Add a cargo_update.py script (#7431)
Our development instructions now recommend installing a number of
binaries through `cargo`. Updating these binaries has to be done by
hand. So we can provide a script that users can use to update them
easily and regularly.
2026-06-29 19:15:41 +00:00
Dana JansensandDavid Blaikie fb12984713 Forbid nested where inside a where expression through eval (#7397)
In #7378 we forbid writing `where` on the RHS of another `where`
expression. However it's still possible to inject a `where` expression
through eval, using an `alias` or an `eval fn`. We address this by
looking in the constant value of constraints of a `WhereExpr` (which
sees the outcome of eval) and searching for a nested `where` there. We
can determine a facet type was written with a nested `where` by seeing
that it has some non-extend constraint.

---------

Co-authored-by: David Blaikie <dblaikie@gmail.com>
2026-06-26 18:31:26 +00:00
Dana Jansens 5aae6a1ca5 Ensure a location for monomorphization diagnostics in call argument deduction (#7401)
If the deduction fails while forming the parameter type, ensure that we
print an actual diagnostic saying what went wrong.

And always ensure that an invalid array bounds error points at a
location. The `inst_id` given to `EvalConstantInst` always has a
location, but the `bounds_id` instruction inside it may be canonical
when it's coming from inside a larger type. So when it is, fall back to
using the location of the whole array inst.
2026-06-25 22:37:14 +00:00
Dana Jansens b22ee48c9b Forbid nested where inside a where expression (#7378)
This disallows building a facet type that contains another facet type
with non-extend constraints in it. Which in turn prevents the
possibility of introducing a different `.Self` into a facet type.

Eval can still insert a facet type with non-extend constraints, as we
only prevent it for `where` being written into the facet type. There is
a TODO in handle_where.cpp for this and some tests in
toolchain/check/testdata/facet/nested_facet_types_from_eval.carbon
2026-06-25 18:56:36 +00:00
Dana Jansens e2d32ab81c Don't crash on monomorphization failure when replacing .Self (#7400)
Depending on the order in which type completion identifies things in the
facet type, it may try to replace `.Self` with a facet that fails to
convert to the type of `.Self` due to a monomorphization error. We
should fail gracefully, not crash.
2026-06-24 13:50:59 +00:00
Dana Jansens 513b0c9e3b Support dumping ImportIRInstId from its printed id (#7398)
Add support to the dump command to `dump context import_ir_inst123`

Support for dumping the ids was previously added, but missed support for
parsing and creating a C++ id from its printed id.
2026-06-22 15:01:59 +00:00