mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 19:51:09 +01:00
This is reducing ValueStore inference of types from `using`, and removes `using ValueType = ...` from affected id types. I'm adding a number of `using FooStore = ValueStore<FooId, Foo>` because I think it's a little repetitive otherwise; often 4 cases where I'm doing this: getter, const getter, member, and getter on `Context`. Note we also have a number of `-> decltype(auto)` that were added I think mainly to avoid repeating the type, but I'm not sure whether there'll be agreement on replacing those and so am not changing them here. I'm placing these aliases with the value type in general, because I think it's probably easier to view that way. An alternative would be to put all the types on `File`, but: - That would be inconsistent with things like `InstStore`, which are very `ValueStore`-adjacent and put with their value type. - `File` would have a _lot_ of using's, and the accessors are already noisy -- I think it would just make the file harder to skim. Note this is the heart of what I'd brought up [on Discord](https://discord.com/channels/655572317891461132/655578254970716160/1388199282250613019). This PR still leaves CanonicalValueStore and BlockValueStore as things to also add parameters to, but I thought it best to try breaking the set of changes apart by type. Both of those rely on ValueStore, so ValueStore needs to change first.
124 lines
4.2 KiB
C++
124 lines
4.2 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_SEM_IR_CLASS_H_
|
|
#define CARBON_TOOLCHAIN_SEM_IR_CLASS_H_
|
|
|
|
#include "toolchain/base/value_store.h"
|
|
#include "toolchain/sem_ir/entity_with_params_base.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::SemIR {
|
|
|
|
// Class-specific fields.
|
|
struct ClassFields {
|
|
enum InheritanceKind : int8_t {
|
|
// `abstract class`
|
|
Abstract,
|
|
// `base class`
|
|
Base,
|
|
// `class`
|
|
Final,
|
|
};
|
|
|
|
// The following members always have values, and do not change throughout the
|
|
// lifetime of the class.
|
|
|
|
// The class type, which is the type of `Self` in the class definition.
|
|
TypeId self_type_id;
|
|
// The kind of inheritance that this class supports.
|
|
// TODO: The rules here are not yet decided. See #3384.
|
|
InheritanceKind inheritance_kind;
|
|
|
|
// Whether this class or any base class has at least one virtual function.
|
|
bool is_dynamic = false;
|
|
|
|
// The following members are set at the `{` of the class definition.
|
|
|
|
// The class scope.
|
|
NameScopeId scope_id = NameScopeId::None;
|
|
// The first block of the class body.
|
|
// TODO: Handle control flow in the class body, such as if-expressions.
|
|
InstBlockId body_block_id = InstBlockId::None;
|
|
|
|
// The following members are accumulated throughout the class definition.
|
|
|
|
// The adapted type declaration, if any. `None` if the class is not an
|
|
// adapter. This is an AdaptDecl instruction.
|
|
// TODO: Consider sharing the storage for `adapt_id` and `base_id`. A class
|
|
// can't have both.
|
|
InstId adapt_id = InstId::None;
|
|
// The base class declaration. `None` if the class has no base class. This is
|
|
// a BaseDecl instruction.
|
|
InstId base_id = InstId::None;
|
|
|
|
// The following members are set at the `}` of the class definition.
|
|
|
|
// A `CompleteTypeWitness` instruction witnessing that this class type is
|
|
// complete, and tracking its object representation. This has a value once the
|
|
// class is defined. For an adapter, the object representation is the
|
|
// non-adapter type that this class directly or transitively adapts.
|
|
InstId complete_type_witness_id = InstId::None;
|
|
|
|
// The virtual function table. `None` if the class has no (direct or
|
|
// inherited) virtual functions.
|
|
InstId vtable_ptr_id = InstId::None;
|
|
|
|
auto PrintClassFields(llvm::raw_ostream& out) const -> void {
|
|
out << "self_type_id: " << self_type_id << ", inheritance_kind: ";
|
|
switch (inheritance_kind) {
|
|
case Abstract:
|
|
out << "Abstract";
|
|
break;
|
|
case Base:
|
|
out << "Base";
|
|
break;
|
|
case Final:
|
|
out << "Final";
|
|
break;
|
|
}
|
|
out << ", is_dynamic: " << is_dynamic << ", scope_id: " << scope_id
|
|
<< ", body_block_id: " << body_block_id << ", adapt_id: " << adapt_id
|
|
<< ", base_id: " << base_id
|
|
<< ", complete_type_witness_id: " << complete_type_witness_id
|
|
<< ", vtable_ptr_id: " << vtable_ptr_id << "}";
|
|
}
|
|
};
|
|
|
|
// A class. See EntityWithParamsBase regarding the inheritance here.
|
|
struct Class : public EntityWithParamsBase,
|
|
public ClassFields,
|
|
public Printable<Class> {
|
|
auto Print(llvm::raw_ostream& out) const -> void {
|
|
out << "{";
|
|
PrintBaseFields(out);
|
|
out << ", ";
|
|
PrintClassFields(out);
|
|
out << "}";
|
|
}
|
|
|
|
// This is false until we reach the `}` of the class definition.
|
|
auto is_complete() const -> bool {
|
|
return complete_type_witness_id.has_value();
|
|
}
|
|
|
|
// Gets the type that this class type adapts. Returns `None` if there is no
|
|
// such type, or if the class is not yet defined.
|
|
auto GetAdaptedType(const File& file, SpecificId specific_id) const -> TypeId;
|
|
|
|
// Gets the base class for this class type. Returns `None` if there is no
|
|
// such type, or if the class is not yet defined.
|
|
auto GetBaseType(const File& file, SpecificId specific_id) const -> TypeId;
|
|
|
|
// Gets the object representation for this class. Returns `None` if the class
|
|
// is not yet defined.
|
|
auto GetObjectRepr(const File& file, SpecificId specific_id) const -> TypeId;
|
|
};
|
|
|
|
using ClassStore = ValueStore<ClassId, Class>;
|
|
|
|
} // namespace Carbon::SemIR
|
|
|
|
#endif // CARBON_TOOLCHAIN_SEM_IR_CLASS_H_
|