Commit Graph
13 Commits
Author SHA1 Message Date
Nicholas Bishop 3bb245364f Support exporting class specifics to C++ (#7634)
This is similar to the previously-added support for accessing generic
carbon classes from C++, but with the specific defined by Carbon, rather
than being derived from template args supplied by clang in
`LoadExternalSpecializations`.

Example:
```carbon
class C(T: type) {
  var t: T;
}
alias A = C(i32);

inline Cpp '''
void F() {
  Carbon::A a;
  a.t = 123;
}
'''
```
2026-08-13 23:30:24 +00:00
Christopher Di BellaandRichard Smith 4ea5ef45dd Skip ImplWitnessTable::elements_id when generating fingerprints (#7629)
Implementing interface modifiers causes an infinite loop when generating
fingerprints because the witness value generates a fingerprint that's
dependent on something dependent on the witness value. We've debugged
this to the witness table's `elements_id` field.

This hack is a workaround for creating a new block type whose value is
not codependent with its identity.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-08-11 22:39:30 +00:00
Nicholas Bishop 700e42a195 Simplify extra_name in ExportFunctionSpecializationToCpp (#7587)
Rather than appending to the thunk name for each template arg, use the
mangled form of the specific ID.
2026-08-10 15:09:58 +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
Geoff RomerandNicholas Bishop 3cb143e878 Add support for exporting Carbon functions as constructors. (#7560)
Co-authored-by: Nicholas Bishop <nbishop@nbishop.net>
2026-07-24 18:43:12 +00:00
Nicholas Bishop 2e61685658 Remove duplicate check for exporting a specific class (#7541)
The check for a specific in `TryMapClassType` is unnecessary;
immediately after it calls `ExportClassToCpp`, which has the same check.
The latter also has a `context.TODO`, which provides a clearer error.

Also improved the `LocId` in `ExportClassToCpp` to use the location of
the first decl rather than the empty location of the class type. This is
the same fix as
https://github.com/carbon-language/carbon-lang/pull/7533, just applied a
little more broadly. This makes the `context.TODO` above point at the
class rather than the start of the source file.
2026-07-21 18:35:20 +00:00
Nicholas Bishop 3a3439c681 Support exporting functions with generic return types to C++ (#7537)
Add a `return_type_id` field to `FunctionInfo` in
`toolchain/check/cpp/export.cpp`. As with the `explicit_params` field,
`ExportFunctionSpecializationToCpp` updates this to the return type in
the specific.

Refactored `BuildCppFunctionDeclForCarbonFn` into
`BuildCppFunctionDeclForNonGenericCarbonFn` and
`BuildCppFunctionDeclForGenericCarbonFn`, with `BuildCppFunctionDecl`
containing shared code.

The `generic_type_impls_interface.carbon` test is updated to include a
generic return type.
2026-07-20 20:44:58 +00:00
Nicholas Bishop 3d71858386 Improve type substitution in ExportFunctionSpecializationToCpp (#7495)
Instead of manually creating a map from symbolic types to concrete
types, create a Specific and look up parameter types via that Specific.

This allows C++ to call a Carbon function like `fn F[T: type](unused t:
T*) {}`. See generic_pointer.carbon.
2026-07-13 21:11:31 +00:00
Richard Smith a8afc45ed5 Omit empty observe: blocks from formatted SemIR. (#7487)
Also add SemIR ranges to observe test, removing 5K lines of
uninteresting SemIR output.
2026-07-13 20:38:19 +00:00
Chandler Carruth 8be274cf60 Replace :! binding syntax with phase keywords and contextual defaults (#7479)
Implement the toolchain side of proposal #7254, removing the `:!`
binding
syntax for generic and template parameters in favor of the keywords
`generic`,
`template`, and `runtime` plus contextual defaults for phase.

For valid programs this is semantics-preserving: each binding resolves
to the
same phase, and produces the same SemIR, as it did under `:!`/`:`. The
parser
derives a binding's phase from its syntactic context plus any explicit
phase
keyword; new diagnostics and error recovery for misused keywords are
described
below.

Implementation details for each component:

- Lexer: remove the `:!` (`ColonExclaim`) token, move its virtual
parse-node
  budget onto `:`, and add the `generic` and `runtime` keywords.
- Parser: thread a `BindingContext` (`ExplicitParam`, `DeducedParam`, or
`CompileTimeEntityParam`) from declaration introducers down through
parameter
lists to each binding pattern, using a one-token lookahead to
distinguish a
name-qualifier parameter list from a declaration's own final list.
Parameters
of a compile-time entity (`class`, `interface`, `constraint`, `choice`,
`alias`, `export`, `namespace`) and deduced `[]` parameters default to
checked
generic; explicit function parameters and local bindings default to
runtime.
`HandleBindingPattern` resolves the phase from that context plus the
keyword: a
`generic` keyword needs no node of its own (the phase is carried by the
  binding's node kind), while a `runtime` keyword is preserved as a
`RuntimeBindingName` node so `check` can name it in a diagnostic. A
phase
keyword that is merely redundant with the contextual default is
diagnosed
  here, without invalidating the parse tree.
- Check: a phase keyword that is invalid for its context (for example
`runtime`
on a checked-generic parameter) is diagnosed here, and recovers by
building an
error binding that still introduces the name so that later uses of it do
not
  produce cascading errors.

The removed `:!` syntax is now rejected as an ordinary parse error.

The `form`/`:?`/`->?` ("extended types") portion of proposal #7254 is
left for a
separate change.

Assisted-by: Claude Code
2026-07-11 01:22:44 +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
Özgür T. ÖnsoyandDana Jansens 08385adeb5 Implement checking observe declarations (#6709)
This adds SemIR structs and implements building `observe` lists, as well
as naming, formatting, and importing `observe` declarations.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-07-08 17:07:10 +00:00
Nicholas Bishop c8fdeef911 Add initial support for exporting generic Carbon functions to C++ (#7462)
This allows C++ to call Carbon functions with generic type parameters,
with some conditions. Example:
```carbon
interface I {
  fn Doit(self);
}
class A {
  impl as I { fn Doit(unused self) {} }
}
class B {
  impl as I { fn Doit(unused self) {} }
}
fn F[T:! I](t: T) {
  t.Doit();
}

inline Cpp '''
void G() {
  Carbon::A a;
  Carbon::B b;
  Carbon::F(a);
  Carbon::F(b);
}
''';
```

The initial support is limited; only explicit parameters are handled
currently.

`CarbonExternalASTSource::GetOrExportFunctionToCpp` now generates a
`clang::FunctionTemplateDecl` for generic Carbon functions. If C++ code
attempts to call that templated function,
`CarbonExternalASTSource::LoadExternalSpecializations` will be called
with the template argument types of that call site. Then we can generate
a specialized thunk for those argument types for C++ to call.
2026-07-08 00:51:21 +00:00