Commit Graph
18 Commits
Author SHA1 Message Date
Jon Ross-Perkins 8779b8f64b Replace pending generic logic with work stack-based logic (#6404)
This continues work to eliminate pending generics/specifics and get them
to be interleaved with instruction imports. I'm trying to use
`FinishGenericOrDone` here as a way to help ensure that code correctly
handles generics, where the simple alternative would be for each
`TryResolveTypedInst` call `SetGenericData` directly (but which might
make it easier to call the wrong `ResolveResult` function, and we do
need the `GenericId`s to be passed).
2025-11-20 01:02:18 +00:00
Richard Smith 0678501038 Replace builtin CppVoidType with a prelude type. (#6403)
Following #6357, map C++ `void` to a prelude class type
`Core.CppCompat.VoidBase`, not to a builtin type. This is mostly just
moving logic around, but does notably change `Cpp.void` from being an
incomplete type to being a complete-but-abstract type.

Also change `NullptrT` to be an adapter for `void*` instead of `()*`, to
follow the approved design.

Implicit conversions to `void` and to `void*` are still absent.

Part of #6280.
2025-11-19 20:40:17 +00:00
Geoff Romer 2b8fdf3417 Switch the prelude to use ref instead of addr (#6359) 2025-11-14 00:40:26 +00:00
Richard Smith 86b02ee8af Interop support for nullptr and nullptr_t. (#6353)
Add a `Core.CppCompat.NullptrT` type that C++'s `nullptr_t` maps into.
Map `nullptr` to an uninitialized constant of that type -- `nullptr`
doesn't actually have any defined bits within it, despite having the
same representation as `void*`.
2025-11-12 23:23:48 +00:00
Richard Smith 8f19f7a7c0 Use the value representation of T as that of MaybeUnformed(T) where possible (#6334)
If the value representation of `T` is a copy representation, but it
copies all of the bits of `T`'s object representation, then it's OK to
use that as the value representation of `MaybeUnformed(T)` too.

This fixes the behavior of interop with nullable pointers, which are
represented as an adapter of `MaybeUnformed(T*)`, and need to be passed
to and returned from functions on the Carbon / C++ boundary as `T*`s.
2025-11-07 16:25:27 +00:00
Richard Smith 5db1141f52 Allow adding / removing const with ImplicitAs. (#6323)
If `T` implicitly converts to `U`, then:

 * `const T` implicitly converts to `U`,
 * `T` implicitly converts to `const U`, and
 * `T` implicitly converts to `Optional(U)`.
2025-11-05 07:38:09 +00:00
Geoff Romer 0811d996e1 Finish renaming BindName and related insts. (#6281)
Resolves the TODO from #6235
2025-10-28 17:17:38 +00:00
Richard Smith a1a35c207e Unify "needs thunk" logic. (#6277)
Remove duplication between determining whether a parameter needs custom
thunk mapping and whether a function needs a thunk. Now a function needs
a thunk if any parameter or the return type does.

This fixes some inconsistencies; previously:
- We would not require a thunk when passing an `unsigned int`, but if we
  had a thunk we'd pass `unsigned int` indirectly.
- We would always require a thunk for an enum parameter, even though
  we'd actually pass it directly if its underlying type is a 32- or
  64-bit integer.
- We would require a thunk for a nullable pointer, even though
  we arrange for all pointer types to have the same ABI in Carbon and
  C++, including nullable pointers / Optional(T*).

This also causes us to use a thunk for rvalue reference return types,
which we used to miscompile.

Depends on #6276.
2025-10-27 22:49:29 +00:00
Geoff Romer 09710d102f Separate binding insts for refs and values (#6235)
This resolves a TODO in `expr_info.cpp` by using the inst kind rather
than the bound value to track the binding's category.

Since we're churning all the `bind_name` insts in testdata anyway, I'm
also taking this opportunity to align the inst naming with the design's
terminology, by calling these insts "bindings" (this aspect of the PR is
dependent on #6231 resolving an ambiguity in that terminology). For
consistency we'll need to rename several other insts as well (see the
TODO on `RefBinding`); I'm deferring that to a separate PR to minimize
the review load, but I think those name changes are in-scope for this
review.
2025-10-23 01:46:24 +00:00
Richard Smith 304d2056cc Map nullable C++ pointer types to Core.Optional(T*). (#6230) 2025-10-16 20:52:32 +00:00
Dana Jansens e682a6660d Avoid adding extraneous local instructions while importing witness table entries (#6180)
When deducing arguments for generic parameters of an `impl`, the
deduction calls `Convert` on the input arguments. Often, the input
argument is a facet, and needs to be converted to a type via
FacetAccessType in order to produce a different facet. These
instructions end up being added to the semir, but only their constant
values are needed for the resulting specific returned from Deduce.

In the best case, these extra instructions are just noise in the semir,
or they just cause instruction names to get differentiated with larger
suffixes.

In the worst case, these extra instructions contain references to
instructions from a generic context, and leak them out of that generic
context and into another. In particular, when importing a
LookupImplWitness instruction, the re-evaluation of it can do deduce
(when the lookup is against a generic `impl`). The instructions created
in Deduce are not part of the import, and end up referring to imported
instructions from the local context, which leads to confusion in the
toolchain, and can crash.

The `import_self_specific.carbon` test demonstrates this. It causes the
`I.F` function to be imported from the `I` interface when building the
witness table for the `impl`. Doing so imports the specific of `C` which
includes a LookupImplWitness for `Self.Accoc` in `I`. The `Self` is a
BindSymbolicName with generic binding index 0, in `I`. When Convert
creates instructions in the generic `impl forall D`, however, they end
up referencing and including this BindSymbolicName into its eval block.
But the generic binding 0 in the `impl` is a very different thing (a
value of type `E`). This confusion leads to crashes.
2025-10-09 16:07:30 +00:00
Dana Jansens fe020ee08b Make FacetAccessType evaluate to SymbolicBindingType for type-of a BindSymbolicName (#6115)
The SymbolicBindingType refers to the type value that will be
substituted in for the BindSymbolicName, but holds onto the EntityNameId
from the BindSymbolicName instead of (or in addition to, for now) the
instruction.

The EntityNameId will be used to look in the ScopeStack to find the
witnesses either from the BindSymbolicName instruction, or other
instructions that specify `impls` constraints against the EntityName.

This will allow us to have the `T` in `I(T)` resolve to a `.Self`
reference in the type so that we get type equality with the binding's
type: `T:! I(.Self)`.
2025-10-06 18:56:43 +00:00
Boaz Brickner 5f561282eb Properly set the name for C++ overload set instructions in SemIR (#6156)
This is a followup of #5891.
Part of #5915.
2025-10-06 07:36:28 +00:00
Boaz Brickner 16999a79cc Fix a crash caused by a bug introduced in C++ overloads support in GetScopeIdOffset() (#6151)
After this change, we correctly increment the offset by the next switch
case type.
Before this change, we accidentally incremented the offset by
`functions()` size instead of `cpp_overload_sets()` size and vice versa.
Also sorted the switch cases according to the order of the enum, for
consistency. This might help prevent a future similar incident.

This fix prevents crashing in the newly introduced test
`multiple_too_few_args_calls`.

This also has the side effect of showing `null name` for
`cpp_overload_set_type` and `cpp_overload_set_value`, instead of having
an arbitrary name.
Examples that demonstrate the old name is arbitrary can easily be seen
in tests like `cpp_namespace.carbon` and `decayed_param.carbon`, but
careful review would show that all old names are arbitrary, though often
luckily almost make sense.

We might want to have a proper name for these, but it's beyond the scope
of this crash fixing change.
See #6156.

Part of #5915.
2025-10-02 14:34:34 +00:00
Ivana Ivanovska a24598f069 Lower CppOverloadSetValue (#6101)
Following up on comments from
[#5891](https://github.com/carbon-language/carbon-lang/pull/5891) ([
1](https://github.com/carbon-language/carbon-lang/pull/5891#discussion_r2317244981),
[2](https://github.com/carbon-language/carbon-lang/pull/5891#discussion_r2317266756)).

Lowering `CppOverloadSetValue` as an empty struct value, using
`context.GetLiteralAsValue()`. Also changed its constant kind to
`InstConstantKind::Always`.

Part of https://github.com/carbon-language/carbon-lang/issues/5915
2025-10-01 16:25:05 +00:00
Jon Ross-Perkins 4a6376cf59 Rename/restructure Destroy logic to better reflect #6124 (#6144)
This also does a little restructuring in the same direction, following
#6124.

Leads want `Destroy` to work similarly now for all types. As a
consequence, there doesn't seem to be as much benefit to splitting off
aggregate destruction. In this PR, the `type.destroy` function can now
be expected to destroy anything that's destructible; that means it'll be
usable for the `final fn` once that support is available.

Similarly, this gets rid of the impls other than the single blanket
impl, now using `type.can_destroy`. Since they all need to use the same
function, there's no benefit to splitting approaches. Also, now it can
just be a `final impl` since there should be no need for people to
create specializations -- if this blanket impl applies, it means the
`final fn` is the same.

This also slips in `partial` support since there's no reason to have it
diverge anymore. Also `abstract`, which I'm not sure is broadly testable
since most cases it'd come up, the `abstract` keyword is explicitly
detected/rejected.

Note though that this doesn't make any really big changes. It's just
realigning on the leads decision. I'm going this way to try to reduce
name-related churn for other changes.
2025-09-30 20:43:36 +00:00
Jon Ross-Perkins 47081be67a Reduce test sensitivity to small import loc changes (#6145)
Locations are similarly fragile, because adding a comment changes them.
This has made me pause when making prelude changes in #6144, so dropping
them for those cases.

Instruction ids aren't actually that interesting outside debugging, and
can be churny when doing other structural changes. I've seen this in
particular when doing singleton changes, which bump every instruction
id.

Note there are still other ways fragility from locations can crop up.
This shouldn't be considered a complete fix, but hopefully a small
improvement.
2025-09-30 17:20:14 +00:00
Richard SmithandJon Ross-Perkins 1e7b7e53ae C++ interop: support for default arguments. (#6108)
The general strategy here is to force use of a thunk when we want to use
default arguments, and have Clang generate uses of the default arguments
on its side of the thunk.

To support this, change the key type used in `clang_decls` from being
just a `Decl*` to being a pair of `Decl*` and number of parameters in
the case of function decls. Import distinct `SemIR::Function`s for each
number of parameters that's used, and corresponding distinct thunks.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-09-24 01:07:59 +00:00