This would save space for every `EntityName` that is not an imported C++
global variable.
C++ global variables include static data members.
Created `CppGlobalVarId`, `CppGlobalVarKey` and `CppGlobalVar` to allow
having `CanonicalValueStore` that maps `EntityNameId` (which is in
`CppGlobalVarKey` and `CppGlobalVar`) to `ClangDeclId` (which is also in
`CppGlobalVar`).
This is similar to `ClangDeclId`, `ClangDeclKey` and `ClangDecl` .
Rather than assume reallocations can occur, we've switched to providing
stable references, so simplify related code.
Only removing the comment in `BuildGeneric`, no refactoring, because I
don't feel a refactoring would be a significant improvement.
This demonstrates two issues:
1. It seems like we wrongly treat private static data members the same
way we treat protected and allow access to them from within derived
classes member functions.
2. Calling instance member functions of a base C++ class using a derived
class as self (no implicit upcast) is not yet supported. This isn't
related to access control, but prevents us from testing some access
control use cases.
Part of #5859.
SymbolicBindingType evaluates to the type component of a symbolic facet
value (a type/witnesses pair), and that symbolic facet value has its
constant value replaced by a specific. That specific can provide a
FacetValue, in which case it just evaluates to that FacetValue's type
component. It can provide a BindSymbolicName of another binding, in
which case it points to that entity instead and awaits a further
specific. Currently the code only handles these two cases, and they
match the behaviour of the evaluation of FacetAccessType itself.
However FacetAccessType evaluation also handles cases beyond these, as
there are other instructions that occur as facet values, such as
ImplWitnessAccess, when accessing an associated constant of an interface
that has a facet type as its type.
Currently eval then crashes in this scenario. Instead of furthering to
reproduce the contents of FacetAccessType's evaluation, defer to calling
the `EvalConstantInst()` overload for it when evaluating
SymbolicBindingType against a new value from a specific. This means
SymbolicBindingType can evaluate back into a FacetAccessType, when it
was originally a FacetAccessType(BindSymbolicName) and becomes
FacetAccessType(ImplWitnessAccess) through a specific.
This comes with a test that crashed in eval before this change.
In preparation for modeling `Optional(T*)` as a null pointer value.
With this PR, pointers remain non-nullable, but `MaybeUnformed(T*)` has
a particular unformed state that has the same representation as a C++
null pointer, which is accessible and detectable via builtins.
Fixes#5800 (flaky test timeouts under -c dbg), which were caused by
these death tests being extremely slow because they cause the symbolizer
to run on a large debug binary. Before this change, the test ran for
~30-90s depending on how long the symbolization happened to take; after
this change, it finishes in about 0.4s.
Using death tests here seems a bit excessive, especially as the process
dying in these cases isn't part of the contract of these functions, so
I'm just removing the death tests rather than trying to make them more
efficient. We have death tests in common/ that check our CARBON_CHECK
macros work.
Implemented by generalizing the reference type support for parameters
and return values to other use cases.
The changes to the `method.carbon` test are due to to supporting the
reference types but not supporting the necessary conversions.
C++ Interop Demo:
```c++
// global.h
struct C {
int member = 0;
int& member_ref = member;
};
extern C& global;
```
```c++
// global.cpp
#include "global.h"
static C static_c;
C& global= static_c;
```
```carbon
// main.carbon
library "Main";
import Core library "io";
import Cpp library "global.h";
fn Run() -> i32 {
Core.Print(Cpp.global->member);
++(*Cpp.global->member_ref);
Core.Print(Cpp.global->member);
++(*Cpp.global->member_ref);
Core.Print(Cpp.global->member);
return 0;
}
```
```shell
$ clang++ -stdlib=libc++ -c global.cpp
$ bazel build toolchain:carbon && bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link global.o main.o --output=demo
$ ./demo
0
1
2
```
**Without this change**:
```shell
main.carbon:10:14: error: semantics TODO: `Unsupported: var type: C &`
Core.Print(Cpp.global->member);
^~~~~~~~~~
main.carbon:10:14: note: in `Cpp` name lookup for `global`
Core.Print(Cpp.global->member);
^~~~~~~~~~
```
Part of #6006 and #6186.
The tests are almost identical and test the same logic so basically
duplicated.
The extra coverage that was in `struct.carbon` is added to
`class.carbon`.
One basic test in `struct.carbon` was left just to make sure `struct` is
supported.
Part of #5150.
This requires changing `ReturnSlotPattern` and `OutParamPattern`
definitions to use untyped node id, so they can have any associated
node.
Follow up of #5197.
Part of #5064.
Only update the canonical for itself if it has no value, otherwise a
"better" canonical was previously added and the chain will be followed
when deleting specifics.
A SymbolicBindingType is going to only have EntityNameId as its field,
and we will use the ScopeStack to use that to find a facet. The
ScopeStack is a check/ thing, so this won't be possible in
SemIR::TypeIterator. And TypeStructure throws away the details for
symbolic types anyways. So this drops the TODO and returns the
EntityName from TypeIterator for any future user who would want it in
check/.
When a pair of specifics is found to be equivalent, the current logic
would always remove the second one (j indexed) from further processing,
assuming that i was the canonical. That's not always the case, when the
j is the canonical, the i indexed specific should be the one removed.
Update logic to reflect that.
Adding testcase.
When we do member access `x.F` we attempt to look into the type of `x`
for `F`. If `x` is a facet, we look at its FacetType to find `F`. We
want `facet` and `facet as type` expressions to be generally treated as
equivalent, so we need to get at the "canonical facet value" of `x` in
order to look into its type. Add a new operation that allows us to
preserve the non-canonical `base_id` in the member access for
diagnostics if no conversion to a canonical facet value was needed.
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.
This change makes dumping and debugging work again with InstIds that are
now tagged with the CheckIRId. The textual representation of an InstId
is changed from `irN.instM` back to `instM` but the `M` is now a hex
value with the tag as part of it, which is the same number that is
physically in the `InstId::index` field. This prevents any cases where
we would potentially print incorrect values for large InstIds.
We teach the `dump` command in lldb to parse hex values for InstId so
that we can paste these numbers back into the debugger.
This fixes a bug, which seems to have been introduced in #6108.
In the new test, without this change, we will diagnose with
```
error: semantics TODO: `Unsupported: parameter type: ExplicitObjectParam` [SemanticsTodo]
```
This tests that `.Self` in an interface generic parameter preserves the
facet type information of the binding when returned, and allows compound
member lookup back into that interface.
And add a failing-todo test that `.Self` gets implied constraints which
can be satisfied through `&` for the facet type `I(.Self)` is part of.
This is a follow up of #6082, which added support for reference types,
but not for return types.
C++ Interop Demo:
```carbon
// main.carbon
library "Main";
import Core library "io";
import Cpp inline '''
struct C {
auto Inc() -> void { ++x; }
int x = 0;
};
auto GetC() -> C& {
static C c;
return c;
}
''';
fn Run() -> i32 {
Core.Print(Cpp.GetC()->x);
Cpp.GetC()->Inc();
Core.Print(Cpp.GetC()->x);
Cpp.GetC()->Inc();
Core.Print(Cpp.GetC()->x);
return 0;
}
```
```shell
$ bazel build toolchain:carbon && bazel-bin/toolchain/carbon compile main.carbon && bazel-bin/toolchain/carbon link main.o --output=demo && ./demo
0
1
2
```
**Without this change**:
```shell
main.carbon:19:14: error: semantics TODO: `Unsupported: return type: C &`
Core.Print(Cpp.GetC()->x);
^~~~~~~~~~
```
Part of #6148.
This allows to find the spaceship `operator<=>` when a comparison
operator is not available, and `operator==` when `operator!=` is not
available.
Support added to both lookup and overload resolution, by adding
`OperatorRewriteInfo` and propagating it in `CppOverloadSet`.
In case overload resolution chooses to use an operator which requires
rewriting, we emit a `TODO` since rewriting is not yet supported.
Part of #6170.
The `AppendLookupScopesForConstant` function had a special case for
`facet as type` which was overly broad (applying to all callers to the
function when only one caller needs it), and was confusingly overly
specific (applying to `facet as type` but not to `facet` constants).
We clarify all of this by moving it out to member access, and applying
it only to the case of looking into the type of `base_id`. In that case
we are doing member lookup into the facet itself, but since it's
symbolic we don't know the type to look into. And we don't defer the
lookup with a symbolic instruction, so we do the lookup into the facet's
type instead.
We add a helper function in member access, `ExtractFacetTypeForFacet` to
encapsulate this slightly-odd operation. It's odd because it ends up
getting *the type of the type* when the `base_id` has a facet as its
type.
The helper is now built on top of GetCanonicalFacetOrTypeValue() instead
of explicitly looking for FacetAccessType, which makes it work more
generally for any type instructions that represent a facet, including
SymbolicBindingType in the future.
While here document and improve clarity throughout the
`PerformActionHelper` for member access.
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)`.
Updates the documentation under `docs/design/` to use `ref` instead of
`addr` after their removal in #5434. Care was taken to manually clean up
edge cases and, in a couple cases, surrounding text (see
3d72c49bb75c0f40ca7e8114b6a1369b941e1697). After this change, there are
no matches for `addr(?!ess)` in `docs/design/`.
Closes#6032
When deducing an argument against a type that is `<facet value> as type`
we don't care about the `as type` part of that expression. We want to
find an argument that can convert to the `FacetType` of the facet value
for the generic binding that is the `<facet value>`.
This was done after-the-fact in the Deduce switch, but we move this
canonicalization step to be more explicit and done up front at the start
of the Deduce loop. This:
- Avoids a trip through the Deduce loop for a `FacetAccessType`
parameter, just to deduce through it in the switch, which avoids convert
and creation of extraneous constant values.
- Uses the `GetCanonicalFacetOrTypeValue()` function so that when we add
`SymbolicBindingType` handling to that function it will apply to Deduce
as well correctly, instead of needing to handle both in the switch.
Previously it performed two kinds of operations, with a boolean
parameter to control whether it would unwrap FacetValue or not. This
made the function hard to explain as "canonicalization".
Now the contract of GetCanonicalFacetOrTypeValue is as follows:
1. For a facet value expression, it returns the canonical value of the
facet value.
2. For a `<facet value> as type` it returns the canonical value of the
`<facet value>`.
3. For other type expressions, it returns the canonical value of the
type.
1 and 2 together collapse together two representations of a facet value
(as a FacetType or as a TypeType) into a single canonical value, which
is important for constant comparison of facet values where the `as type`
is not meant to change the result. This is the case in impl lookups and
`.Self` comparisons.
The step of unwrapping `FacetValue` is only useful in the constant
evaluation of `LookupImplWitness` and is used to collapse *symbolic*
queries on `FacetValue(T)` and on `T` down to a single canonical value,
since they produce the same result later when `T` is replaced with a
facet value or type that can provide a concrete witness. This is now
extensively documented in the constant evaluation of
`LookupImplWitness`.
This change came out of a request/discussion in #6115 (see comment
https://github.com/carbon-language/carbon-lang/pull/6115#discussion_r2383696576).
This fixes and tests two crashes related to what I was observing [on
#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1422723976483831848).
The approach to Cpp imports taken in #6086 is problematic because it
returns before the work stack is completed, and doesn't store the
resulting constants. This fixes the approach taken in that PR.
Use the `CheckIRId` as a unique identifier for the scope of an `InstId`
- if an `InstId` is created within the scope of one `CheckIRId` it must
not be used in the scope of a different `CheckIRId`.
This is achieved without extra storage, but with false negatives for
large inputs.
When an `InstId` is created, the original index of the `Inst` is XORed
with a tag derived from the `CheckIRId` to produce the final `InstId`.
When the `InstId` is used, the expected tag is XORed with the `InstId`
to get back to the original index - if the tags don't match, the
resulting index will be corrupted, likely too large - resulting in an
out of bounds index CHECK-failure.
(the tag value is derived as such:
* take the CheckIRId
* left shift one bit (padding zero)
* left shift another bit (padding 1 - used to signify that the resulting
`InstId` has a tag combined into it)
* reverse the bits
In this way, the tag is unlikely to overlap with the index for small
test cases - making it possible to separate out the `CheckIRId` from the
index in these cases to provide more meaningful debugging/CHECK
messages, and more informative `SemIR` textual dumping that can now
include the `CheckIRId` along with the `Inst`'s index in the name of an
`inst`)
The test churn here is improved printing as tagged `InstId`s can now,
with best effort (more likely for small test cases where the `CheckIRId`
and the `Inst` index aren't at risk of overlapping from the high and low
bits), render the `CheckIRId` as part of the inst's name. Going from
`instNN` to `irMM.instNN`.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
When doing impl lookup with a constraint facet type including the
builtin `TypeCanAggregateDestroy`, we look at the type to see if it
satisfies it. However if the type is a facet value, we need to look at
the FacetType to see if the eventual concrete type is going to satisfy
it.
Note that we can do this check up front in the `LookupImplWitness()`
function without creating a symbolic instruction to be modified by
future specifics with a more precise type for the facet value, because
the result of `TypeCanAggregateDestroy` does not actually provide a
witness, so we don't need the final specific type.
This was noticed by removing the "shortcut" in convert for converting a
`FacetAccessType(<symbolic binding>)` to `typeof(<symbolic binding>)`.
By removing the shortcut, we go into impl lookup when checking `impl`
decls containing `TypeCanAggregateDestroy` via deduce.
Before this change, we wrongly ignore the decision to generate a thunk
for a function with default args by overriding this decision with the
fact the return type by itself doesn't require a thunk.
This causes not generating a thunk which leads to crashing in lowering.
Add tests that show that now thunk is generated in `check` and it no
longer crashes in `lower`.
Follow up of #6108.