From 5d808dd4c4003968bbdf180e1e1193231db5d43b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 3 Oct 2026 10:08:05 +0200 Subject: Strip outmost constness on infered arguments --- boot/symbol.cc | 11 +++++++++ boot/type_check.cc | 10 +++++--- include/elna/boot/symbol.h | 8 +++++++ source/common.elna | 11 --------- testsuite/compilable/generic_const_inference.elna | 28 +++++++++++++++++++++++ testsuite/compilable/generic_inference.elna | 2 -- 6 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 testsuite/compilable/generic_const_inference.elna 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()) + { + current = constant->unqualified; + } + return current; + } + type unwrap_aliases(const type& checked) { if (const auto alias = checked.get()) 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()) { const std::shared_ptr right_constant = right.get(); + 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()) { @@ -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((*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 @@ -678,6 +678,14 @@ namespace elna::boot /// \overload type resolve_underlying_type(const std::shared_ptr& 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 -- cgit v1.2.3