Compare commits

...

2 Commits

Author SHA1 Message Date
Jesse Brault
46ced3980a Some e2e tests passing again. Yay! 2026-06-26 18:22:56 -05:00
Jesse Brault
c59fbe4033 Fix some analysis/lowering bugs. WIP. 2026-06-26 18:02:21 -05:00
11 changed files with 136 additions and 72 deletions

View File

@ -10,7 +10,7 @@ use crate::ir::ir_parameter::IrParameter;
use crate::ir::ir_return::IrReturn; use crate::ir::ir_return::IrReturn;
use crate::ir::ir_statement::IrStatement; use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId}; use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
use crate::ir::ir_variable::IrVariableId; use crate::ir::ir_variable::{IrVariable, IrVariableId};
use crate::ir::variable_locations::{VariableLocation, VariableLocations}; use crate::ir::variable_locations::{VariableLocation, VariableLocations};
use dvm_lib::instruction::{ use dvm_lib::instruction::{
AddOperand, Instruction, Location, LocationOrInteger, LocationOrNumber, MoveOperand, AddOperand, Instruction, Location, LocationOrInteger, LocationOrNumber, MoveOperand,
@ -19,27 +19,23 @@ use dvm_lib::instruction::{
use std::collections::HashMap; use std::collections::HashMap;
struct FunctionAssemblyContext<'a> { struct FunctionAssemblyContext<'a> {
type_infos: &'a [IrTypeInfo],
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
variable_locations: &'a VariableLocations, variable_locations: &'a VariableLocations,
parameters: &'a [IrParameter], parameters: &'a [IrParameter],
variables: &'a [IrVariable],
constants_table: &'a mut ConstantsTable, constants_table: &'a mut ConstantsTable,
instructions: Vec<Instruction>, instructions: Vec<Instruction>,
} }
pub fn assemble_ir_function( pub fn assemble_ir_function(
ir_function: &IrFunction, ir_function: &IrFunction,
type_infos: &[IrTypeInfo],
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
variable_locations: &VariableLocations, variable_locations: &VariableLocations,
constants_table: &mut ConstantsTable, constants_table: &mut ConstantsTable,
) -> Vec<Instruction> { ) -> Vec<Instruction> {
let mut ctx = FunctionAssemblyContext { let mut ctx = FunctionAssemblyContext {
type_infos,
variables_to_type_infos,
variable_locations, variable_locations,
constants_table, constants_table,
parameters: ir_function.parameters(), parameters: ir_function.parameters(),
variables: ir_function.variables(),
instructions: Vec::new(), instructions: Vec::new(),
}; };
for block in ir_function.blocks() { for block in ir_function.blocks() {
@ -210,15 +206,17 @@ fn to_multiply_operand(
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
), ),
IrExpression::Variable(ir_variable_id) => { IrExpression::Variable(ir_variable_id) => {
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id]; let ir_variable = &ctx.variables[*ir_variable_id];
let ir_type_info = &ctx.type_infos[ir_type_info_id]; match ir_variable.type_info() {
match ir_type_info {
IrTypeInfo::Int | IrTypeInfo::Double => { IrTypeInfo::Int | IrTypeInfo::Double => {
let location = let location =
to_location(ctx.variable_locations.get_variable_location(ir_variable_id)); to_location(ctx.variable_locations.get_variable_location(ir_variable_id));
MultiplyOperand::Location(location) MultiplyOperand::Location(location)
} }
_ => panic!("Attempt to multiply non-number (found {})", ir_type_info), _ => panic!(
"Attempt to multiply non-number (found {})",
ir_variable.type_info()
),
} }
} }
IrExpression::Int(i) => MultiplyOperand::Int(*i), IrExpression::Int(i) => MultiplyOperand::Int(*i),
@ -240,9 +238,8 @@ fn to_add_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContex
} }
} }
IrExpression::Variable(ir_variable_id) => { IrExpression::Variable(ir_variable_id) => {
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id]; let ir_variable = &ctx.variables[*ir_variable_id];
let ir_type_info = &ctx.type_infos[ir_type_info_id]; match ir_variable.type_info() {
match ir_type_info {
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => AddOperand::Location( IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => AddOperand::Location(
to_location(ctx.variable_locations.get_variable_location(ir_variable_id)), to_location(ctx.variable_locations.get_variable_location(ir_variable_id)),
), ),
@ -274,16 +271,15 @@ fn to_subtract_operand(
), ),
} }
} }
IrExpression::Variable(ir_variable) => { IrExpression::Variable(ir_variable_id) => {
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable]; let ir_variable = &ctx.variables[*ir_variable_id];
let ir_type_info = &ctx.type_infos[ir_type_info_id]; match ir_variable.type_info() {
match ir_type_info {
IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location(to_location( IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location(to_location(
ctx.variable_locations.get_variable_location(ir_variable), ctx.variable_locations.get_variable_location(ir_variable_id),
)), )),
_ => panic!( _ => panic!(
"Attempt to subtract with non-number type (found {})", "Attempt to subtract with non-number type (found {})",
ir_type_info ir_variable.type_info()
), ),
} }
} }

