From 3742770ca14485ccf8ab78edead944ebaa800c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= Date: Mon, 3 Feb 2025 21:10:43 +0100 Subject: [PATCH] bytecode: Use BytecodeTraitType for ImplData::trait_ty --- dora-bytecode/src/display.rs | 110 ++++++++++++++++++++++++--- dora-bytecode/src/program.rs | 2 +- dora-bytecode/src/ty.rs | 13 ++++ dora-frontend/src/program_emitter.rs | 2 +- dora-frontend/src/ty.rs | 1 + dora-runtime/src/compiler/aot.rs | 2 +- dora-runtime/src/vm/impls.rs | 7 +- dora-runtime/src/vm/stdlib_lookup.rs | 10 +-- 8 files changed, 125 insertions(+), 22 deletions(-) diff --git a/dora-bytecode/src/display.rs b/dora-bytecode/src/display.rs index 971106f70..236c145e5 100644 --- a/dora-bytecode/src/display.rs +++ b/dora-bytecode/src/display.rs @@ -1,5 +1,6 @@ use crate::{ - BytecodeType, BytecodeTypeArray, FunctionId, FunctionKind, ModuleId, Program, TypeParamData, + BytecodeTraitType, BytecodeType, BytecodeTypeArray, FunctionId, FunctionKind, ModuleId, + Program, TypeParamData, }; pub fn display_fct(prog: &Program, fct_id: FunctionId) -> String { @@ -67,7 +68,7 @@ pub fn display_fct(prog: &Program, fct_id: FunctionId) -> String { } result.push_str(" "); - result.push_str(&display_ty_with_type_params( + result.push_str(&display_trait_ty_with_type_params( prog, &impl_.trait_ty, &impl_.type_params, @@ -138,18 +139,44 @@ pub fn display_ty_without_type_params(prog: &Program, ty: &BytecodeType) -> Stri printer.string() } +pub fn fmt_ty_with_type_params<'a>( + prog: &'a Program, + ty: &'a BytecodeType, + type_params: &'a TypeParamData, +) -> BytecodeTypePrinter<'a> { + BytecodeTypePrinter { + prog, + type_params: TypeParamMode::TypeParams(type_params), + ty: ty.clone(), + } +} + pub fn display_ty_with_type_params( prog: &Program, ty: &BytecodeType, type_params: &TypeParamData, ) -> String { - let printer = BytecodeTypePrinter { + fmt_ty_with_type_params(prog, ty, type_params).string() +} + +pub fn fmt_trait_ty_with_type_params<'a>( + prog: &'a Program, + trait_ty: &'a BytecodeTraitType, + type_params: &'a TypeParamData, +) -> BytecodeTraitTypePrinter<'a> { + BytecodeTraitTypePrinter { prog, - type_params: TypeParamMode::TypeParams(type_params), - ty: ty.clone(), - }; + type_params, + trait_ty, + } +} - printer.string() +pub fn display_trait_ty_with_type_params( + prog: &Program, + trait_ty: &BytecodeTraitType, + type_params: &TypeParamData, +) -> String { + fmt_trait_ty_with_type_params(prog, trait_ty, type_params).string() } enum TypeParamMode<'a> { @@ -158,14 +185,14 @@ enum TypeParamMode<'a> { TypeParams(&'a TypeParamData), } -struct BytecodeTypePrinter<'a> { +pub struct BytecodeTypePrinter<'a> { prog: &'a Program, type_params: TypeParamMode<'a>, ty: BytecodeType, } impl<'a> BytecodeTypePrinter<'a> { - fn string(&self) -> String { + pub fn string(&self) -> String { format!("{}", self) } @@ -269,6 +296,71 @@ impl<'a> std::fmt::Display for BytecodeTypePrinter<'a> { } } +pub struct BytecodeTraitTypePrinter<'a> { + prog: &'a Program, + type_params: &'a TypeParamData, + trait_ty: &'a BytecodeTraitType, +} + +impl<'a> BytecodeTraitTypePrinter<'a> { + pub fn string(&self) -> String { + format!("{}", self) + } + + pub fn name( + &self, + trait_ty: &BytecodeTraitType, + fmt: &mut std::fmt::Formatter, + ) -> std::fmt::Result { + let trait_id = trait_ty.trait_id; + let trait_ = self.prog.trait_(trait_id); + write!(fmt, "{}", trait_.name)?; + + if !trait_ty.type_params.is_empty() || !trait_ty.bindings.is_empty() { + let mut first = false; + write!(fmt, "[")?; + + for ty in trait_ty.type_params.iter() { + if !first { + write!(fmt, ", ")?; + } + + write!( + fmt, + "{}", + fmt_ty_with_type_params(&self.prog, &ty, self.type_params) + )?; + first = false; + } + + for (alias_id, ty) in trait_ty.bindings.iter() { + if !first { + write!(fmt, ", ")?; + } + + let alias = self.prog.alias(*alias_id); + write!( + fmt, + "{}={}", + alias.name, + fmt_ty_with_type_params(&self.prog, &ty, self.type_params) + )?; + first = false; + } + + write!(fmt, "]")?; + } + + Ok(()) + } +} + +impl<'a> std::fmt::Display for BytecodeTraitTypePrinter<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.name(&self.trait_ty, f) + } +} + pub fn module_path_name(prog: &Program, module_id: ModuleId, name: &str) -> String { let mut result = module_path(prog, module_id); diff --git a/dora-bytecode/src/program.rs b/dora-bytecode/src/program.rs index ad4d384b8..f27679781 100644 --- a/dora-bytecode/src/program.rs +++ b/dora-bytecode/src/program.rs @@ -175,7 +175,7 @@ pub struct ImplId(pub u32); pub struct ImplData { pub module_id: ModuleId, pub type_params: TypeParamData, - pub trait_ty: BytecodeType, + pub trait_ty: BytecodeTraitType, pub extended_ty: BytecodeType, pub methods: Vec, pub trait_method_map: Vec<(FunctionId, FunctionId)>, diff --git a/dora-bytecode/src/ty.rs b/dora-bytecode/src/ty.rs index 79dd44ed8..741586018 100644 --- a/dora-bytecode/src/ty.rs +++ b/dora-bytecode/src/ty.rs @@ -266,3 +266,16 @@ pub struct BytecodeTraitType { pub type_params: BytecodeTypeArray, pub bindings: Vec<(AliasId, BytecodeType)>, } + +impl BytecodeTraitType { + pub fn is_trait_object_ty(&self, ty: &BytecodeType) -> bool { + match ty { + BytecodeType::TraitObject(trait_id, type_params, bindings) => { + assert!(bindings.is_empty()); + self.trait_id == *trait_id && &self.type_params == type_params + } + + _ => false, + } + } +} diff --git a/dora-frontend/src/program_emitter.rs b/dora-frontend/src/program_emitter.rs index 835c216d4..d135eee51 100644 --- a/dora-frontend/src/program_emitter.rs +++ b/dora-frontend/src/program_emitter.rs @@ -149,7 +149,7 @@ fn create_impls(sa: &Sema) -> Vec { result.push(ImplData { module_id: convert_module_id(impl_.module_id), type_params: create_type_params(sa, impl_.type_param_definition()), - trait_ty: bty_from_ty(trait_ty.ty()), + trait_ty: convert_trait_type(&trait_ty), extended_ty: bty_from_ty(impl_.extended_ty()), methods, trait_method_map, diff --git a/dora-frontend/src/ty.rs b/dora-frontend/src/ty.rs index 65896f964..511305e9e 100644 --- a/dora-frontend/src/ty.rs +++ b/dora-frontend/src/ty.rs @@ -1115,6 +1115,7 @@ impl TraitType { } pub fn ty(&self) -> SourceType { + assert!(self.bindings.is_empty()); SourceType::TraitObject(self.trait_id, self.type_params.clone(), ().into()) } diff --git a/dora-runtime/src/compiler/aot.rs b/dora-runtime/src/compiler/aot.rs index 3e0480cd7..501c7f70e 100644 --- a/dora-runtime/src/compiler/aot.rs +++ b/dora-runtime/src/compiler/aot.rs @@ -356,7 +356,7 @@ impl<'a> TransitiveClosureComputation<'a> { let trait_type_params = trait_object_ty.type_params(); for impl_ in self.vm.program.impls.iter() { - if impl_.trait_ty == trait_object_ty { + if impl_.trait_ty.is_trait_object_ty(&trait_object_ty) { for (trait_method_id, impl_method_id) in &impl_.trait_method_map { if *trait_method_id == trait_fct_id { let actual_ty = impl_.extended_ty.clone(); diff --git a/dora-runtime/src/vm/impls.rs b/dora-runtime/src/vm/impls.rs index 63e66cecd..1b0aa3a0f 100644 --- a/dora-runtime/src/vm/impls.rs +++ b/dora-runtime/src/vm/impls.rs @@ -21,7 +21,7 @@ pub fn find_trait_impl( .expect("no impl found for generic trait method call"); let impl_ = vm.impl_(impl_id); - let impl_trait_id = impl_.trait_ty.trait_id().expect("expected trait type"); + let impl_trait_id = impl_.trait_ty.trait_id; assert_eq!(impl_trait_id, trait_ty.trait_id); @@ -48,15 +48,14 @@ pub fn find_impl( for (impl_id, impl_) in vm.program.impls.iter().enumerate() { let impl_id = ImplId(impl_id.try_into().expect("doesn't fit")); - if impl_.trait_ty.trait_id().expect("trait expected") != trait_id { + if impl_.trait_ty.trait_id != trait_id { continue; } if let Some(binding) = impl_block_matches_ty(vm, check_ty.clone(), check_type_param_defs, impl_id) { - let impl_trait_ty_params = - specialize_bty_array(&impl_.trait_ty.type_params(), &binding); + let impl_trait_ty_params = specialize_bty_array(&impl_.trait_ty.type_params, &binding); if impl_trait_ty_params != trait_ty.type_params { continue; diff --git a/dora-runtime/src/vm/stdlib_lookup.rs b/dora-runtime/src/vm/stdlib_lookup.rs index 270a68cf1..6b07e0233 100644 --- a/dora-runtime/src/vm/stdlib_lookup.rs +++ b/dora-runtime/src/vm/stdlib_lookup.rs @@ -195,9 +195,8 @@ fn lookup_extension_for_ty(vm: &VM, extended_ty: BytecodeType) -> Option Option { for (id, impl_) in vm.program.impls.iter().enumerate() { - match &impl_.trait_ty { - BytecodeType::TraitObject(impl_trait_id, ..) if *impl_trait_id == trait_id => {} - _ => continue, + if impl_.trait_ty.trait_id != trait_id { + continue; } if impl_.extended_ty == extended_ty { @@ -210,9 +209,8 @@ fn lookup_impl_for_ty(vm: &VM, trait_id: TraitId, extended_ty: BytecodeType) -> fn lookup_impl_for_item(vm: &VM, trait_id: TraitId, extended_ty: ModuleItem) -> Option { for (id, impl_) in vm.program.impls.iter().enumerate() { - match &impl_.trait_ty { - BytecodeType::TraitObject(impl_trait_id, ..) if *impl_trait_id == trait_id => {} - _ => continue, + if impl_.trait_ty.trait_id != trait_id { + continue; } match impl_.extended_ty {