Use TypeInstId in many more places where the instruction is required
to/known to always be a type value. This should be a somewhat exhaustive
set of places, as it covers all instructions given to
GetTypeIdFromTypeInstId().
The things of interest here are:
- Singleton instructions are always of type TypeType, so they are now
TypeInstIds.
- ErrorInst::SingletonInstId gets upcast to be an InstId because it's
sometimes used to define the type of a variable (as in `auto inst_id =
SemIR::ErrorInst::SingletonInstId;` that may hold other InstIds.
- Parse nodes don't really know about TypeInstId, so NodeStack::Push
needs to do some special casing to avoid CHECK failures when given a
TypeInstId but expecting an InstId. We leave a TODO behind here because
the nodes which are being pushed a TypeInstId should probably be taught
to expect that, but such a change is a bit tricky, so too much for this
PR.
This allows us to import the table for a given impl only once, while we
can import many ImplWitness instructions with different specifics for a
generic impl.
For example in convert_facet_value_to_narrowed_facet_type.carbon we see
that a single witness table is imported for the BitAnd interface, with
multiple witnesses (for different specifics) imported and sharing the
same table.
The ImplWitnessTable now contains a back-link to the Impl the witness is
for, allowing inst namer to name that interface in the textual semir,
and allowing the interface to be found when debugging from a witness.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
After #5280 there are a few more typed instructions that have an `InstId
type_inst_id` that always holds a type value. These are converted to
`TypeInstId` to encode this fact in the type system. The
`ConvertAggregateElement()` function in convert.cpp is now able to
receive `TypeInstId` for a couple arguments as well.
Additionally, the `type_inst_id` field of `StructTypeField` is made into
a `TypeInstId`.
The `TupleType::elements_id` is renamed to `TupleType::type_elements_id`
to try record the fact that it's an InstBlock of type value
instructions. We don't introduce a TypeInstBlockId at this time, but it
might be nice to make blocks of TypeInstIds in the future.
To assist in working with a block of InstId that are type values, two
additional helpers are added to the TypeStore:
- GetBlockAsTypeInstIds which turns an `ArrayRef<InstId>` into a range
of `TypeInstId`
- GetBlockAsTypeIds which turns an `ArrayRef<InstId>` into a range of
`TypeId`
We use these helpers in places that iterate over the
`TupleType::type_elements_id`.
Rules executed by bazel don't necessarily have the right environment to
find the symbolizer, which was the intent of `cc_env` setting
`LLVM_SYMBOLIZER_PATH`. So far, this has kind of been a case-by-case
fix, but every so often I'm trying to debug a crash in a test that
doesn't provide it. Rather continuing down this route, instead add
drop-in wrappers for cc rules so that it's hard to forget.
Note `bazel/cc_rules` is intended to mirror `bazel/carbon_rules` and
`bazel/cc_toolchains`, rather than `@rules_cc`.
AFAICT there isn't a great way to add this as a default for the `bazel
run` environment. It's not typically going to be set on its own,
forwarding `$PATH` would be too broad, and the [action
`env_sets`](https://bazel.build/docs/cc-toolchain-config-reference#using-action-config)
I think are not quite what we need (I think those don't include output
execution, only compilation).
References were removed by #5287, #5291, and #5292; this is just
deleting the directories themselves.
Note this does not change anything else (e.g. removing things in
MODULE.bazel that were only used by explorer). I'm trying to make a pure
delete that's easy to review.
The main goal of this is to collapse the LocId and SemIRLoc types into a
single type, eliminating the need for APIs to decide which to use. This
originated from discussion about UnwrapSemIRLoc in #5169. Although that
was removed in #5202, it's probably still a good direction for LocId.
This changes the packing of LocId to allow adding InstId, making it
tri-modal: ImportIRInstId, InstId, or NodeId. This has a side-effect of
reducing the available space for ImportIRInstId, although not by much
due to the pre-existing `ImplicitBit` behavior. If needed, we could also
probably play with packing a bit more since `ImplicitBit` really only
applies to `NodeId`, but I was trying to keep the logic a little
simpler. Note `TokenOnlyBit` can still apply to `ImportIRInstId`.
This leaves in place a typedef for SemIRLoc -- I intend to clean that up
separately.
Some Discord discussion is
[here](https://discord.com/channels/655572317891461132/655578254970716160/1353755830058745959).
TypeInstId is an InstId whose constant value has a type of TypeType.
This includes:
- Type value instructions, the `ClassType` or `IntLiteralType`
instructions.
- Constraint value instructions, which are the `FacetType` and
`TypeType` instructions, each of which also have type TypeType.
TypeInstId encodes in the type system that it is safe to convert the
instruction's value to a TypeId, and CHECKs at construction that this
invariant is maintained.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
I'm doing this separately from removing the explorer/ and installers/
directories so that it's easier to review the side-effects.
Note for the main README, I didn't think it was worth keeping a mention
of "used to have a prototype interpreter, now archived" versus focusing
on the existing toolchain (for "Currently, we have fleshed out").
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
In preparation for shifting from `TypeId`s potentially representing
attached types to always representing unattached types, using
[terminology suggested on
Discord](https://discord.com/channels/655572317891461132/963846118964350976/1359286326779973712).
This change causes us to track slightly more type spelling information
through SemIR.
One change that has significant impact on the SemIR output is that we
now build a `struct_type` instruction in each class representing the
types of the fields, including the spelling used for those types. This
is now no longer always identical to the corresponding canonical
`struct_type` for the object representation, so it's built separately
and owned by the class.
Also remove `TypeBlock` support entirely, as its only use was
representing `TupleType`s, which now use an `InstBlock`.
Use it to stringify associated constant values in diagnostics. In
passing, add missing support for stringifying bool literals. Note that
there are some cases that it doesn't stringify properly, but that's not
new here; such cases could already be observed when stringifying generic
arguments.
While facets may come with a rewrite for an associated constant, they
are symbolic. A final impl has the ability to provide a concrete value
instead, which allows generic code to use the concrete value in place of
the associated constant's (fully qualified) name.
For instance, instead of `I.Type`, the concrete type `()` can be used if
there is an `impl final [T:! type] T as I where .Type = ()` impl.
This does not yet cache the result of the lookups.
Depends on https://github.com/carbon-language/carbon-lang/pull/5255
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This follows the pattern used elsewhere, and allows facet types in eval
blocks to directly reference their operands instead of doing so
indirectly via a `ConstantId` attached to the generic. This prepares us
for making `ConstantId`s always be unattached.
In passing, add a stringified version of the `InstId` to diagnostics in
a couple of places where it seems useful.
Unintentionally, we were adding ImplWitnessAssociatedConstant to the
witness table and then immediately evaluting and replacing it with its
constant value instruction, which is incorrect. The point of the
instruction is to be a symbolic value in the witness table that is a
dependent of the generic impl declaration being built.
This is trying to document the status quo. Note
https://github.com/carbon-language/carbon-lang/pull/4497 placed
restrictions on a bit, and this is in part flowing back to restrictions
on both NodeId and ImportIRInstId limits.
Reuse LLVM global constants: do not generate a new llvm::Global constant
for a pointer to a global constant for the same Carbon const_inst_id,
reuse already generated one.
The explorer is an archived codebase, without a plan to restart
development on it. The costs incurred by keeping it in the main git repo
can be alleviated by moving it to a new sibling repo, without
diminishing the usefulness of the explorer codebase for demonstrating
implementation of the carbon language design.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This gives a slightly simpler representation for `UnboundElementType`s
in eval blocks, and in principle allows us to preserve the spelling of a
field's type into the `UnboundElementType` and thereby into a field
reference, although as of right now this doesn't affect our diagnostic
output in any way.
During error recovery for a field with a non-concrete type, preserve the
type in the `UnboundElementType` regardless. It's not really problematic
to have a non-concrete type there, and this makes it easier to track the
instruction used to specify the type.
This is a step towards switching symbolic types to always be abstract
during type checking.
Use that instead of `AddInstInNoBlock` to get the value of an
instruction when evaluation might depend on the `InstId` but only the
`ConstantId` of the instruction is desired by the consumer.
Instead of using None, use an explicit ImplWitnessTablePlaceholder in
the witness table for entries that have not yet been populated, to aid
debugging. This would ensure they would show up very clearly in the
SemIR. This uncovered some `<invalid>` in the SemIR under erroneous
conditions that have now been turned into `<error>`.
Add the ImplWitnessAssociatedConstant instruction which wraps the
canonical instruction found from the constant value of the rewrite
constraint. This ensures that we have an instruction inside the eval
block for a generic impl declaration for each rewrite constraint's
value, which allows Subst to be performed to rewrite the symbolic
constant of the ImplWitnessAssociatedConstant instruction to associate
it with the generic. This will prevent the otherwise orphaned symbolic
constant of the rewrite's value from being used which can not have a
specific applied to them.
While applying the new insts in InitialFacetTypeImplWitness(), rearrange
the function to use less nesting. And avoid using entity names from
imported instructions (as we found is not effective in deduce.cpp) and
use a local instruction by going through the constant value.
This PR is part of the effort to allow a rewrite to name a generic
parameter, such as `impl forall [T:! type] T as Z where .X = T`, however
tests for this involve a final impl so that we can typecheck that the .X
value is a specific T, so the tests will come with that work. This piece
is split off because introducing new instructions causes a lot of SemIR
churn, and I wanted to get that done separately.
For each kind of instruction, specify whether its constant evaluation
needs an `InstId` or not. If it does, ensure that all constant
evaluation of that instruction provides one. Otherwise, allow calling
into the evaluator without providing an `InstId`.
This allows us to reliably use the `InstId` in evaluation steps that
either need a location or need to look at the original operands of the
instruction prior to evaluation, and also to support `TryEvalInst` calls
safely for instructions whose evaluation does not need an `InstId`.
Instead of storing a `TypeId` that always refer to a facet type that
always contains exactly a single interface, store the interface
directly.
Also improve stringification of `LookupImplWitness` and witness access
into it, switching to using newly-added functionality for stringifying
specific interfaces.
Adds a mapping to keep track of vtable LLVM IR decls/defs for use.
Adds the vtable_id to the vtable_ptr initialize instruction for lookup.
Adds emission of vtable declarations for use outside the file that
defines the vtable. (this isn't done lazily, it's done for any imported
class - it could be done lazily & maybe eventually has to be lazy to
handle generics)
Also renames variables of that type to match. A follow-up PR will rename
`Parse::StateStackEntry` to `Parse::State`. This is more consistent with
the naming of similar enums elsewhere in the toolchain, and with the
prevailing practice of using `state` rather than e.g. `entry` as the
name of a `StateStackEntry`.
See also discussion
[here](https://discord.com/channels/655572317891461132/963846118964350976/1326280585592700990)
Some minor code health improvements discovered by clang-tidy:
* avoid copying; use const reference
* harmonize parameter names
* use more efficient absl::StrSplit-by-character
(Note: this is *not* anything related to April 1st.)
Proposal to switch our week-to-week Carbon project development syncs to
be more
async.
- Start of each week, create a summary of what happened last week.
- Publish this in GitHub discussions for async reading and further
discussion.
- Stop our weekly meeting focused on these summaries.
- Start up a new discussion meetings every two months.
- Structure will be a 10-minutes-or-less update, and a "demo".
- Demo may be traditional: showcase a newly landed thing in Carbon.
- Or demo may showcase an interesting top-of-mind language design
discussion.
- Either way, goal will be to field lots of questions about the topic
and
have a good discussion everyone understands, not to reach some
"conclusion" or "decision".
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Perhaps we will disallow member lookup on and conversion of runtime
facet values. For now, leave a TODO and produce a TODO diagnostic
instead of crashing.
Related to #5241.
Each of these types takes another type as an operand. Instead of storing
that other type as a `TypeId`, store it as an `InstId` so that we can
track how it was written, not only its canonical form.
The canonical constant values of these types continue to store the
canonical constant values of their operands, as normal.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>