aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-03 10:08:05 +0200
committerEugen Wissner <belka@caraus.de>2026-10-03 10:08:05 +0200
commit5d808dd4c4003968bbdf180e1e1193231db5d43b (patch)
tree6391fc8990790288e76dc8eb6ff7b1a6872dab26
parent2ea84997ae37517729c3c8ed3af8a000bdc632df (diff)
downloadelna-5d808dd4c4003968bbdf180e1e1193231db5d43b.tar.gz
Strip outmost constness on infered arguments
-rw-r--r--boot/symbol.cc11
-rw-r--r--boot/type_check.cc10
-rw-r--r--include/elna/boot/symbol.h8
-rw-r--r--source/common.elna11
-rw-r--r--testsuite/compilable/generic_const_inference.elna28
-rw-r--r--testsuite/compilable/generic_inference.elna2
6 files changed, 54 insertions, 16 deletions
diff --git a/boot/symbol.cc b/boot/symbol.cc
index 2293275..e247bdb 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -572,6 +572,17 @@ namespace elna::boot
}
}
+ type unqualify(const type& subject)
+ {
+ type current = subject;
+
+ while (const auto constant = resolve_aliases(current).get<constant_type>())
+ {
+ current = constant->unqualified;
+ }
+ return current;
+ }
+
type unwrap_aliases(const type& checked)
{
if (const auto alias = checked.get<alias_type>())
diff --git a/boot/type_check.cc b/boot/type_check.cc
index ea0bcd5..42e7227 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -1159,9 +1159,11 @@ namespace elna::boot
else if (const auto left_constant = left.get<constant_type>())
{
const std::shared_ptr<constant_type> right_constant = right.get<constant_type>();
+ const type right_unqualified = right_constant != nullptr
+ ? right_constant->unqualified
+ : right;
- return right_constant != nullptr
- && bind_arguments(parameters, bindings, left_constant->unqualified, right_constant->unqualified);
+ return bind_arguments(parameters, bindings, left_constant->unqualified, right_unqualified);
}
else if (const auto left_instance = left.get<instantiated_type>())
{
@@ -1334,8 +1336,10 @@ namespace elna::boot
while (argument_iterator != std::cend(call.arguments)
&& declared_iterator != std::cend(procedure.symbol.parameters))
{
+ const type actual = unqualify((*argument_iterator)->type_decoration);
+
if (!bind_arguments(procedure.parameters, bindings,
- *declared_iterator, (*argument_iterator)->type_decoration))
+ *declared_iterator, actual))
{
add_error<generic_error>((*argument_iterator)->position(), reference.name,
generic_error::shape_mismatch{
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index fd56d98..31d5c45 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -679,6 +679,14 @@ namespace elna::boot
type resolve_underlying_type(const std::shared_ptr<alias_type>& alias);
/**
+ * Resolves outer type qualifiers while preserving non-qualified aliases.
+ *
+ * \param subject The type to unqualify.
+ * \return The unqualified type.
+ */
+ type unqualify(const type& subject);
+
+ /**
* Resolves an alias chain until the underlying type or a qualified type is
* reached.
*
diff --git a/source/common.elna b/source/common.elna
index e31def8..4579a67 100644
--- a/source/common.elna
+++ b/source/common.elna
@@ -18,18 +18,14 @@ proc write*(fd: Int; buf: Pointer; Word: Int) -> Int
extern
proc write_s*(value: []const Word8)
-begin
- (* fwrite(cast(value.ptr: Pointer), value.length, 1u, stdout) *)
write(1, cast(value.ptr: Pointer), cast(value.length: Int))
return
proc write_z*(value: ^Word8)
-begin
write(1, cast(value: Pointer), cast(strlen(value): Int))
return
proc write_b*(value: Bool)
-begin
if value then
write_s("true")
else
@@ -38,7 +34,6 @@ begin
return
proc write_c*(value: Word8)
-begin
putchar(cast(value: Int));
fflush(nil)
return
@@ -68,15 +63,9 @@ begin
return
proc write_u*(value: Word)
-begin
write_i(cast(value: Int))
return
-proc free_and_nil*(pointer: Pointer) -> Pointer
-begin
- free(pointer)
-return nil
-
(* Returns true or false depending whether two strings are equal. *)
proc string_compare*(lhs_pointer: ^Word8; lhs_length: Word; rhs_pointer: []const Word8) -> Bool
var
diff --git a/testsuite/compilable/generic_const_inference.elna b/testsuite/compilable/generic_const_inference.elna
new file mode 100644
index 0000000..a9fc41f
--- /dev/null
+++ b/testsuite/compilable/generic_const_inference.elna
@@ -0,0 +1,28 @@
+program()
+type
+ ConstAlias = const ^Word8
+ BasePtr = ^Word8
+ NestedConst = const BasePtr
+
+var
+ slice: []const Word8
+ aliased: ConstAlias := nil
+ nested: NestedConst := nil
+ direct_const: const ^Word8 := nil
+
+proc write#[T](fd: Int; buf: T; count: Int) -> Int
+return 0
+
+proc write_const#[T](fd: Int; buf: const T; count: Int) -> Int
+return 0
+
+begin
+ write(1, slice.ptr, cast(slice.length: Int));
+ write(1, aliased, 0);
+ write(1, nested, 0);
+ write(1, direct_const, 0);
+ write_const(1, slice.ptr, cast(slice.length: Int));
+ write_const(1, aliased, 0);
+ write_const(1, nested, 0);
+ write_const(1, direct_const, 0)
+end.
diff --git a/testsuite/compilable/generic_inference.elna b/testsuite/compilable/generic_inference.elna
index ab1ff3a..860eab1 100644
--- a/testsuite/compilable/generic_inference.elna
+++ b/testsuite/compilable/generic_inference.elna
@@ -15,12 +15,10 @@ var
b: Word8
proc store#[T](target: ^Cell#[T]; value: T)
-begin
target^.held := value
return
proc relay#[T](target: ^Cell#[T]; value: T)
-begin
store(target, value)
return