Skip to content

Commit

Permalink
frontend: Start limiting scope of impl block calls
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Nov 17, 2024
1 parent 4e14137 commit 57c4f34
Show file tree
Hide file tree
Showing 95 changed files with 227 additions and 28 deletions.
1 change: 1 addition & 0 deletions bench/binarytrees/binarytrees-mt.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const MIN_DEPTH: Int32 = 4i32;
const DEFAULT_DEPTH: Int32 = 6i32;
const DEFAULT_THREADS: Int32 = 4i32;
use std::string::Stringable;

fn main() {
let maxDepth = if std::argc() > 0i32 {
Expand Down
2 changes: 2 additions & 0 deletions bench/binarytrees/binarytrees.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::Stringable;

fn main() {
let mut maxDepth = 6i32;

Expand Down
2 changes: 2 additions & 0 deletions bench/fannkuchredux/fannkuchredux.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::Stringable;

fn main() {
let mut n = 7i32;
if std::argc() > 0i32 { n = std::argv(0i32).toInt32().getOrPanic(); }
Expand Down
1 change: 1 addition & 0 deletions bench/gcbench/gcbench.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::argc;
use std::argv;
use std::timestamp;
use std::string::Stringable;

class Node {
left: Option[Node],
Expand Down
2 changes: 2 additions & 0 deletions bench/gcold/gcold.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::Stringable;

class TreeNode {
left: Option[TreeNode],
right: Option[TreeNode],
Expand Down
2 changes: 2 additions & 0 deletions bench/nbody/nbody.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::Stringable;

fn main() {
SOLAR_MASS = 4.0 * PI * PI;
let n = std::argv(0i32).toInt32().getOrPanic();
Expand Down
1 change: 1 addition & 0 deletions bench/richards/richards.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Dora implementation of Richards benchmark.
// Originally implemented in BCPL (http://www.cl.cam.ac.uk/~mr10/Bench.html)
// Used in Octane 2.0 (https://developers.google.com/octane/benchmark)
use std::traits::{IndexGet, IndexSet, Not};

fn main() {
let mut iterations = 8200i32;
Expand Down
1 change: 1 addition & 0 deletions bench/splay/splay.dora
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fatalError;
use std::timestamp;
use std::string::Stringable;

fn main() {
if std::argc() != 3i32 {
Expand Down
1 change: 1 addition & 0 deletions bench/splunc/splunc.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::argc;
use std::argv;
use std::exit;
use std::string::Stringable;

class Node {
payload: Option[Array[Int32]],
Expand Down
21 changes: 18 additions & 3 deletions dora-frontend/src/generator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ fn sema(code: &'static str) -> Sema {
let mut sa = Sema::new(args);

let result = check_program(&mut sa);
if sa.diag.borrow().has_errors() {
sa.diag.borrow_mut().dump(&sa, true);
}
assert!(!sa.diag.borrow().has_errors());
assert!(result);

Expand Down Expand Up @@ -3750,15 +3753,22 @@ fn gen_array_get() {

#[test]
fn gen_array_get_method() {
let sa = sema("fn f(x: Array[Float32], idx: Int64): Float32 { x.get(idx) }");
let sa = sema(
"use std::traits::IndexGet;
fn f(x: Array[Float32], idx: Int64): Float32 { x.get(idx) }",
);
let (_, code) = bc(&sa, "<prog>::f");
let expected = vec![LoadArray(r(2), r(0), r(1)), Ret(r(2))];
assert_eq!(expected, code);
}

#[test]
fn gen_array_set_method() {
let sa = sema("fn f(x: Array[Float32], idx: Int64, value: Float32) { x.set(idx, value); }");
let sa = sema(
"
use std::traits::IndexSet;
fn f(x: Array[Float32], idx: Int64, value: Float32) { x.set(idx, value); }",
);
let (_, code) = bc(&sa, "<prog>::f");
let expected = vec![StoreArray(r(2), r(0), r(1)), Ret(r(3))];
assert_eq!(expected, code);
Expand Down Expand Up @@ -3811,7 +3821,12 @@ fn gen_string_equals() {

#[test]
fn gen_bool_to_string() {
let sa = sema("fn f(a: Bool): String { a.toString() }");
let sa = sema(
"
use std::string::Stringable;
fn f(a: Bool): String { a.toString() }
",
);
let (fct, code) = bc(&sa, "<prog>::f");

let fct_id = lookup_fct(
Expand Down
4 changes: 2 additions & 2 deletions dora-frontend/src/impldefck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,9 +1160,9 @@ mod tests {
#[test]
fn impl_generic_extended_ty() {
ok("
trait Foo[T] { fn getter(): T; }
trait Foo[T] { fn get(): T; }
impl[T] Foo[T] for T {
fn getter(): T { self }
fn get(): T { self }
}
fn f(x: Int64): Foo[Int64] { x as Foo[Int64] }
");
Expand Down
31 changes: 29 additions & 2 deletions dora-frontend/src/sym.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use parking_lot::RwLock;

use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::sync::Arc;

Expand Down Expand Up @@ -81,6 +81,24 @@ impl ModuleSymTable {
None
}

pub fn contains_trait(&self, trait_id: TraitDefinitionId) -> bool {
for level in self.levels.iter().rev() {
if level.contains_trait(trait_id) {
return true;
}
}

if self.outer.contains_trait(trait_id) {
return true;
}

if self.prelude.contains_trait(trait_id) {
return true;
}

false
}

pub fn insert(&mut self, name: Name, sym: SymbolKind) -> Option<Symbol> {
self.levels.last_mut().unwrap().insert(name, sym)
}
Expand All @@ -89,13 +107,15 @@ impl ModuleSymTable {
#[derive(Debug)]
pub struct SymTable {
table: HashMap<Name, Symbol>,
traits: HashSet<TraitDefinitionId>,
}

impl SymTable {
// creates a new table
pub fn new() -> SymTable {
SymTable {
table: HashMap::new(),
traits: HashSet::new(),
}
}

Expand All @@ -107,6 +127,10 @@ impl SymTable {
self.table.get(&name)
}

pub fn contains_trait(&self, trait_id: TraitDefinitionId) -> bool {
self.traits.contains(&trait_id)
}

pub fn insert(&mut self, name: Name, kind: SymbolKind) -> Option<Symbol> {
let symbol = Symbol {
visibility: None,
Expand All @@ -125,6 +149,9 @@ impl SymTable {
visibility: Some(visibility),
kind,
};
if let SymbolKind::Trait(trait_id) = kind {
self.traits.insert(trait_id);
}
self.table.insert(name, symbol)
}

Expand All @@ -151,7 +178,7 @@ impl Symbol {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SymbolKind {
Class(ClassDefinitionId),
Struct(StructDefinitionId),
Expand Down
6 changes: 4 additions & 2 deletions dora-frontend/src/typeck/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ fn check_expr_call_static_method(

let candidates = find_method_call_candidates(
ck.sa,
&ck.symtable,
object_type.clone(),
&ck.type_param_definition,
interned_method_name,
Expand Down Expand Up @@ -387,6 +388,7 @@ fn check_expr_call_method(

let candidates = find_method_call_candidates(
ck.sa,
&ck.symtable,
object_type.clone(),
&ck.type_param_definition,
interned_method_name,
Expand Down Expand Up @@ -599,7 +601,7 @@ fn check_expr_call_ctor_with_named_fields(
let def_ty = replace_type(ck.sa, field.ty, Some(&type_params), None);
let arg_ty = ck.analysis.ty(arg.id);

if !def_ty.allows(ck.sa, arg_ty.clone()) {
if !def_ty.allows(ck.sa, arg_ty.clone()) && !arg_ty.is_error() {
let exp = ck.ty_name(&def_ty);
let got = ck.ty_name(&arg_ty);

Expand Down Expand Up @@ -643,7 +645,7 @@ fn check_expr_call_ctor_with_unnamed_fields(
.report(ck.file_id, name.span, ErrorMessage::UnexpectedNamedArgument);
}

if !def_ty.allows(ck.sa, arg_ty.clone()) {
if !def_ty.allows(ck.sa, arg_ty.clone()) && !arg_ty.is_error() {
let exp = ck.ty_name(&def_ty);
let got = ck.ty_name(&arg_ty);

Expand Down
3 changes: 2 additions & 1 deletion dora-frontend/src/typeck/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ fn check_expr_assign_call(ck: &mut TypeCheck, e: &ast::ExprBinType) {
impl_item_type_alias_ty.clone(),
value_type.clone(),
None,
) {
) && !value_type.is_error()
{
let exp = ck.ty_name(&impl_item_type_alias_ty);
let got = ck.ty_name(&value_type);
ck.sa.report(
Expand Down
8 changes: 6 additions & 2 deletions dora-frontend/src/typeck/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,9 @@ pub(super) fn check_args_compatible(
);
let arg_ty = ck.analysis.ty(arg.id);

if !arg_allows(ck.sa, param_ty.clone(), arg_ty.clone(), self_ty.clone()) {
if !arg_allows(ck.sa, param_ty.clone(), arg_ty.clone(), self_ty.clone())
&& !arg_ty.is_error()
{
let exp = ck.ty_name(&param_ty);
let got = ck.ty_name(&arg_ty);

Expand Down Expand Up @@ -498,7 +500,9 @@ pub(super) fn check_args_compatible(
for arg in &args.arguments[no_regular_params..] {
let arg_ty = ck.analysis.ty(arg.id);

if !arg_allows(ck.sa, variadic_ty.clone(), arg_ty.clone(), self_ty.clone()) {
if !arg_allows(ck.sa, variadic_ty.clone(), arg_ty.clone(), self_ty.clone())
&& !arg_ty.is_error()
{
let exp = ck.ty_name(&variadic_ty);
let got = ck.ty_name(&arg_ty);

Expand Down
21 changes: 17 additions & 4 deletions dora-frontend/src/typeck/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ use crate::interner::Name;
use crate::sema::{
extension_matches, impl_matches, Candidate, Sema, TraitDefinition, TypeParamDefinition,
};
use crate::SourceType;
use crate::sym::ModuleSymTable;
use crate::{package_for_type, SourceType};

pub fn find_method_call_candidates(
sa: &Sema,
table: &ModuleSymTable,
object_type: SourceType,
type_param_defs: &TypeParamDefinition,
name: Name,
is_static: bool,
) -> Vec<Candidate> {
let mut candidates = Vec::with_capacity(1);
let package_id = sa.module(table.module_id()).package_id();

if let SourceType::TraitObject(trait_id, trait_type_params, _bindings) = object_type.clone() {
let trait_ = sa.trait_(trait_id);
Expand Down Expand Up @@ -55,10 +58,20 @@ pub fn find_method_call_candidates(
}

for (_id, impl_) in sa.impls.iter() {
if let Some(bindings) = impl_matches(sa, object_type.clone(), type_param_defs, impl_.id()) {
if let Some(trait_ty) = impl_.trait_ty() {
let trait_ = &sa.trait_(trait_ty.trait_id);
if let Some(trait_ty) = impl_.trait_ty() {
let trait_ = &sa.trait_(trait_ty.trait_id);

let is_trait_foreign = trait_.package_id != package_id;
let is_extended_ty_foreign =
package_for_type(sa, impl_.extended_ty()) != Some(package_id);

if is_trait_foreign && !table.contains_trait(trait_.id()) && is_extended_ty_foreign {
continue;
}

if let Some(bindings) =
impl_matches(sa, object_type.clone(), type_param_defs, impl_.id())
{
if let Some(trait_method_id) = trait_.get_method(name, is_static) {
if let Some(fct_id) = impl_.get_method_for_trait_method_id(trait_method_id) {
candidates.push(Candidate {
Expand Down
5 changes: 4 additions & 1 deletion dora-frontend/src/typeck/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2585,7 +2585,9 @@ fn for_with_array() {

#[test]
fn for_with_vec() {
ok("fn f(x: Vec[Int32]): Int32 {
ok("
use std::traits::IntoIterator;
fn f(x: Vec[Int32]): Int32 {
let mut result = 0i32;
for i in x.iter() {
result = result + i;
Expand Down Expand Up @@ -3972,6 +3974,7 @@ fn alias_in_local_type() {
#[test]
fn for_iterator_trait() {
ok("
use std::traits::IntoIterator;
fn f() {
let it = Array[Int64]::new(1, 2, 3).iter();
let mut sum = 0;
Expand Down
2 changes: 1 addition & 1 deletion pkgs/boots/assembler.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::Hash;
use std::Equals;
use std::traits::Iterator;
use std::traits::{IntoIterator, Iterator};

use package::graph::Location;

Expand Down
2 changes: 1 addition & 1 deletion pkgs/boots/graph.dora
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::{BitVecIter, HashMap};
use std::Equals;
use std::Hash;
use std::Stringable;
use std::traits::Iterator;
use std::traits::{IndexGet, IntoIterator, Iterator};

use package::assembler::{FloatRegister, Label, Register, RegMap, RegSet};
use package::bytecode::{BytecodeType, ClassId, FunctionId, ClassFieldId, GlobalId, StructId, TraitId};
Expand Down
1 change: 1 addition & 0 deletions pkgs/boots/interface.dora
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::VecIter;
use std::traits::IntoIterator;

use package::bytecode::{BytecodeFunction, BytecodeType, ConstPoolId, FunctionId, Location};
use package::bytecode::{ClassId, EnumId, ClassFieldId, GlobalId, StructId, StructFieldId, TraitId};
Expand Down
1 change: 1 addition & 0 deletions pkgs/boots/resolver.dora
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{HashMap, HashSet};
use std::traits::{IntoIterator, Iterator};

use package::assembler::{FloatRegister, Register, RegisterType};
use package::codegen::CodeGen;
Expand Down
2 changes: 2 additions & 0 deletions tests/array/array-compare.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::traits::Not;

fn main() {
let a = Array[Int32]::new(1i32, 2i32, 3i32, 3i32, 4i32, 5i32, 4i32, 5i32, 4i32, 3i32, 3i32);
let b = Array[Int32]::new(1i32, 2i32, 3i32, 3i32, 4i32, 5i32, 4i32, 5i32, 4i32, 3i32, 4i32);
Expand Down
2 changes: 2 additions & 0 deletions tests/array/array-enumerate2.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::traits::Iterator;

fn main() {
iterateManually();
iterateWithForIn();
Expand Down
2 changes: 2 additions & 0 deletions tests/array/array-equals.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::traits::Equals;

fn main() {
assert(Array[Int32]::new() == Array[Int32]::new());
assert(Array[Int32]::new().equals(Array[Int32]::new()));
Expand Down
2 changes: 2 additions & 0 deletions tests/array/array-toString.dora
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::Stringable;

fn main() {
assert(Array[Int32]::new().toString() == "Array()");
assert(Array[Int32]::new(1i32).toString() == "Array(1)");
Expand Down
1 change: 1 addition & 0 deletions tests/boots/compare-ordering-float32.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//= boots

use std::Ordering;
use std::traits::Comparable;

fn main() {
assert(f(1.0f32, 2.0f32) == Ordering::Less);
Expand Down
Loading

0 comments on commit 57c4f34

Please sign in to comment.