Skip to content

Commit

Permalink
frontend: Make first use of super trait in boots
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Oct 17, 2024
1 parent 208257c commit 74d2981
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 51 deletions.
11 changes: 1 addition & 10 deletions dora-boots/assembler.dora
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,10 @@ fn testAssemblerBufferEmitInt() {
assert(buffer.size() == 4i64);
}

pub trait RegisterType {
pub trait RegisterType: Equals {
static fn fromInt32(value: Int32): Self;
fn toInt32(): Int32;
fn toLocation(): Location;
fn equals(other: Self): Bool;
}

pub struct Register(pub value: UInt8)
Expand Down Expand Up @@ -167,10 +166,6 @@ impl RegisterType for Register {
fn toLocation(): Location {
Location::Reg(self)
}

fn equals(other: Register): Bool {
self.value == other.value
}
}

impl std::Stringable for Register {
Expand Down Expand Up @@ -212,10 +207,6 @@ impl RegisterType for FloatRegister {
fn toLocation(): Location {
Location::FloatReg(self)
}

fn equals(other: FloatRegister): Bool {
self.value == other.value
}
}


Expand Down
6 changes: 3 additions & 3 deletions dora-boots/regalloc.dora
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ impl SimpleRegisterAllocator {
fn allocateFixedRegisterGeneric[T: RegisterType](dest: T, registers: RegisterTracker[T], inst: Inst) {
let current = registers.getRegister(inst);

if current is Some(current) && current.equals(dest) {
if current is Some(current) && current == dest {
registers.protect(dest);
return;
}
Expand Down Expand Up @@ -763,7 +763,7 @@ impl[T: RegisterType] RegisterTracker[T] {
let old_reg = self.locations.insert(value, reg);
if old_reg is Some(old_reg) {
if !self.protected.contains(old_reg) {
assert(!old_reg.equals(reg));
assert(old_reg != reg);
self.free.add(old_reg);
self.data.free(old_reg);
}
Expand Down Expand Up @@ -864,7 +864,7 @@ impl[T: RegisterType] RegisterTracker[T] {
if self.data.get(reg) is Some(inst) {
let current_reg = self.locations.get(inst);

if current_reg.isNone() || (current_reg is Some(current_reg) && !reg.equals(current_reg)) {
if current_reg.isNone() || (current_reg is Some(current_reg) && reg != current_reg) {
self.free.add(reg);
self.data.free(reg);
}
Expand Down
2 changes: 1 addition & 1 deletion dora-frontend/src/aliasck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ mod tests {
}
",
&[
((5, 47), ErrorMessage::UnexpectedTypeAliasAssignment),
((5, 29), ErrorMessage::UnexpectedWhere),
((5, 47), ErrorMessage::UnexpectedTypeAliasAssignment),
],
);
}
Expand Down
50 changes: 50 additions & 0 deletions dora-frontend/src/impldefck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,40 @@ fn check_type_aliases_bounds_inner(sa: &Sema, impl_: &ImplDefinition, trait_: &T
}
}

pub fn check_super_traits(sa: &Sema) {
for (_id, impl_) in sa.impls.iter() {
if let Some(trait_ty) = impl_.trait_ty() {
check_super_traits_for_bound(sa, impl_, trait_ty);
}
}
}

fn check_super_traits_for_bound(sa: &Sema, impl_: &ImplDefinition, trait_ty: TraitType) {
let trait_ = sa.trait_(trait_ty.trait_id);
let type_param_definition = trait_.type_param_definition();

for bound in type_param_definition.bounds_for_self() {
if implements_trait(
sa,
impl_.extended_ty(),
impl_.type_param_definition(),
bound.clone(),
) {
check_super_traits_for_bound(sa, impl_, bound);
} else {
let name = impl_
.extended_ty()
.name_with_type_params(sa, impl_.type_param_definition());

let bound_name = bound.name_with_type_params(sa, trait_.type_param_definition());
let msg = ErrorMessage::TypeNotImplementingTrait(name, bound_name);
sa.report(impl_.file_id, impl_.parsed_trait_ty().span(), msg);

impl_.parsed_trait_ty().set_ty(None);
}
}
}

#[cfg(test)]
mod tests {
use crate::error::msg::ErrorMessage;
Expand Down Expand Up @@ -1134,6 +1168,22 @@ mod tests {
");
}

#[test]
fn impl_generic_extended_ty_with_trait_bound() {
err(
"
trait Foo[T] { fn get(): T; }
trait Bar {}
impl[T] Foo[T] for T where T: Bar {
fn get(): T { self }
}
fn f(x: Int64): Foo[Int64] { x as Foo[Int64] }
",
(7, 42),
ErrorMessage::TypeNotImplementingTrait("Int64".into(), "Foo[Int64]".into()),
);
}

#[test]
fn impl_reuse_trait_implementation() {
ok("
Expand Down
39 changes: 32 additions & 7 deletions dora-frontend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ pub use parsety::{ParsedTraitType, ParsedType, ParsedTypeAst};
pub use path::{parse_path, PathKind};
pub use program_emitter::emit_program;
pub use specialize::{
replace_type, specialize_for_element, specialize_type, specialize_type_array,
replace_type, specialize_for_element, specialize_trait_type, specialize_type,
specialize_type_array,
};

pub(crate) mod access;
Expand Down Expand Up @@ -82,6 +83,7 @@ pub fn check_program(sa: &mut Sema) -> bool {
impldefck::check_definition(sa);
impldefck::check_definition_against_trait(sa);
impldefck::check_type_aliases_bounds(sa);
impldefck::check_super_traits(sa);
enumck::check(sa);
globaldefck::check(sa);
extensiondefck::check(sa);
Expand Down Expand Up @@ -296,16 +298,39 @@ pub mod tests {
}

pub fn errors(code: &'static str, vec: &[((u32, u32), ErrorMessage)]) {
test::check(code, |vm| {
let diag = vm.diag.borrow();
let errors = diag.errors();
test::check(code, |sa| {
let diag = sa.diag.borrow();
let mut errors = diag.errors().to_vec();
errors.sort_by_key(|e| e.span);

println!("expected errors:");
for error in vec {
println!("{}:{}: {}", error.0 .0, error.0 .1, error.1.message());
}
println!("");

println!("errors = {:?}", errors);
assert_eq!(vec.len(), errors.len());
println!("actual errors:");
for error in &errors {
println!("{}", error.message(sa));
}
println!("\n");

assert_eq!(
vec.len(),
errors.len(),
"test expects {} errors but actually got {} errors.",
vec.len(),
errors.len()
);

for (ind, error) in errors.iter().enumerate() {
println!("compare error {}", ind);
assert_eq!(Some(vec[ind].0), compute_pos(code, error));
assert_eq!(vec[ind].1, error.msg);
assert_eq!(
vec[ind].1, error.msg,
"\nexpected: {:?}\n but got: {:?}",
vec[ind].1, error.msg
);
}
});
}
Expand Down
15 changes: 7 additions & 8 deletions dora-frontend/src/parsety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ impl ParsedTraitType {
*self.ty.borrow_mut() = ty;
}

pub fn span(&self) -> Span {
self.parsed_ast().expect("missing ast node").span
}

fn parsed_ast(&self) -> Option<&ParsedTypeAst> {
self.parsed_ast.get().map(|ast| &**ast)
}
Expand Down Expand Up @@ -1009,7 +1013,7 @@ fn check_type_params(

fn check_trait_type_param_definition(
sa: &Sema,
element: &dyn Element,
_element: &dyn Element,
trait_: &TraitDefinition,
generic_arguments: &[SourceType],
type_bindings: &[(AliasDefinitionId, SourceType)],
Expand All @@ -1023,15 +1027,10 @@ fn check_trait_type_param_definition(
let mut success = true;

for bound in type_param_definition.bounds() {
let mut tp_ty = bound.ty();
let tp_ty = bound.ty();

if tp_ty.is_self() {
if element.is_impl() {
let impl_ = element.to_impl().expect("impl expected");
tp_ty = impl_.extended_ty();
} else {
continue;
}
continue;
}

if let Some(trait_ty) = bound.trait_ty() {
Expand Down
6 changes: 6 additions & 0 deletions dora-frontend/src/sema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ impl Sema {
Location::new(line, column)
}

pub fn debug_loc(&self, element: &dyn Element) -> String {
let file = self.file(element.file_id());
let loc = self.compute_loc(element.file_id(), element.span());
format!("{}:{}", file.path.display(), loc)
}

pub fn report(&self, file: SourceFileId, span: Span, msg: ErrorMessage) {
self.diag.borrow_mut().report(file, span, msg);
}
Expand Down
5 changes: 5 additions & 0 deletions dora-frontend/src/sema/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::sema::{
Element, ElementId, ImplDefinitionId, ModuleDefinitionId, PackageDefinitionId, Sema,
SourceFileId, TraitDefinitionId, TypeParamDefinition, Visibility,
};
use crate::Span;
use dora_parser::ast;

pub type AliasDefinitionId = Id<AliasDefinition>;
Expand Down Expand Up @@ -128,6 +129,10 @@ impl Element for AliasDefinition {
self.file_id
}

fn span(&self) -> Span {
self.node.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
7 changes: 5 additions & 2 deletions dora-frontend/src/sema/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ use id_arena::Id;
use crate::interner::Name;
use crate::program_parser::ParsedModifierList;
use dora_parser::ast;
use dora_parser::Span;

use crate::sema::{
module_path, Element, ElementAccess, ElementId, ExtensionDefinitionId, FctDefinitionId,
ModuleDefinitionId, PackageDefinitionId, Sema, SourceFileId, TypeParamDefinition,
};
use crate::{specialize_for_element, ParsedType, SourceType, SourceTypeArray};
use crate::{specialize_for_element, ParsedType, SourceType, SourceTypeArray, Span};

pub type ClassDefinitionId = Id<ClassDefinition>;

Expand Down Expand Up @@ -191,6 +190,10 @@ impl Element for ClassDefinition {
self.file_id.expect("missing file_id")
}

fn span(&self) -> Span {
self.span()
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ impl Element for ConstDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
17 changes: 8 additions & 9 deletions dora-frontend/src/sema/elements.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
use std::rc::Rc;

use crate::{
sema::{
AliasDefinition, AliasDefinitionId, AliasParent, ClassDefinitionId, ConstDefinitionId,
EnumDefinitionId, ExtensionDefinitionId, FctDefinition, FctDefinitionId, FctParent,
GlobalDefinitionId, ImplDefinition, ImplDefinitionId, ModuleDefinitionId,
PackageDefinitionId, Sema, SourceFileId, StructDefinitionId, TraitDefinition,
TraitDefinitionId, TypeParamDefinition, UseDefinitionId,
},
ty::SourceType,
use crate::sema::{
AliasDefinition, AliasDefinitionId, AliasParent, ClassDefinitionId, ConstDefinitionId,
EnumDefinitionId, ExtensionDefinitionId, FctDefinition, FctDefinitionId, FctParent,
GlobalDefinitionId, ImplDefinition, ImplDefinitionId, ModuleDefinitionId, PackageDefinitionId,
Sema, SourceFileId, StructDefinitionId, TraitDefinition, TraitDefinitionId,
TypeParamDefinition, UseDefinitionId,
};
use crate::{SourceType, Span};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ElementId {
Expand All @@ -30,6 +28,7 @@ pub trait Element {
fn element_id(&self) -> ElementId;

fn file_id(&self) -> SourceFileId;
fn span(&self) -> Span;
fn module_id(&self) -> ModuleDefinitionId;
fn package_id(&self) -> PackageDefinitionId;
fn type_param_definition(&self) -> Option<&Rc<TypeParamDefinition>>;
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ impl Element for EnumDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ impl Element for ExtensionDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ impl Element for FctDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ impl Element for GlobalDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/sema/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ impl Element for ImplDefinition {
self.file_id
}

fn span(&self) -> Span {
self.span
}

fn module_id(&self) -> ModuleDefinitionId {
self.module_id
}
Expand Down
Loading

0 comments on commit 74d2981

Please sign in to comment.