This splits off the functionality to handle the base facet type,
rewrites, and impls constraints into separate functions.
We use the Context instead of EvalContext throughout, as the goal is to
move this code to EvalConstantInst in time. That means we do not apply
specifics to the functions in the requirements inst block. That is fine
because WhereExpr never evaluates to an WhereExpr, so this instruction
never survives as a constant value long enough to be re-evaluated with a
specific applied to it.
Use the same C++ -> Carbon map for both interop directions, and when
importing an entity from Carbon -> C++, check whether it was originally
a C++ entity and if so return the original.
Assisted-by: Gemini via Google Antigravity
This is already allowed as a builtin conversion, but the impl allows the
generics system to know about it, so that conversions like
`Optional(T*)` to `Optional(const T*)` are allowed. This in turn allows
a C++ `T*` to be implicitly converted to a C++ `const T*` in Carbon
code.
Fix some situations where we'd drop the storage argument when building
an in-place initializing expression. We now guarantee that an expression
with the in-place initializing category always has a storage argument.
Instead of recursing back into Convert, make CppThunkRef conversion just
add an extra step to category conversion, performing a copy conversion
followed by an ephemeral reference binding conversion.
This is only fixing the decision about *whether* to produce a witness.
Implementation of the witness is still a TODO, though where a body is
generated, it should also precisely reflect where one _needs_ to be
generated.
Note the tests:
- toolchain/lower/testdata/function/generic/import_core_witness.carbon
- toolchain/lower/testdata/function/generic/import_unused_def.carbon
These tests can probably be produced _without_ Core.Destroy, but I found
the essence of them while trying to build //examples with Core.Destroy
and a simpler minimization wasn't striking me.
Assisted-by: Google Antigravity with Gemini
---------
Co-authored-by: jonmeow <jperkins@google.com>
Remove special-case handling in conversion logic for C++ enum types,
synthesize a custom witness of `Core.Copy` using the `primitive_copy`
builtin function.
This makes it possible to do const eval when calling a constexpr C++
function with params and return types other than 32/64-bit integers.
Most of the new logic is in `MaybeModifyCppThunkCallForConstEval`, which
is called by `MakeConstantForCall`. This checks if the callee is a C++
thunk (using a new `SpecialFunctionKind::CppThunk` variant), and if so
it:
* Changes the callee from the C++ thunk to the thunk's callee
* Remaps parameters that are passed by pointer to the thunk to the
underlying value
* Drops the return value parameter, if present
For #6830, add support for inline C++ fragments as a declaration rather
than as a packaging directive. For now, this uses `inline Cpp
<string-literal>;` as syntax. The prior `import Cpp inline
<string-literal>;` is left alone for the time being. We can decide
separately whether to remove that.
`inline Cpp` requires that there was at least one `import Cpp`. It's not
clear to me if that's the right design long-term, but it seems
reasonable for now.
Assisted-by: Gemini via Google Antigravity
This will be used for const-evaling functions. Splitting into a separate
commit since it touches a lot of test files, and a couple fail_todo
tests are no longer failing.
Tests combinations of extend and impls in a facet type and inside a
named constraint. Name scopes are only extended if the named constraint
extends an interface, and the facet type extends the named constraint.
When parsing a pattern, if we encounter something that isn't pattern
syntax, try parsing as an expression instead. We only need one-token
lookahead to distinguish pattern syntax from expression syntax.
Track a precedence group through pattern parsing so that we can allow
different kinds of expressions in a top-level pattern (such as the
operand of `let`) and in a nested pattern (such as a subpattern of a
tuple pattern or within grouping parens). For example, we do not allow
`case if ...`, and for now I've chosen to also not allow logical or
relational operators at the top level of a pattern, so `case 1 + 1` is
OK, but `case 1 == 1` and `case true and false` require parentheses.
This decision should be ratified or revisited by a design proposal.
Very basic check support is also provided, only sufficient to form an
`ExprPattern` instruction and nothing beyond that. For now, all pattern
matching against an `ExprPattern` fails with a TODO error. To support
that, I've switched from calling `BeginSubpattern` in the parent handler
of a pattern and `EndSubpatternAs*` in the pattern handler itself to
calling both functions in parent handlers, with `EndSubpattern`
converting an expression into an expression pattern where needed.
Depends on #6976.
Assisted-by: Gemini via Google Antigravity
Do not treat it as a 1-tuple pattern as we used to. The design indicates
that `(pattern)` is invalid, but this appears to be an oversight, and
grouping parens appear to be the intended interpretation.
---------
Co-authored-by: Geoff Romer <gromer@google.com>
This removes some loops in type completion, but is motivated by the
thought that eval probably wants to query it.
Assisted-by: Google Antigravity with Gemini
EvalOrAddInst has to create a non-canonical instruction for evaluating a
few typed insts, such as LookupImplWitness which uses an InstId to
provide a location for diagnostics.
But the output of the function is a ConstantId. We do not have access to
the non-canonical InstId after the function returns. But if the constant
value was symbolic, it was being attached to the inst, and the inst
would be added to the eval block of the enclosing generic. This
needlessly added semir for a symbolic value.
The ConstantId returned by EvalOrAddInst can be used immediately, such
as to evaluate an ImplWitnessAccess. In that case, the final evaluated
result is all we need to keep in semir.
If the ConstantId needs to be replaced by specifics, it is only as part
of some other instruction, since ConstantIds themselves are not modified
by specifics, instructions are. In that case, the canonical instruction
in the constant value would have been added to some other (now symbolic)
instruction, which would be replaced by a specific.
This has no functional change, but it reduces runtime overhead and semir
output for LookupImplWitness and ImplWitnessAccess.
Performing a lookup against `Self` inside the definition of the named
constraint leads to cycles, as described in the document [Self
contradictions in Named
Constraints](https://docs.google.com/document/d/17rn2XmME8o2MM4OJqatSVuMa1iYZ1PAgcNrf0PXR9Q4/edit?tab=t.0).
To prevent those cycles, this change introduces a large refactoring of
impl lookup.
The impl lookup done inside eval is reduced to only performing
monomorphization. That is it:
- Only looks for an provides final witnesses.
- Is not allowed to identify the facet type of the query self.
- Returns either a final witness or None (or an error)
The paths for finding non-final witnesses are now done outside of eval,
directly in the initial `LookupImplWitness()` function. If no final
witness it found through eval, the resulting non-final
`LookupImplWitness` instruction witness is returned. It does not produce
cycles to identify the facet type of query self outside of eval, since
that does not result in repeating the identification when resolving
specifics of the named constraint or require decl.
Move the ArrayStack for Context::require_impls_stack into a new class
which tracks a NamedConstraintId (or InterfaceId) for each frame of
RequireImplsIds, so that in type completion we always can find the
correct frame for a given named constraint which is still being defined,
in order to find the RequireImplsIds in the in-progress definition.
Ignore storage arguments when evaluating a call, like we do for other
kinds of instruction. Create a placeholder constant to represent each
out parameter so that it can be used in the function body to form more
storage arguments.
Assisted-by: Gemini 3.1 Pro via Antigravity
Start recording the clang::DeclContext* -> InstId mapping for use in
later operations.
The test update includes removing the initial fail_* test because I
hadn't thought about the use of namespace aliases as a way to test for
the presence of a namespace without the failure caused by not finding
the thing inside the namespace.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Initialize the `Diag` field `EvalResult` to get notes from clang when
`EvaluateAsConstantExpr` fails, then emit them using clang's diagnostic
infrastructure.
Also set valid source locations in a couple places, otherwise clang's
diagnostics code crashes.
The diagnostic requires bit widths to be multiples of 8, but the test
used a mask of 3 (lower two bits), which only enforces multiples of 4.
Use a mask of 7 so values like 12 incorrectly pass the check.
Adding a library to lower the odds of tripping someone up in the future
(I don't plan to modify this file now)
Assisted-by: Google Antigravity with Gemini
This commit creates an instance for any associated types in an interface
with a custom witness table. This unlocks interfaces designed for C++
interop that rely on arbitrary return types. For example,
`CppUnsafeDeref` becomes usable as of this commit.
This commit may have also implemented support for non-type associated
constants, but since we're lacking a practical test case, they're still
marked as TODO for the time being.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
The `CompleteTypeWitness` can be concrete. This avoids making a symbolic
`CompleteTypeWitness` value which itself has a concrete
`CompleteTypeWitness` value with the same operands.
Instead of injecting code to declare an `operator new`, generate AST for
it directly. In order to use this, directly generate a `CXXNewExpr`
rather than asking Clang to build one.
This is less of a hack, and doesn't visibly leak an `operator new`
declaration that inline C++ code or template instantiations might see.
It also avoids generating a warning in C++26 and later that the
`constexpr` declaration of `operator new` is used but not defined.
Assisted-by: Gemini 3.1 Pro via Antigravity
This enables some nice simplifications, and it's also a step toward a
broader restructuring of binding and parameter patterns.
Assisted-by: Gemini 3.1 Pro via Antigravity
When a `var` is not explicitly given an initializer, initialize it in
one of two ways:
* If its type implements the new interface `Core.Default`, call
`Core.Default.Op` to initialize it.
* Otherwise, if its type implements `UnformedInit`, leave it in an
unformed state. For now, this is always an uninitialized state, but that
will change in the future.
* If neither of those apply, the `var` declaration is ill-formed.
This is a step towards implementing leads decision #6739 and proposals
#257 and #5913.
Assisted-by: Gemini 3.1 Pro via Antigravity
---------
Co-authored-by: Geoff Romer <gromer@google.com>
`LookupCppImpl` handles exactly one function ID, so core interfaces with
multiple associated entities were regarded as unsupported. This commit
adds support for a single associated function with a single associated
constant.
Note: associated constants are still TODO.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
This resolves some todos, and makes `Convert` safer to call, which
unblocks some changes in pattern matching that I'm working on.
Assisted-by: Gemini 3.1 Pro via Antigravity
This moves the LValue path code from macros.cpp to constant.cpp, so that
it can be called from `MapAPValueToConstant`. TODO messages are updated
accordingly to avoid referring to macros. Added a constexpr pointer test
to `constexpr.carbon` to show the result of this change.
Add a clang::ExternalASTSource to begin exposing Carbon entities to
Clang - initially only a single `Carbon` top level namespace.
Subsequent work will add Carbon entities to this namespace.
Likely this CarbonExternalASTSource will be refactored into another
file, tie into/reference SemIR::File and CppFile, etc eventually - but
that'll wait for future patches.
If there's mechanical problems with the current implementation - how I'm
creating the new NamespaceDecl, etc - I'm all ears. It's very much in
the "it seems to work" state, not much more than that.
This does break Clang Modules (header modules, C++20 modules,
precompiled headers, etc) since they're implemented as an
ExternalASTSource as well, and Clang's ASTContext only supports one
ExternalASTSource at a time. To fix that regression we'll need to
implement some kind of ExternalASTSource multiplexing support - either
in Clang or Carbon (unclear which).
This regression of modules support can be observed by the following:
`A.h`
```
inline void f1() { }
```
`module.modulemap`
```
module A {
header "A.h"
export *
}
```
`test.carbon`
```
import Cpp inline '''
// Hardcode the pragma to ensure this isn't silently falling back to
// textual inclusion.
void f2() {
f1();
}
''';
```
```
carbon compile test.carbon -- -I . -fmodules -fimplicit-modules -fmodules-cache-path=module_cache
```
I wrote a `file_test` test for this, but it doesn't /quite/ work because
`file_test` provides an in-memory filesystem for tests to make them more
hermetic, but Clang's Filesystem abstrtaction is for reading only - so
the module that's written out successfully can't be found when it needs
to be read back in - so the test doesn't pass as a baseline. Clang does
have support for `llvm::vfs::OutputBackend` which allows virtualizing
output - which I guess we could tie together with the InMemoryFilesystem
we use for input to make such a test work. But I guess that's not worth
the effort here?
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Using a named constraint inside itself is problematic:
- If there were not require decls written above, it identifies as an
empty set. This makes `Z(Self)` essentially disappear in the identified
facet type, which produces "no use of Self" diagnostics while the user
can see a use of Self in the code.
- It won't include require decls that are written after, and so `require
T impls Z` won't actually enforce that `T` impls all of `Z`.
Previously this was an error because using the named constraint would
require it to be identified, and it's not identified until it is
complete. But this will change in proposal #6902. So that proposal also
includes changes to preserve diagnostics for incorrect use of a named
constraint before it's complete, which is implemented here.
Discussed in open discussion [on
2026-03-12](https://docs.google.com/document/d/1mjllGO3ZCL4qGt9uJHUtcxKoHAGEY7Y999ie4EtBWB8/edit?tab=t.0#heading=h.1dvbbrp5a6t3).
The new tests exposed a bug where we're not copying named constraints in
a facet type on the RHS of `where .Self impls` into the facet type on
the left, which is now fixed. The
`fail_require_impls_incomplete_self_in_period_self_impls.carbon` test
would not diagnose its error without this fix.
This is so that the last file is more likely what we're trying to
compile in tests. Just splitting out the churn-y change of reordering.
Assisted-by: Google Antigravity with Gemini
Iterators, smart pointers, optional, and expected types depend on
`operator*`. This commit adds `CppUnsafeDeref` as a core interface, with
an associated function, so that the compiler can dereference
user-defined C++ types.
Things not implemented in this commit:
* `operator*` overload resolution
* SemIR lowering
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Use the object parameter type when creating a reference to the thunk
parameter so that we create an xvalue rather than an lvalue for the
`*this` expression in the thunk.