mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 18:50:09 +01:00
In the `EntityName` for a binding, preserve the `TypeInstId` describing how the type was written. When a diagnostic refers to that type via `TypeOfInstId`, use the type-as-written in the diagnostic rather than the canonical type. Assisted-by: Claude Opus via Antigravity
120 lines
5.4 KiB
C++
120 lines
5.4 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_CHECK_PATTERN_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_PATTERN_H_
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// The following functions are used to mark the start and end of a time interval
|
|
// during pattern handling, in which we may build an `ExprRegion` to represent
|
|
// an expression. During one of these intervals, we say that an `ExprRegion` is
|
|
// _pending_. Any insts added to `inst_block_stack` while an `ExprRegion` is
|
|
// pending are treated as part of the expression. These intervals do not nest:
|
|
// we can't start an interval if an `ExprRegion` is already pending.
|
|
//
|
|
// To ensure that each start has a matching end, without nesting, callers should
|
|
// maintain the invariant that an `ExprRegion` is pending before handling the
|
|
// start of a pattern, and after handling the end of a pattern.
|
|
|
|
// Marks the start of a pending `ExprRegion` (see above).
|
|
auto BeginExprRegionForPattern(Context& context) -> void;
|
|
|
|
// Finishes building the pending `ExprRegion`, and returns its ID. It will not
|
|
// yet have any control-flow edges into or out of it. An empty `ExprRegion` will
|
|
// still be pending after the call, so `End[Empty]ExprRegionForPattern` must be
|
|
// called separately after this.
|
|
auto ConsumeExprRegionForPattern(Context& context, SemIR::InstId result_id)
|
|
-> SemIR::ExprRegionId;
|
|
|
|
// Ends the pending `ExprRegion`, and asserts that it is empty.
|
|
auto EndEmptyExprRegionForPattern(Context& context) -> void;
|
|
|
|
// Ends the pending `ExprRegion`. If the top of the node stack is an expression,
|
|
// the `ExprRegion` is consumed and converted to an expression pattern, which
|
|
// replaces the expression on the node stack. Otherwise, the top of the node
|
|
// stack should be a pattern, in which case this asserts that the pending region
|
|
// is empty, and discards it.
|
|
//
|
|
// The node stack is passed explicitly as a reminder that this function affects
|
|
// the node stack, unlike the other `*ExprRegionForPattern` functions.
|
|
auto EndExprRegionForPattern(Context& context, NodeStack& node_stack) -> void;
|
|
|
|
// Builds and returns an empty `ExprRegion`.
|
|
auto MakeEmptyRegion(Context& context, SemIR::InstId result_id)
|
|
-> SemIR::ExprRegionId;
|
|
|
|
// Information about a created binding pattern.
|
|
struct BindingPatternInfo {
|
|
SemIR::InstId pattern_id;
|
|
SemIR::InstId bind_id;
|
|
};
|
|
|
|
// The phase of a binding pattern.
|
|
enum class BindingPhase { Template, Symbolic, Runtime };
|
|
|
|
// Creates an entity name for a binding pattern with the given properties.
|
|
// `type_inst_id` is the declared type of the binding as written, if known; see
|
|
// `SemIR::EntityName::type_inst_id`.
|
|
auto AddBindingEntityName(Context& context, SemIR::NameId name_id,
|
|
SemIR::TypeInstId type_inst_id, SemIR::InstId form_id,
|
|
bool is_unused, BindingPhase phase)
|
|
-> SemIR::EntityNameId;
|
|
|
|
// Creates a binding pattern and the associated binding inst, and returns their
|
|
// IDs. `scrutinee_type_id` is the type of the binding, and `type_region_id` is
|
|
// the region representing that type expression. The binding is added to
|
|
// `context.bind_name_map()`, with a placeholder value.
|
|
auto AddBindingPattern(Context& context, SemIR::LocId name_loc,
|
|
SemIR::ExprRegionId type_region_id,
|
|
SemIR::TypeId scrutinee_type_id,
|
|
SemIR::AnyBindingPattern pattern) -> BindingPatternInfo;
|
|
|
|
// Creates a binding inst with the given type and value, to represent the result
|
|
// of matching the given binding pattern. The binding is not added to any block,
|
|
// or to `context.bind_name_map()`.
|
|
auto AddBindingForPattern(Context& context, SemIR::LocId name_loc,
|
|
SemIR::AnyBindingPattern pattern,
|
|
SemIR::TypeId binding_type_id, SemIR::InstId value_id)
|
|
-> SemIR::InstId;
|
|
|
|
// Returns a VarStorage inst for the given `var` pattern. `is_returned_var`
|
|
// indicates whether the pattern is the `var` part of a `returned var`; if so,
|
|
// this reuses the return parameter, and otherwise it adds a new inst.
|
|
auto GetOrAddVarStorage(Context& context, SemIR::InstId var_pattern_id,
|
|
bool is_returned_var) -> SemIR::InstId;
|
|
|
|
// Kinds of parameters that can be added by `AddParamPattern`.
|
|
enum class ParamPatternKind {
|
|
// A value parameter, `x: T`.
|
|
Value,
|
|
// A reference parameter, `ref x: T`.
|
|
Ref,
|
|
// A variable parameter, `var x: T`.
|
|
Var,
|
|
};
|
|
|
|
// Returns the `ParamPatternKind` of the parameter instruction `param_inst_id`.
|
|
auto GetParamPatternKind(Context& context, SemIR::InstId param_inst_id)
|
|
-> ParamPatternKind;
|
|
|
|
// Adds a parameter pattern with the specified name and type information. The
|
|
// pattern emulates `x: T`, `ref x: T`, or `var x: T` depending on the value of
|
|
// `kind`. This only sets up the parameter pattern, binding pattern and type;
|
|
// callers are expected to add the returned parameter pattern instruction to
|
|
// appropriate blocks. This is used when generating functions, rather than
|
|
// processing a user-authored declaration.
|
|
auto AddParamPattern(Context& context, SemIR::LocId loc_id,
|
|
SemIR::NameId name_id,
|
|
SemIR::ExprRegionId type_expr_region_id,
|
|
SemIR::TypeId type_id, ParamPatternKind kind)
|
|
-> SemIR::InstId;
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_PATTERN_H_
|