View File

@ -75,13 +75,7 @@ impl IrFunction {
variable_locations: &VariableLocations, variable_locations: &VariableLocations,
constants_table: &mut ConstantsTable, constants_table: &mut ConstantsTable,
) -> Function { ) -> Function {
let instructions = assemble_ir_function( let instructions = assemble_ir_function(self, variable_locations, constants_table);
self,
type_infos,
variables_to_type_infos,
variable_locations,
constants_table,
);
Function::new( Function::new(
self.fqn.clone(), self.fqn.clone(),
self.parameters.len(), self.parameters.len(),

View File

@ -35,18 +35,10 @@ mod variable_locations;
pub fn compile_dvm_function( pub fn compile_dvm_function(
ir_function: &IrFunction, ir_function: &IrFunction,
ir_type_infos: &[IrTypeInfo],
ir_variables_to_ir_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
constants_table: &mut ConstantsTable, constants_table: &mut ConstantsTable,
) -> Function { ) -> Function {
let variable_locations = assign_registers(ir_function); let variable_locations = assign_registers(ir_function);
let instructions = assemble_ir_function( let instructions = assemble_ir_function(ir_function, &variable_locations, constants_table);
ir_function,
ir_type_infos,
ir_variables_to_ir_type_infos,
&variable_locations,
constants_table,
);
Function::new( Function::new(
ir_function.fqn().into(), ir_function.fqn().into(),
ir_function.parameters().len(), ir_function.parameters().len(),

View File

@ -24,10 +24,11 @@ pub fn block_live_in_live_out(ir_block: &IrBlock) -> (LivenessSets, LivenessSets
// for now, a statement can only have one successor // for now, a statement can only have one successor
// this will need to be updated when we add jumps // this will need to be updated when we add jumps
let statement_live_out = &mut live_out[statement_index]; let statement_live_out = &mut live_out[statement_index];
let successor_live_in = &live_in[statement_index + 1]; if let Some(successor_live_in) = live_in.get(statement_index + 1) {
for ir_variable_id in successor_live_in { for ir_variable_id in successor_live_in {
if statement_live_out.insert(*ir_variable_id) { if statement_live_out.insert(*ir_variable_id) {
did_work = true; did_work = true;
}
} }
} }

View File

@ -63,7 +63,7 @@ pub fn compile_compilation_unit(
let mut dvm_functions = HashMap::new(); let mut dvm_functions = HashMap::new();
for ir_function in &lower_to_ir_result.functions { for ir_function in &lower_to_ir_result.functions {
let dvm_function = compile_dvm_function(ir_function, todo!(), todo!(), constants_table); let dvm_function = compile_dvm_function(ir_function, constants_table);
dvm_functions.insert(dvm_function.name_owned(), dvm_function); dvm_functions.insert(dvm_function.name_owned(), dvm_function);
} }

View File

@ -17,7 +17,7 @@ use crate::ir::ir_call::IrCall;
use crate::ir::ir_expression::IrExpression; use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_function::IrFunction; use crate::ir::ir_function::IrFunction;
use crate::ir::ir_operation::IrOperation; use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_parameter::IrParameter; use crate::ir::ir_parameter::{IrParameter, IrParameterId};
use crate::ir::ir_return::IrReturn; use crate::ir::ir_return::IrReturn;
use crate::ir::ir_statement::IrStatement; use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_type_info::IrTypeInfo; use crate::ir::ir_type_info::IrTypeInfo;
@ -27,7 +27,6 @@ use crate::semantic_analysis::symbol::{Symbol, SymbolId};
use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId}; use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId};
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Neg; use std::ops::Neg;
use std::rc::Rc;
pub struct LowerToIrResult { pub struct LowerToIrResult {
pub functions: Vec<IrFunction>, pub functions: Vec<IrFunction>,
@ -72,6 +71,8 @@ struct LowerToIrFunctionContext {
blocks: Vec<IrBlock>, blocks: Vec<IrBlock>,
ir_variables: Vec<IrVariable>, ir_variables: Vec<IrVariable>,
symbols_to_variables: HashMap<SymbolId, IrVariableId>, symbols_to_variables: HashMap<SymbolId, IrVariableId>,
ir_parameters: Vec<IrParameter>,
symbols_to_parameters: HashMap<SymbolId, IrParameterId>,
current_block_statements: Vec<IrStatement>, current_block_statements: Vec<IrStatement>,
t_var_counter: usize, t_var_counter: usize,
} }
@ -82,6 +83,8 @@ impl LowerToIrFunctionContext {
blocks: Vec::new(), blocks: Vec::new(),
ir_variables: Vec::new(), ir_variables: Vec::new(),
symbols_to_variables: HashMap::new(), symbols_to_variables: HashMap::new(),
ir_parameters: Vec::new(),
symbols_to_parameters: HashMap::new(),
current_block_statements: Vec::new(), current_block_statements: Vec::new(),
t_var_counter: 0, t_var_counter: 0,
} }
@ -101,6 +104,20 @@ impl LowerToIrFunctionContext {
self.blocks.push(ir_block); self.blocks.push(ir_block);
} }
fn insert_ir_parameter(
&mut self,
ir_parameter: IrParameter,
maybe_associated_symbol_id: Option<SymbolId>,
) -> IrParameterId {
self.ir_parameters.push(ir_parameter);
let ir_parameter_id = self.ir_parameters.len() - 1;
if let Some(associated_symbol_id) = maybe_associated_symbol_id {
self.symbols_to_parameters
.insert(associated_symbol_id, ir_parameter_id);
}
ir_parameter_id
}
fn insert_ir_variable( fn insert_ir_variable(
&mut self, &mut self,
ir_variable: IrVariable, ir_variable: IrVariable,
@ -124,24 +141,10 @@ impl LowerToIrFunctionContext {
} }
fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) { fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
fn lower_to_ir_parameters(function: &Function, ctx: &mut LowerToIrContext) -> Vec<IrParameter> {
let mut ir_parameters = Vec::new();
let n_parameters = function.parameters().len() as isize;
for (i, parameter) in function.parameters().iter().enumerate() {
let parameter_type_info_id = ctx.nodes_to_type_infos[&parameter.node_id()];
let parameter_type_info = &ctx.type_infos[parameter_type_info_id];
let ir_parameter = IrParameter::new(
parameter.declared_name(),
to_ir_type_info(parameter_type_info),
n_parameters.neg() + (i as isize),
);
ir_parameters.push(ir_parameter);
}
ir_parameters
}
let mut fn_ctx = LowerToIrFunctionContext::new(); let mut fn_ctx = LowerToIrFunctionContext::new();
lower_to_ir_parameters(function, ctx, &mut fn_ctx);
let n_statements = function.statements().len(); let n_statements = function.statements().len();
for (i, statement) in function.statements().iter().enumerate() { for (i, statement) in function.statements().iter().enumerate() {
let can_return_value = i == n_statements - 1; let can_return_value = i == n_statements - 1;
@ -156,12 +159,16 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
_ => panic!("Expected function symbol"), _ => panic!("Expected function symbol"),
}; };
let return_type_info_id = ctx.symbols_to_type_infos[&function_symbol_id]; let function_type_info_id = ctx.symbols_to_type_infos[&function_symbol_id];
let return_type_info = &ctx.type_infos[return_type_info_id]; let function_type_info = match &ctx.type_infos[function_type_info_id] {
TypeInfo::Function(function_type_info) => function_type_info,
_ => panic!("Expected FunctionTypeInfo"),
};
let return_type_info = &ctx.type_infos[function_type_info.return_type_id()];
let ir_function = IrFunction::new( let ir_function = IrFunction::new(
function_symbol.fqn_owned(), function_symbol.fqn_owned(),
lower_to_ir_parameters(function, ctx), fn_ctx.ir_parameters,
fn_ctx.ir_variables, fn_ctx.ir_variables,
return_type_info_to_ir_type_info(return_type_info), return_type_info_to_ir_type_info(return_type_info),
fn_ctx.blocks, fn_ctx.blocks,
@ -170,6 +177,27 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
ctx.ir_functions.push(ir_function); ctx.ir_functions.push(ir_function);
} }
fn lower_to_ir_parameters(
function: &Function,
ctx: &LowerToIrContext,
fn_ctx: &mut LowerToIrFunctionContext,
) {
let n_parameters = function.parameters().len() as isize;
for (i, parameter) in function.parameters().iter().enumerate() {
let parameter_type_info_id = ctx.nodes_to_type_infos[&parameter.node_id()];
let parameter_type_info = &ctx.type_infos[parameter_type_info_id];
let ir_parameter = IrParameter::new(
parameter.declared_name(),
to_ir_type_info(parameter_type_info),
n_parameters.neg() + (i as isize),
);
fn_ctx.insert_ir_parameter(
ir_parameter,
Some(ctx.nodes_to_symbols[&parameter.node_id()]),
);
}
}
fn lower_to_ir_statement( fn lower_to_ir_statement(
statement: &Statement, statement: &Statement,
ctx: &LowerToIrContext, ctx: &LowerToIrContext,
@ -389,8 +417,18 @@ fn lower_expression_to_ir_expression(
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let rhs_symbol_id = ctx.nodes_to_symbols[&identifier.node_id()]; let rhs_symbol_id = ctx.nodes_to_symbols[&identifier.node_id()];
let rhs_ir_variable_id = fn_ctx.symbols_to_variables[&rhs_symbol_id]; if let Some(rhs_ir_variable_id) = fn_ctx.symbols_to_variables.get(&rhs_symbol_id) {
IrExpression::Variable(rhs_ir_variable_id) IrExpression::Variable(*rhs_ir_variable_id)
} else if let Some(rhs_ir_parameter_id) =
fn_ctx.symbols_to_parameters.get(&rhs_symbol_id)
{
IrExpression::Parameter(*rhs_ir_parameter_id)
} else {
panic!(
"Could not find parameter or variable for symbol_id {}",
rhs_symbol_id
);
}
} }
Expression::Integer(integer_literal) => IrExpression::Int(integer_literal.value()), Expression::Integer(integer_literal) => IrExpression::Int(integer_literal.value()),
Expression::Double(double_literal) => IrExpression::Double(double_literal.value()), Expression::Double(double_literal) => IrExpression::Double(double_literal.value()),

View File

@ -70,7 +70,12 @@ impl<'a> SymbolCollectionContext<'a> {
} }
pub fn resolve_fqn(&self, suffix: &Rc<str>) -> String { pub fn resolve_fqn(&self, suffix: &Rc<str>) -> String {
Self::join_fqn_parts(&[self.get_fqn_base().into(), suffix.clone()]) let base = self.get_fqn_base();
if base.is_empty() {
suffix.to_string()
} else {
Self::join_fqn_parts(&[base.into(), suffix.clone()])
}
} }
} }

View File

@ -53,7 +53,8 @@ pub fn collect_types(
} }
fn collect_types_function(function: &Function, ctx: &mut CollectTypesContext) { fn collect_types_function(function: &Function, ctx: &mut CollectTypesContext) {
let parameter_type_info_ids = get_parameter_type_info_ids(function.parameters(), ctx); let parameter_type_info_ids =
collect_and_get_parameter_type_info_ids(function.parameters(), ctx);
let return_type_info = match function.return_type() { let return_type_info = match function.return_type() {
None => TypeInfo::Void, None => TypeInfo::Void,
@ -83,7 +84,7 @@ fn declared_name_to_type_info(declared_name: &str) -> TypeInfo {
} }
} }
fn get_parameter_type_info_ids( fn collect_and_get_parameter_type_info_ids(
parameters: &[Parameter], parameters: &[Parameter],
ctx: &mut CollectTypesContext, ctx: &mut CollectTypesContext,
) -> Vec<TypeInfoId> { ) -> Vec<TypeInfoId> {
@ -92,12 +93,17 @@ fn get_parameter_type_info_ids(
let type_info = declared_name_to_type_info(parameter.type_use().declared_name()); let type_info = declared_name_to_type_info(parameter.type_use().declared_name());
let type_info_id = ctx.insert_type_info(type_info); let type_info_id = ctx.insert_type_info(type_info);
parameter_type_info_ids.push(type_info_id); parameter_type_info_ids.push(type_info_id);
// also associate the parameter symbol with the type info
let symbol_id = ctx.nodes_to_symbols[&parameter.node_id()];
ctx.symbols_to_type_infos.insert(symbol_id, type_info_id);
} }
parameter_type_info_ids parameter_type_info_ids
} }
fn collect_types_extern_function(extern_function: &ExternFunction, ctx: &mut CollectTypesContext) { fn collect_types_extern_function(extern_function: &ExternFunction, ctx: &mut CollectTypesContext) {
let parameter_type_info_ids = get_parameter_type_info_ids(extern_function.parameters(), ctx); let parameter_type_info_ids =
collect_and_get_parameter_type_info_ids(extern_function.parameters(), ctx);
let return_type_info = let return_type_info =
declared_name_to_type_info(extern_function.return_type().declared_name()); declared_name_to_type_info(extern_function.return_type().declared_name());

View File

@ -9,11 +9,12 @@ use crate::ast::function::Function;
use crate::ast::identifier::Identifier; use crate::ast::identifier::Identifier;
use crate::ast::let_statement::LetStatement; use crate::ast::let_statement::LetStatement;
use crate::ast::negative_expression::NegativeExpression; use crate::ast::negative_expression::NegativeExpression;
use crate::ast::parameter::Parameter;
use crate::ast::statement::Statement; use crate::ast::statement::Statement;
use crate::diagnostic::Diagnostics; use crate::diagnostic::Diagnostics;
use crate::diagnostic_factories::symbol_not_found; use crate::diagnostic_factories::symbol_not_found;
use crate::semantic_analysis::scope::{Scope, ScopeId}; use crate::semantic_analysis::scope::{Scope, ScopeId};
use crate::semantic_analysis::symbol::{Symbol, SymbolId, VariableSymbol}; use crate::semantic_analysis::symbol::{ParameterSymbol, Symbol, SymbolId, VariableSymbol};
use std::collections::HashMap; use std::collections::HashMap;
pub struct NameResolutionResult { pub struct NameResolutionResult {
@ -105,9 +106,27 @@ pub fn resolve_names(
} }
fn resolve_names_function(function: &Function, ctx: &mut NameResolutionContext) { fn resolve_names_function(function: &Function, ctx: &mut NameResolutionContext) {
for parameter in function.parameters() {
resolve_names_parameter(parameter, ctx);
}
for statement in function.statements() { for statement in function.statements() {
resolve_names_statement(statement, ctx, StatementResolutionPhase::Static); resolve_names_statement(statement, ctx, StatementResolutionPhase::Static);
} }
// point this function's node_id to the symbol_id for the function symbol
let scope_id = ctx.nodes_to_scopes[&function.node_id()];
let scope = &ctx.scopes[scope_id];
let symbol_id = scope.symbols()[function.declared_name()];
ctx.nodes_to_symbols.insert(function.node_id(), symbol_id);
}
fn resolve_names_parameter(parameter: &Parameter, ctx: &mut NameResolutionContext) {
// point this parameter's node_id to the symbol_id for the parameter symbol
let scope_id = ctx.nodes_to_scopes[&parameter.node_id()];
let scope = &ctx.scopes[scope_id];
let symbol_id = scope.symbols()[parameter.declared_name()];
ctx.nodes_to_symbols.insert(parameter.node_id(), symbol_id);
} }
fn resolve_names_statement( fn resolve_names_statement(

View File

@ -10,6 +10,7 @@ use crate::ast::function::Function;
use crate::ast::identifier::Identifier; use crate::ast::identifier::Identifier;
use crate::ast::let_statement::LetStatement; use crate::ast::let_statement::LetStatement;
use crate::ast::negative_expression::NegativeExpression; use crate::ast::negative_expression::NegativeExpression;
use crate::ast::parameter::Parameter;
use crate::ast::statement::Statement; use crate::ast::statement::Statement;
use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::diagnostic::{Diagnostic, Diagnostics};
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES; use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
@ -67,11 +68,23 @@ pub fn resolve_types(
} }
fn resolve_types_function(function: &Function, ctx: &mut ResolveTypesContext) { fn resolve_types_function(function: &Function, ctx: &mut ResolveTypesContext) {
for parameter in function.parameters() {
resolve_types_parameter(parameter, ctx);
}
for statement in function.statements() { for statement in function.statements() {
resolve_types_statement(statement, ctx); resolve_types_statement(statement, ctx);
} }
} }
fn resolve_types_parameter(parameter: &Parameter, ctx: &mut ResolveTypesContext) {
// point the parameter's node_id to the associated type_info
let symbol_id = ctx.nodes_to_symbols[&parameter.node_id()];
let type_info_id = ctx.symbols_to_type_infos[&symbol_id];
ctx.nodes_to_type_infos
.insert(parameter.node_id(), type_info_id);
}
fn resolve_types_statement(statement: &Statement, ctx: &mut ResolveTypesContext) { fn resolve_types_statement(statement: &Statement, ctx: &mut ResolveTypesContext) {
match statement { match statement {
Statement::Let(let_statement) => { Statement::Let(let_statement) => {
@ -300,7 +313,7 @@ fn resolve_types_call(call: &Call, ctx: &mut ResolveTypesContext) {
// set return type as type of call expression // set return type as type of call expression
let return_type_info_id = function_type_info.return_type_id(); let return_type_info_id = function_type_info.return_type_id();
ctx.nodes_to_type_infos ctx.nodes_to_type_infos
.insert(call.node_id(), *return_type_info_id); .insert(call.node_id(), return_type_info_id);
} }
TypeInfo::__Error => { TypeInfo::__Error => {
// bubble it up // bubble it up

View File

@ -49,7 +49,7 @@ impl FunctionTypeInfo {
&self.parameter_type_info_ids &self.parameter_type_info_ids
} }
pub fn return_type_id(&self) -> &TypeInfoId { pub fn return_type_id(&self) -> TypeInfoId {
&self.return_type_info_id self.return_type_info_id
} }
} }