Commit Graph
3069 Commits
Author SHA1 Message Date
Nicholas Bishop bd918fb33b Parse vars in classes the same as vars in other locations (#7188)
Class vars are still restricted to simple `name: type` bindings, not
full patterns. This is now handled in the check phase instead of during
parsing.

This is in preparation for supporting `static var`.
2026-05-13 21:22:46 +00:00
Dana Jansens 5706601096 Replace .Self in the self type of T(.Self) impls NamedConstraint when identifying a facet type (#7204)
Given this example function:

```carbon
fn F(T:! Z where .Self imps Y(.Self) and E(.Self) impls X(.Self)) {
  T as Y(T);
  E(T) as X(T);
}
```

When we identify the facet type of `T`, we replace `.Self` with `T`.
However in the initial loop, the self _is_ `T` so we don't want to
substitute `.Self` instances inside `T` with itself, as that creates
cycles.

When we see a `type impls...` constraint such as `E(.Self)` we now have
a different self-type so we can, and want to, substitute the `.Self` in
it with `T`. This was already being done, unless the RHS of the `impls`
was a named constraint. In that case we forgot that we were in a `type
impls...` constraint, and avoided replacing `.Self`. Now the algorithm
remembers and correctly replaces `.Self` for `type impls named
constraint` constraints in a facet type.
2026-05-13 18:49:02 +00:00
Dana Jansens 77f1d93369 Avoid replacing .Self in designators more robustly in rewrite constraints (#7202)
When replacing `.Self` in a facet type we don't want to destroy the
structure of designators in rewrite constraints so that rewrite
constraint resolution and other similar code can still find them. We
were doing this only for the LHS, and for the RHS if it was a standalone
designator, like `.X = .Y` but we want to do this more robustly to also
avoid rewrite the `.Self` in `.Y` in the expression `.X = C(.Y)`. This
allows resolution, and ImplWitnessAccess to recognize the designator and
replace the `.Y` with the RHS value of another rewrite constraint
assigning to `.Y`.
2026-05-13 18:24:31 +00:00
Richard Smith 917856aff7 Export Carbon classes as base / final / abstract. (#7191)
* For Carbon `base class C`, export as a regular C++ class.
* For Carbon `class C`, export with the C++ `final` keyword attribute.
* For Carbon `abstract C`, mark the destructor as pure virtual in cases
where no member function is abstract, or emit an error if the destructor
is not virtual.

To support the final point, mark the destructor of an exported class as
virtual if it overrides a virtual destructor from the base class.

In passing, fix a crash exporting fields if the class has an invalid
base type.
2026-05-13 17:48:55 +00:00
Richard Smith c33fb9fc48 Support signature mismatch between virtual fn and override fn. (#7198)
For now, hide `override fn`s from name lookup, so that the base class
version is always used, as the derived-class version does not have its
own vptr entry and so would not do the right thing if a further-derived
class adds a new override. This is implemented via a new access kind of
`Hidden`.

When checking the overriding function, pass in the expected `Self` type
and check the `self` parameter against that; the signature that we
generate for the thunk in the derived class is the base class signature
with the `self` parameter's type changed to the derived class.

When we generate a thunk for a virtual function, the thunk is assigned a
`virtual_index`, and the virtual function itself is not. When the thunk
makes a direct call to the virtual function, recognize this situation by
checking for a `virtual_index`, and perform a non-virtual call if there
isn't one.

Assisted-by: Gemini via Antigravity
2026-05-13 17:40:45 +00:00
Dana Jansens 0b47efa57a Don't re-require complete types for extended scopes (#7194)
When an outer type defines an `extend` relationship to an inner type, we
require that inner type to be complete so that we can know that name
lookup can search both scopes as soon as the outer type is complete.

When doing name lookup, we require the type in which we are looking to
be complete. Then, we recursively add extended scopes, but then also
require each of them to be complete again, which inserts
RequireCompleteType instructions into the block doing lookup.

While these new instructions may differ in terms of their specifics,
they are redundant since we already required the type to be complete,
and specifics can not change the completeness of a type. They are also
problematic because a named constraint or interface can extend a scope
with a symbolic specific, by using `Self` as an argument. This inserts a
symbolic instruction into the block doing name lookup, even though that
block may not be generic.
2026-05-13 17:16:02 +00:00
Dana JansensandRichard Smith 6326bbdbe1 Resolve cycles in .Self replacement in nested designators (#7183)
A nested designator like `.(X.X1).(Y.Y1)` results in nested
ImplWitnessAccess instructions, which can produce cycles in the
toolchain easily when replacing `.Self`.

First, when constructing a facet type like `V:! Z where .Z1 impls (Y
where .Y1 = U)` we substitute replace `.Self` in the nested facet type,
and in this case we replace `.Self` with `.Z1` which contains a `.Self`
of its own. This was coming from us being lazy about replacing `.Self`
in an `impl as` declaration, such as `impl C as Z where .Z1 = .Self`.
The self type is known there, so we can more eagerly replace `.Self` as
we do in a `require impls` declaration. Then the replacement for `.Self`
never comes with a `.Self` that needs to also be replaced. Any resulting
`.Self` would always be the top-level one.

Second, when evaluating ImplWitnessAccess, we were replacing .Self in
the LHS of rewrite constraints, but the `.Self` may itself have a type
that contains rewrite constraints. If one of those rewrite constraints
has nested ImplWitnessAccess instructions, we evaluate the new
ImplWitnessAccess, which again finds rewrite constraints to replace
`.Self` in, and we repeat forever. For this one we just stop replacing
.Self in the LHS of rewrite constraints. Since they are always against
.Self, we can always look in the access facet's type for a value.

While fixing ImplWitness access, also correct the lookup to search
through the types of nested ImplWitnessAccess instructions to find a
rewrite value, since it may find it at any level up to the eventual
`.Self`.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-13 16:11:20 +00:00
Richard Smith 798b177fc0 Tidy up virtual method tests. (#7196)
Move the tests from `class/` to `class/method` and add SemIR dump
ranges.
2026-05-13 13:58:14 +00:00
Richard Smith 71ba07239f Support pass-by-move when calling a C++ function taking by value. (#7135)
Previously, we picked a single Carbon parameter pattern for each C++
parameter pattern. This doesn't work well in cases where the Carbon
semantics and the C++ semantics are not perfectly aligned. In
particular, when a parameter is passed by value in C++, that might mean
either pass-by-move (which in Carbon would best be modeled by a `var`
pattern, as no other form of parameter would perform a move) or
pass-by-copy (which in Carbon would best be modeled by a value
parameter, as a `var` parameter would force an extra copy).

After this change, we compute a passing mode for each parameter based on
the implicit conversion sequence from the argument to the parameter as
determined by C++ overload resolution, and use that to determine the
Carbon pattern corresponding to each C++ parameter. This results in
potentially generating multiple different thunks for the same C++
function if it's called in different ways, but we already did that to
handle default arguments and list-initialization. The passing modes are
included in the thunk mangling.

Add a new value store for clang decl signatures, which capture the
information about parameter passing mode as well as the other existing
information about different ways that a C++ function might be imported
to Carbon.

Most of the rules for computing passing modes are the same as before:
const references use pass by value, non-const lvalue references use
pass-by-ref, non-const rvalue references use pass-by-var. But for C++
non-reference parameters, pick between pass-by-value and pass-by-var
based on whether the implicit conversion sequence was effectively
performing a copy. Prefer pass-by-value if either would work and they'd
do the same thing. We still use pass-by-value for const references, even
when the argument is an lvalue and we could pass a reference; we may
want to change this in future.

For virtual functions, we try to pick a worst-case passing mode, as we
can only pick a single signature for what goes in the vtable. Calls to
virtual functions will still use a thunk to C++, allowing variance in
the calling convention at call sites. We don't allow variance in the
overriders as we don't implement support for thunks for virtual
functions yet. We currently use pass-by-value for const reference
parameters here, but that should probably change at some point.

Assisted-by: Gemini via Antigravity
2026-05-13 01:44:07 +00:00
Dana Jansens 71eed5b04a Add tests that demonstrate missing diagnostics for impl as a named constraint (#7195)
Any non-extend require decls must be satisfied when the impl definition
starts, but they are not checked. We only check for require decls in the
target interface being impld.
2026-05-12 22:15:09 +00:00
Christopher Di BellaandRichard Smith 2aaa061688 Support detecting begin()/end() methods for range-for loops (#7185)
This commit adds support for range-based for loops using C++ types. It's
currently limited to detecting that `r.begin()` and `r.end()` are
available. We should be able to add full support for methods after #7181
is merged.

Support for ADL is still a work-in-progress, and will be added at a
later time.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-12 19:03:55 +00:00
Richard Smith dd7cfdb149 Relax alias restrictions. (#7190)
Implement the alias rules from proposal #5389, wherein an alias is
permitted so long as the target has a constant value. While that
proposal is not yet accepted, this seems like a reasonable basis for
further iteration, and will be useful for the examples we're currently
pursuing.
2026-05-12 17:22:44 +00:00
Dana Jansens d4063cad65 Remove completed TODO in import test (#7193)
The generic args are now in the stringified name
2026-05-12 17:02:57 +00:00
Chandler CarruthandDana Jansens b5a1688c85 Add check/dump.cpp functions for the new ones in sem_ir (#7126)
Also cleans up redundant code in the `sem_ir` dump methods that I missed
initially. Now we share as much logic as we can for dumping the non-ID
and ID components.

Assisted-by: Antigravity with Gemini

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-05-11 18:22:31 +00:00
David Blaikie df8b25522e Import C++ vtables (#7174)
This correctly renders the vtable in SemIR, including allowing overrides
in
Carbon-derived-from-C++ classes.

It doesn't work in lowering because clang walks the methods of the
CXXRecordDecl - and we currently don't export anything into the
CXXRecordDecl's methods (we do export the fields) - so that's next.

This also doesn't teach Clang to affirmatively emit the vtable
regardless of the types use in C++ code - or to have Carbon use the
vtable in an object's initialization.
2026-05-11 17:33:08 +00:00
David Blaikie 0f5de499d6 Roundtrip (export/reimport) class declarations (#7182)
Roundtrip (export/reimport) class declarations

The remapping was previously implemented using name_scopes, which aren't
created for class declarations, only definitions - causing the reimport
to import a fresh copy of the type that mismatched with the original (as
seen in the test baseline).

By changing the mapping to use the reverse part of the clang_decls
mapping this should generalize better (& we probably should further
migrate to that mapping). Though it did trip over some issue with
exactly which instruction is used as the key in the clang_decls map -
this change moves towards standardizing on the first decl id of the
class as its map key.
2026-05-11 16:35:47 +00:00
Dana Jansens eea1e58376 Correctly handle ImplWitnessAccess in impl lookup (#7181)
We were treating ImplWitnessAccess as a concrete type, but that is
incorrect if its accessing a symbolic type value. This results in
concrete impl lookup queries failing to match a generic impl that is
built with a symbolic ImplWitnessAccess in its type structure, when the
query does not have the equivalent ImplWitnessAccess in its own type
structure.

We need to look in the top level facet being accessed through
ImplWitnessAccess for witnesses, such as in `T:! Z where .Z1 impls Y`
where `T` provides the witness for `T.Z1 as Y`. But we also need to look
in the facet type of the ImplWitnessAccess for witnesses, such as in
`T:! Z` for `interface Z { let Z1:! Y }`, where `T.Z1` provides the
witness for `T.Z1 as Y`.

To support that we give TypeIterator an iteration step for
ImplWitnessAccess before recursing into it, like we do for FacetValue.

While doing this, we make TypeIterator more recursive, by making less
special casing around the step from one inst into the next. Instead of
eagerly finding a SymbolicType, we consistently recurse back into the
big switch statement and have it decide the next iteration step. This
allows it to recurse into instructions like ImplWitnessAccess and
FacetValue in a consistent manner.
2026-05-11 14:17:18 +00:00
Christopher Di Bella 219d1cdee1 Teach comparison interfaces about C++ operators (#7163) 2026-05-10 21:54:50 +00:00
Viktor 8d907e857e Add regression test for var parameter cleanup from struct literals (#7175)
`param.carbon` already tests cleanup when passing a class value produced
by
`C.Make()` to a `var` parameter. Add the corresponding struct literal
case,
`F({})`, matching the repro from #7168

The issue appears to already be fixed on main so this adds a test to
make sure
the compiler keeps calling `Core.Destroy` for the temporary value after
`F({})`
returns

Closes #7168

Assisted-by: Qwen 3.6
2026-05-08 19:13:52 +00:00
Lucile Rose Nihlen bc1ae703c3 return 0 from Run when it doesn't specify a return value (#7180)
https://carbon.compiler-explorer.com/z/88K9Kh5Wo shows the program
exiting with a garbage value copied from uninitialized memory.

This PR modifies `lower` to detect if the function lowered is the
entry point and doesn't specify a return type. If so, it emits
different LLVM IR to return int32 0, and modifies the lowered
function signature to match the int32 return type.
2026-05-08 19:00:47 +00:00
Christopher Di Bella 3e36f7d43c Replace manual CoreInterface tables with x-macros (#7176)
Manually filling out tables involving `CoreInterface` is error-prone,
especially when switching on strings, which the compiler can't warn on.
2026-05-08 05:47:38 +00:00
Dana Jansens a19a6ab6d1 Search all facets in the impl lookup query for witnesses (#7178)
This enables searching facets like `T:! Z where .Z1 impls Y` for queries
like `T.Z1 as Y`, etc.

Any facet in the query self or the query target type may provide a
witness for the requirements of the impl lookup, so search through them
all.

We accept partially identified facet types in the query self, since
`Self` can be used inside a named constraint before it's fully
identified. But any use of `Self` being converted would put it in the
query self, not the query target, which would be some generic parameter
facet type that a type involving `Self` is being converted to.

TypeIterator is expanded to support this use case, by giving it the
ability to walk through FacetType's extend/impls constraints. We return
the facet values that we find in the iterator instead of a type id. And
we also include FacetValue instructions as an iterator step for clients
that want them, while also recursing through them.
2026-05-07 22:33:47 +00:00
Richard Smith bc06f6c5ec Mangle the signature decl when mangling a thunk. (#7177)
Fixes mangling collisions when two thunks with the same name (eg, `Op`)
are created in the same context, which in turn would lead to LLVM
verifier failures and miscompiles.

To support this, add a new value store to track a little more
information about thunks beyond what's in the `Function`.
2026-05-07 21:58:29 +00:00
Geoff Romer 031ec0a140 Implement BundleStore (#7173)
See
[here](https://docs.google.com/document/d/1eWW8MTko3PIqxZ32-GhsdaRSYqoDicxMB1VeessMTOg/edit?tab=t.0#heading=h.igl2myxbaf58)
for the background and design. The only usage of `BundleStore` in this
PR is artificial, but I'm working on a PR involving an action inst with
3 arguments, which requires something like `BundleStore`.
2026-05-07 19:42:23 +00:00
Dana Jansens 6776e2b804 Detect impl redecls in non-declarative scopes (#7170)
Avoid crashing on the fact that block scopes have no related InstId. So
we can't push the InstId of the current scope in the ImplIntroducer
node, as it can be None. Instead we have to find the parent InstId when
we're building the ImplDecl, because the ImplDecl has a node at the top
of the scope stack for the DeclNameStack.

Impls are allowed in sequential (non-declarative) scopes (functions,
blocks), but [redeclarations are not
allowed](https://github.com/carbon-language/carbon-lang/blob/db24042fe56d22275aa801696e2f8f5c4171e35b/proposals/p3763.md?plain=1#L279).
We now diagnose these redecls as invalid.
2026-05-07 13:44:40 +00:00
Geoff Romer daebbf32fa Restructure ArgAndKind as a type-safe generic ID. (#7172)
The key changes here are:
- Relocating and renaming it to align with `IdKind` (and relocating
`ToRaw` and `FromRaw` to follow it).
- Adding a `Dispatch` method that provides a generic overload-based API
for expressing per-ID-kind dispatch, and rewriting existing code to use
it.

Note in particular that using overloads instead of switch cases makes it
possible to generically handle all specializations of a templated ID
type, e.g. `SomeIdType<T>` for all `T`. We have no such templated ID
types yet, but I'm introducing one in a follow-up PR that needs this
capability.
2026-05-07 00:13:52 +00:00
Dana Jansens db24042fe5 Diagnose overlapping impls in the api/impl files of the same library (#7164)
An `impl` decl in an impl file can refer only to things defined in the
api file, without the orphan rule rejecting it. If they are in different
scopes (such as one being in a class and one not), then they are treated
as separate `impl` decls. But if they have the same type structure, then
they fully overlap which is an error unless they are in a match_first
block.

This catches the overlap when two `impl` decls are in the same library
but are split between the api and the impl file of the library.
Previously we only diagnosed if they were in the same _file_ but now we
diagnose if they are in the same _library_.
2026-05-06 14:17:54 +00:00
Richard Smith 341901e337 Fix crash if an inst in a pending block needs a cleanup. (#7166)
Insert the cleanup if and when the pending block is inserted, not
eagerly. And if the pending block is inserted by overwriting an existing
instruction, create a cleanup for that instruction rather than for the
instruction in the pending block that we are discarding.

Assisted-by: Gemini via Antigravity
2026-05-04 21:50:13 +00:00
Nicholas Bishop 1bc329af14 Support calling Carbon destructors from C++ (#7143)
A destructor is added to the C++ class definition in
`CarbonExternalASTSource::CompleteType`. The destructor calls a Carbon
function that calls the `Destroy` operator.
2026-05-04 20:28:58 +00:00
Dana Jansens f8dd4d85bf Do not treat impls in different scopes as redeclarations (#7161)
An impl in a different scope, with the same parameters, will overlap and
get diagnosed for that later by the [prioritization
rule](https://docs.carbon-lang.dev/docs/design/generics/details.html#prioritization-rule),
if they are not in a match_first block. But they are not considered as
redeclarations.

See [proposal
p5366](https://github.com/carbon-language/carbon-lang/blob/62b94f79322039acc3fc8e175896a64a32df470e/proposals/p5366.md)
for the rule.
2026-05-04 19:11:51 +00:00
Dana Jansens 4d1a61de29 Don't consider designators in a nested facet type as constraining the current type (#7139)
The design says:
> We don’t allow a where constraint unless it applies a restriction to
the current type. This means referring to some
[designator](https://docs.carbon-lang.dev/docs/design/generics/details.html#kinds-of-where-constraints),
like .MemberName, or
[.Self](https://docs.carbon-lang.dev/docs/design/generics/details.html#recursive-constraints).
--
https://docs.carbon-lang.dev/docs/design/generics/details.html#constraints-must-use-a-designator

A nested facet type in a constraint does not constrain the current type,
with the exception of the LHS of a nested `where` in an impls
constraint. Diagnose this appropriately by not recursing into unrelated
parts of nested facet types to look for designators.

Before this change, this facet type is accepted:
```carbon
fn F(unused T:! Z where C impls (Y where .Y1 = .Y2)) {}
```

But then no calls to `F` work, since the `.Y1` and `.Y2` designators are
never resolved to anything from the caller, as they do not depend on `T`
in any way.
2026-05-04 16:42:06 +00:00
Dana Jansens 4819e68dac Make choice to replace only implicit .Self or all into a parameter of SubstPeriodSelfCallbacks (#7133)
This avoids the need for a virtual method, and a class overriding it in
eval.
2026-05-04 14:52:00 +00:00
Dana Jansens 88931a4196 Give the .Self instruction a location (#7147)
This lets us stop eliding it in textual semir tests with dump ranges.
Previously it would always get elided, even though it was part of the
range being dumped, and was referred to by other instructions in the
dump range.

Since each `.Self` is unique (can change its type if not its value) in a
facet type, having each one distinct by location also aids
understanding.
2026-05-04 14:45:06 +00:00
Richard Smith b784900305 Simplify struct literal pop loop. (#7158)
Assisted-by: Gemini via Antigravity
2026-05-02 01:09:50 +00:00
David Blaikie 071ab9f532 Import dynamic-ness of a C++ class (#7141) 2026-05-01 22:53:44 +00:00
Richard Smith b5877d8afa Factor out definition merging logic. (#7154)
Move logic to merge class and function definitions onto Class and
Function, matching how we handle merging for EntityWithParamsBase.

Assisted-by: Gemini via Antigravity
2026-05-01 22:45:22 +00:00
Dana Jansens 46bb0fecd4 Properly diagnose ambiguous .Self in T impls X where... (#7132)
A `where` expression nested inside a `T impls X` constraint makes
`.Self` ambiguous on the right-hand side of the `where` if `T` is
anything other than `.Self`. After the `where`, the value of a `.Self`
could be `T` or could be the value of `.Self` before the `impls`
constraint: the so-called top-level value of `.Self`.

Implicit use of `.Self` in designators is always allowed, and they are
bound (and replaced by a reference) to the inner-most possible value of
`.Self`. On the right-hand side of the nested `where` above, they have
the value `T as X`.

`.Self impls ...` is also always allowed, since it acts more as a
keyword here, and it always refers to the inner-most possible value of
`.Self`.

Any other explicit use of `.Self` is diagnosed when ambiguous, in any
kind of constraint. This is done in the handling of `WhereExpr` since it
has enough context to allow `.Self impls` (which is an explicit use)
while disallowing other explicit uses. And because it has non-canonical
instructions to work with, so it is able to diagnose errors with precise
locations.

Since `.Self` is no longer going to be marked with depth modifiers, the
eval of `WhereExpr` does not need an input facet value instruction
representing `.Self` to compare with, as they are now going to all be
equivalent. So revert it back to just looking for the `PeriodSelf` name
id, through a shared helper being introduced as `IsPeriodSelf`. And drop
the period self InstId from the `WhereExpr` instruction. This causes
most of the formatted SemIR changes.

Move helpers for working with and replacing `.Self` to their own file,
out of the `facet_type.h` header/cpp files. These are working with
`.Self` facet values more than facet types, though `.Self` is a name
that only exists inside the scope of a facet type.
2026-05-01 21:22:32 +00:00
Richard Smith 0fcbe7c6b5 Remove redundant call. (#7156)
Assisted-by: Gemini via Antigravity
2026-05-01 19:53:16 +00:00
Dana Jansens 63c1f1e44e Add a colon to the dump output for IdentifiedFacetType (#7150)
Put a colon after `impls` to make it a bit easier to read.

Before:
```
identified_facet_type50000000
  - self: concrete_constant(inst50000023): {kind: ClassType, arg0: class50000004, arg1: specific<none>, type: type(TypeType)}
    impls interface50000000: {name: name0, parent_scope: name_scope0, require_impls_block_id: require_block_empty} `Z`
```

After:
```
identified_facet_type50000000
  - self: concrete_constant(inst50000023): {kind: ClassType, arg0: class50000004, arg1: specific<none>, type: type(TypeType)}
    impls: interface50000000: {name: name0, parent_scope: name_scope0, require_impls_block_id: require_block_empty} `Z`
```
2026-05-01 18:48:59 +00:00
Richard Smith ab409a6a71 Simplify type check. (#7155)
Assisted-by: Gemini via Antigravity
2026-05-01 18:46:52 +00:00
Richard Smith aebd7f9d7f Simplify logic a little. (#7153)
Also preserve the error state rather than overriding it, though this
doesn't seem to make a difference in practice.

Assisted-by: Gemini via Antigravity
2026-05-01 18:41:33 +00:00
Christopher Di BellaandDana Jansens 62b94f7932 reduces how many SpecificIds a custom witness generates (#6961)
The removed TODO warned that we'd end up with O(n^2) witness table
entries per specific. This isn't a problem for a single associated
function but will cause issues for larger custom witnesses.

This commit generates at most two `SpecificId`s with an inner `Self`:
one for associated constants and one for associated functions.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-04-30 20:27:20 +00:00
Nicholas Bishop 2445ad9703 Prevent ref self methods from being called from C++ with an rvalue (#7130)
If the Carbon method takes a `ref self`, give the C++ thunk an lvalue
ref-qualifier.
2026-04-30 00:50:28 +00:00
Nicholas Bishop f3f039516e Support accessing Carbon class fields from C++ (#7119)
When any field of a Carbon class is access from C++ for the first time,
all fields are exported as `clang::FieldDecl`s (this is necessary
because clang fields have an internal index that is initialized on first
use).

`ClangDeclStore` now provides bidirectional mapping. This allows looking
up a `ClangDeclId` by `InstId`, so when Carbon class fields are exported
they can be looked up that way.
2026-04-29 20:07:10 +00:00
Geoff Romer bd6aeae9d4 Don't require ref tags in thunks (#7115)
This enables thunking to work when the function has `ref` parameters,
without jumping through hoops to add `ref` tags in the desugared
function body.

This also renames `is_operator_syntax` to `is_desugared`, which is more
general and more accurate.
2026-04-29 18:33:53 +00:00
Geoff Romer 4c9049346d Replace form insts with actions (#7100)
See
[here](https://docs.google.com/document/d/1rWcueFwIfZox6GKVGxiUG4cBzjrZ6djXiIDGyJDtrE4/edit?tab=t.0)
for the design doc.

This also removes the default value of the `result_type_inst_id`
parameter of `HandleAction`, moves it before the action in the parameter
list, and documents it. This solves two problems:
- The default made it easy to forget, leading to unnecessary
`TypeOfInst` instructions.
- When it was present, putting it after the fairly "bulky" action
argument tended to make the callsite harder to read.
2026-04-29 18:13:42 +00:00
Richard Smith 0124aae041 Import non-const rvalue references as var parameters. (#7125)
When importing a C++ function with an rvalue reference parameter, we
previously produced a Carbon value parameter. This would lead to the
toolchain believing it could pass the address of a non-expiring object
to the function, which would lead to a use-after-move.

Instead, we now map non-const rvalue reference parameters to Carbon
`var` parameters. This forces the object passed into C++ to be unique
and owned by the call. While that's not an exact match for C++ rvalue
reference parameters, given that it provides "always move" not
"conditionally move", it's the closest match we have at the moment.
2026-04-29 00:28:00 +00:00
Richard Smith ab0aff91b8 Support indirect imports of namespaces. (#7122)
When a namespace that was imported from C++ is indirectly imported, find
the corresponding namespace in the current C++ AST and return that
instead. This namespace may have completely different contents than the
one we found before; that's fine. The current file's view of a namespace
depends on what it imported.

Assisted-by: Gemini via Antigravity
2026-04-28 23:55:18 +00:00
Richard Smith 23339bc810 Fix initialization of var parameters. (#7023)
When an initializing expression is used to initialize a var parameter,
we need to create the storage earlier in SemIR than the initializing
expression. To do so, pass a pending block to initialization containing
the var storage.

Also stop using `temporary` for this purpose, since we treat temporaries
as potentially-constant and immutable, but `var` parameters can be
mutated by the callee. We should ideally introduce a new kind of
instruction for this purpose but for now we just use `var_storage`.
2026-04-28 20:10:13 +00:00
Richard Smith 51e843d904 Suppress some clang-tidy false positives (#7131)
This gets us back to being mostly clang-tidy clean. This turns out to be
important for agentic coding agents, which otherwise sometimes try to
"fix" these false-positive lints.

Assisted-by: Gemini via Antigravity
2026-04-28 18:20:37 +00:00