Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug?]: Inconsistency with c_array documentation and c_array behavior w.r.t. coercion to c_ptr #25059

Open
lydia-duncan opened this issue May 16, 2024 · 2 comments

Comments

@lydia-duncan
Copy link
Member

Summary of Problem

Description:
I'm not sure how much of this is user error on my part, but I'm having difficulty using a c_array as though it was a c_ptr for the purpose of calling string.createCopyingBuffer (which accepts a c_ptr or a c_ptrConst).

The documentation for c_array says:

A variable of type c_array can coerce to a c_ptr with the same element type. In that event, the pointer will be equivalent to c_ptrTo(array[0]).

And the documentation for coercions says:

An implicit conversion for a function call - also called a coercion - occurs when the actual argument of a function call is converted to the type of the corresponding formal argument, if the formal’s intent is param, in, const in, const, or the default intent.

Given that the argument for string.createCopyingBuffer uses the default intent, my expectation based on these two paragraphs is that I should be able to pass a c_array to that function without an explicit cast. However, when I try to do so, I get an unresolved call error. I think this means that either the documentation or the compiler needs to be updated.

Is this a blocking issue with no known work-arounds?
No. I encountered this while writing an example for another user (so nothing in work I was doing myself) and it looks like an explicit cast may be okay (though I'm having other difficulties that could also just be user error on my part, so I can't verify that the cast works at execution time until I figure those out).

Steps to Reproduce

Source Code:

// <some valid code to create a c_array named cArr>
var str = string.createCopyingBuffer(cArr);

Compile command:
chpl foo.chpl

Execution command:
N/A

Associated Future Test(s):
TBD

Configuration Information

  • Output of chpl --version: 2.1.0 pre-release
  • Output of $CHPL_HOME/util/printchplenv --anonymize: Any, this is a compiler error
  • Back-end compiler and version, e.g. gcc --version or clang --version: Any, this is a compiler error
  • (For Cray systems only) Output of module list: N/A
@lydia-duncan
Copy link
Member Author

I've tried four different ways to create the c_array in Chapel code (instead of creating it in C code and obtaining it that way, which I think would probably be easier to do at this point), but none of them have worked. Recording them here for myself when I get back to submitting a test to the test system:

Attempt 1:

var cArr = new c_array(c_char, 5);
cArr[0] = "a": c_char;
cArr[1] = "b": c_char;
cArr[2] = "c": c_char;
cArr[3] = "d": c_char;
cArr[4] = "e": c_char;

Output:

uncaught IllegalArgumentError: bad cast from string 'a' to int(8)

Attempt 2:

var cArr: c_array(c_char, 5) = c_ptrToConst("abcde");

Output:

error: could not find a copy initializer ('init=') for type 'c_array(int(8),5)' from type 'c_ptrConst(uint(8))'

Attempt 3:

var cArr = new c_array(c_uchar, 5);
  cArr = c_ptrToConst("abcde");

Output:

 error: Cannot assign to c_array(int(8),5) from c_ptrConst(uint(8))

Attempt 4:

var cArr = new c_array(c_uchar, 5);
cArr[0] = "a": c_uchar;
cArr[1] = "b": c_uchar;
cArr[2] = "c": c_uchar;
cArr[3] = "d": c_uchar;
cArr[4] = "e": c_uchar;

Output (at execution time):

uncaught IllegalArgumentError: bad cast from string 'a' to uint(8)

@bradcray
Copy link
Member

I haven't gotten far enough to try reproducing the original issue yet, but with a quick look, I wonder whether the issue is that the argument to createBorrowingBuffer is generic, and we don't support coercions to generic arguments?

In attempt 1, recall that since Chapel strings can be UTF-8 and arbitrary length (i.e., we don't have a char type), you need to use a technique to specifically grab out the singleton byte if there is one. For example, string.toByte() is one such approach: https://chapel-lang.org/docs/language/spec/strings.html#String.string.toByte Here's approach one updated to address that on ATO

Oh, except then I'm not sure why approach 4 got through compilation… that's pretty surprising to me.

It makes sense that approach 2 doesn't work to me because it's effectively requesting a copy from a pointer to an array. For example, C similarly wouldn't support: char str[5] = myCharStarPtr; [ATO]. You'd need to use a memcpy() to get from one to the other [ATO]. We could arguably add an initializer that would do this conversion, but it'd be supporting a pattern that C doesn't (which is what I think of the c_array and c_ptr types as trying to do).

Approach 3 seems equivalent to approach 2.

Here's a proposed approach to writing the pattern: [ATO]

use CTypes, OS.POSIX;

var cArr = new c_array(c_char, 6);

memcpy(cArr, c_ptrToConst(b"abcde"), 6);

extern proc printf(in x...);
printf("%s", cArr);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants