Skip to content

Commit

Permalink
Remove various redundant compiler limitations
Browse files Browse the repository at this point in the history
These haven't been relevant since we switched from using a VM to
compiling to machine code.

This fixes #784.

Changelog: changed
  • Loading branch information
yorickpeterse committed Dec 23, 2024
1 parent 91c564d commit 6f8a503
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 170 deletions.
16 changes: 0 additions & 16 deletions compiler/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub(crate) enum DiagnosticId {
InvalidSyntax,
InvalidThrow,
InvalidType,
LimitReached,
MissingField,
MissingMain,
MissingTrait,
Expand Down Expand Up @@ -51,7 +50,6 @@ impl fmt::Display for DiagnosticId {
DiagnosticId::Unreachable => "unreachable",
DiagnosticId::Moved => "moved",
DiagnosticId::InvalidMatch => "invalid-match",
DiagnosticId::LimitReached => "limit-reached",
DiagnosticId::MissingMain => "missing-main",
DiagnosticId::InvalidCast => "invalid-cast",
DiagnosticId::UnusedSymbol => "unused-symbol",
Expand Down Expand Up @@ -863,20 +861,6 @@ impl Diagnostics {
);
}

pub(crate) fn string_literal_too_large(
&mut self,
limit: usize,
file: PathBuf,
location: Location,
) {
self.error(
DiagnosticId::LimitReached,
format!("string literals can't be greater than {} bytes", limit),
file,
location,
);
}

pub(crate) fn duplicate_type_parameter_requirement(
&mut self,
param: &str,
Expand Down
16 changes: 1 addition & 15 deletions compiler/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ use ::ast::nodes::{self as ast, Node as _};
use location::Location;
use std::path::PathBuf;
use std::str::FromStr;
use types::{
ARRAY_INTERNAL_NAME, ARRAY_LIMIT, ARRAY_PUSH, ARRAY_WITH_CAPACITY,
};
use types::{ARRAY_INTERNAL_NAME, ARRAY_PUSH, ARRAY_WITH_CAPACITY};

const BUILTIN_RECEIVER: &str = "_INKO";
const ARRAY_LIT_VAR: &str = "$array";
Expand Down Expand Up @@ -2144,18 +2142,6 @@ impl<'a> LowerToHir<'a> {
}

fn array_literal(&mut self, node: ast::Array) -> Expression {
if node.values.len() > ARRAY_LIMIT {
self.state.diagnostics.error(
DiagnosticId::LimitReached,
format!(
"array literals are limited to a maximum of {} values",
ARRAY_LIMIT
),
self.file(),
node.location,
);
}

let var_ref = Expression::IdentifierRef(Box::new(IdentifierRef {
name: ARRAY_LIT_VAR.to_string(),
kind: types::IdentifierKind::Unknown,
Expand Down
16 changes: 2 additions & 14 deletions compiler/src/mir/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use types::module_name::ModuleName;
use types::{
self, Block as _, ClassId, ConstantId, FieldId, Inline, MethodId, ModuleId,
Symbol, TypeBounds, TypeRef, VerificationError, ENUM_TAG_INDEX, EQ_METHOD,
FIELDS_LIMIT, OPTION_NONE, OPTION_SOME, RESULT_CLASS, RESULT_ERROR,
RESULT_MODULE, RESULT_OK,
OPTION_NONE, OPTION_SOME, RESULT_CLASS, RESULT_ERROR, RESULT_MODULE,
RESULT_OK,
};

const SELF_NAME: &str = "self";
Expand Down Expand Up @@ -3664,18 +3664,6 @@ impl<'a> LowerMethod<'a> {
variable_fields.insert(var, field);
}

if field_index >= FIELDS_LIMIT {
self.state.diagnostics.error(
DiagnosticId::InvalidType,
format!(
"closures can't capture more than {} variables",
FIELDS_LIMIT
),
self.file(),
node.location,
);
}

let mut mir_class = Class::new(class_id);
let mut mir_method = Method::new(method_id);
let mut lower = LowerMethod::new(
Expand Down
74 changes: 1 addition & 73 deletions compiler/src/type_check/define_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,9 @@ use types::{
Class, ClassId, ClassInstance, ClassKind, Constant, Database, ModuleId,
Symbol, Trait, TraitId, TraitImplementation, TypeId, TypeRef, Visibility,
ARRAY_INTERNAL_NAME, CONSTRUCTORS_LIMIT, ENUM_TAG_FIELD, ENUM_TAG_INDEX,
FIELDS_LIMIT, MAIN_CLASS, OPTION_CLASS, OPTION_MODULE, RESULT_CLASS,
RESULT_MODULE,
MAIN_CLASS, OPTION_CLASS, OPTION_MODULE, RESULT_CLASS, RESULT_MODULE,
};

/// The maximum number of arguments a single constructor can accept. We subtract
/// one as the tag is its own field.
const MAX_MEMBERS: usize = FIELDS_LIMIT - 1;

/// A compiler pass that defines classes and traits.
///
/// This pass _only_ defines the types, it doesn't define their type parameters,
Expand Down Expand Up @@ -585,20 +580,6 @@ impl<'a> DefineFields<'a> {
break;
}

if id >= FIELDS_LIMIT {
self.state.diagnostics.error(
DiagnosticId::InvalidType,
format!(
"classes can't define more than {} fields",
FIELDS_LIMIT
),
self.file(),
fnode.location,
);

break;
}

if class_id.field(self.db(), &name).is_some() {
self.state.diagnostics.duplicate_field(
&name,
Expand Down Expand Up @@ -1135,20 +1116,6 @@ impl<'a> DefineConstructors<'a> {
args_count = len;
}

if len > MAX_MEMBERS {
self.state.diagnostics.error(
DiagnosticId::InvalidSymbol,
format!(
"enum constructors can't contain more than {} members",
MAX_MEMBERS
),
self.file(),
node.location,
);

continue;
}

if constructors_count == CONSTRUCTORS_LIMIT {
self.state.diagnostics.error(
DiagnosticId::InvalidSymbol,
Expand Down Expand Up @@ -1286,7 +1253,6 @@ mod tests {
use crate::modules_parser::ParsedModule;
use crate::test::{cols, define_drop_trait};
use ast::parser::Parser;
use std::fmt::Write as _;
use types::module_name::ModuleName;
use types::{
ClassId, ConstantId, TraitId, TraitInstance, TypeBounds,
Expand Down Expand Up @@ -1887,44 +1853,6 @@ mod tests {
assert_eq!(error.location(), &cols(34, 47));
}

#[test]
fn test_define_too_many_fields() {
let mut state = State::new(Config::new());
let string = Class::alloc(
&mut state.db,
"String".to_string(),
ClassKind::Regular,
Visibility::Public,
ModuleId(0),
Location::default(),
);
let mut input = "class Person {".to_string();

for i in 0..260 {
let _ = write!(input, "\nlet @{}: String", i);
}

input.push_str("\n}");

let mut modules = parse(&mut state, input);
let module = ModuleId(0);

module.new_symbol(
&mut state.db,
"String".to_string(),
Symbol::Class(string),
);

DefineTypes::run_all(&mut state, &mut modules);

assert!(!DefineFields::run_all(&mut state, &mut modules));
assert_eq!(state.diagnostics.iter().count(), 1);

let diag = state.diagnostics.iter().next().unwrap();

assert_eq!(diag.id(), DiagnosticId::InvalidType);
}

#[test]
fn test_define_field_with_self_type() {
let mut state = State::new(Config::new());
Expand Down
58 changes: 12 additions & 46 deletions compiler/src/type_check/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ use types::{
};

const IGNORE_VARIABLE: &str = "_";
const STRING_LITERAL_LIMIT: usize = u32::MAX as usize;
const CONST_ARRAY_LIMIT: usize = u16::MAX as usize;

/// The maximum number of methods that a single class can define.
///
Expand Down Expand Up @@ -1022,14 +1020,6 @@ impl<'a> CheckConstant<'a> {
&mut self,
node: &mut hir::ConstStringLiteral,
) -> TypeRef {
if node.value.len() > STRING_LITERAL_LIMIT {
self.state.diagnostics.string_literal_too_large(
STRING_LITERAL_LIMIT,
self.file(),
node.location,
);
}

node.resolved_type = TypeRef::string();
node.resolved_type
}
Expand Down Expand Up @@ -1170,18 +1160,6 @@ impl<'a> CheckConstant<'a> {
}
}

if types.len() > CONST_ARRAY_LIMIT {
self.state.diagnostics.error(
DiagnosticId::InvalidConstExpr,
format!(
"constant arrays are limited to at most {} values",
CONST_ARRAY_LIMIT
),
self.file(),
node.location,
);
}

// Mutating constant arrays isn't safe, so they're typed as `ref
// Array[T]` instead of `Array[T]`.
let ary = TypeRef::Ref(TypeId::ClassInstance(
Expand Down Expand Up @@ -1502,32 +1480,20 @@ impl<'a> CheckMethodBody<'a> {
scope: &mut LexicalScope,
) -> TypeRef {
for value in &mut node.values {
match value {
hir::StringValue::Expression(v) => {
let val = self.call(v, scope, false);
let hir::StringValue::Expression(v) = value else { continue };
let val = self.call(v, scope, false);

if val != TypeRef::Error && !val.is_string(self.db()) {
self.state.diagnostics.error(
DiagnosticId::InvalidType,
format!(
"expected a 'String', 'ref String' or \
if val != TypeRef::Error && !val.is_string(self.db()) {
self.state.diagnostics.error(
DiagnosticId::InvalidType,
format!(
"expected a 'String', 'ref String' or \
'mut String', found '{}' instead",
format_type(self.db(), val)
),
self.file(),
v.location,
);
}
}
hir::StringValue::Text(node) => {
if node.value.len() > STRING_LITERAL_LIMIT {
self.state.diagnostics.string_literal_too_large(
STRING_LITERAL_LIMIT,
self.file(),
node.location,
);
}
}
format_type(self.db(), val)
),
self.file(),
v.location,
);
}
}

Expand Down
6 changes: 0 additions & 6 deletions types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,6 @@ pub const ENUM_TAG_INDEX: usize = 0;
/// class.
pub const CONSTRUCTORS_LIMIT: usize = u16::MAX as usize;

/// The maximum number of fields a class can define.
pub const FIELDS_LIMIT: usize = u8::MAX as usize;

/// The maximum number of values that can be stored in an array literal.
pub const ARRAY_LIMIT: usize = u16::MAX as usize;

/// The maximum number of methods supported.
///
/// This is one less than the u32 maximum such that we can use `u32::MAX` as a
Expand Down

0 comments on commit 6f8a503

Please sign in to comment.