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

Diplomat: delete default constructor in C++ for transparent structs #2522

Closed
echeran opened this issue Sep 6, 2022 · 10 comments
Closed

Diplomat: delete default constructor in C++ for transparent structs #2522

echeran opened this issue Sep 6, 2022 · 10 comments
Labels
A-ffi Area: FFI, WebAssembly, Transpilation C-ffi-infra Component: Diplomat, horizontal FFI

Comments

@echeran
Copy link
Contributor

echeran commented Sep 6, 2022

Background

When writing tests for Diplomat code added for Collator, a problem occurred with the new CollatorOptions. Currently, CollatorOptions is an options bag struct in Rust that meant to be mutated directly before passed to a constructor. Int Diplomat, it gets transpiled to a transparent struct in C++. The generated C++ code looks like:

struct ICU4XCollatorOptions {
 public:
  ICU4XCollatorStrength strength;
  ICU4XCollatorAlternateHandling alternate_handling;
  ICU4XCollatorCaseFirst case_first;
  ICU4XCollatorMaxVariable max_variable;
  ICU4XCollatorCaseLevel case_level;
  ICU4XCollatorNumeric numeric;
  ICU4XCollatorBackwardSecondLevel backward_second_level;
};

Then, in my test code, I wrote the faulty code

...
  ICU4XLocale locale = ICU4XLocale::create("en").ok().value();
  ICU4XCollatorOptions options;
  ICU4XCollator collator = ICU4XCollator::try_new(dp, locale, options).ok().value();
  ICU4XOrdering actual = collator.compare(manna, manana);
...

"Faulty" as in, it caused segmentation faults because ICU4XCollatorOptions options; was not being initialized, as the valgrind utility pointed out.

Proposal

Instead we want:

struct ICU4XCollatorOptions {
  ICU4XCollatorOptions() = delete;
 public:
...
};

This disallows the default constructor, which forces users to initialize all fields of a transparent struct upfront when instaniating it anew. Then, they would be forced to do the safe thing in the calling code:

...
  ICU4XLocale locale = ICU4XLocale::create("en").ok().value();
  ICU4XCollatorOptions options {
    strength: ICU4XCollatorStrength::Auto,
    alternate_handling: ICU4XCollatorAlternateHandling::Auto,
    case_first: ICU4XCollatorCaseFirst::Auto,
    max_variable: ICU4XCollatorMaxVariable::Auto,
    case_level: ICU4XCollatorCaseLevel::Auto,
    numeric: ICU4XCollatorNumeric::Auto,
    backward_second_level: ICU4XCollatorBackwardSecondLevel::Auto,
  };
  ICU4XCollator collator = ICU4XCollator::try_new(dp, locale, options).ok().value();
...
@sffc
Copy link
Member

sffc commented Sep 6, 2022

Ideally we should be able to make the default constructor populate the fields with default values. But in the short term it may be advisable to delete the default constructor since it creates uninitialized memory.

@Manishearth
Copy link
Member

Yes, let's do that.

@Manishearth
Copy link
Member

Actually, wait, why is this broken? Each of these is an enum with a zero value of Auto, no? C++ ought to be generating the right default initializer here?

At least, that was the intent: we do this with options bags elsewhere too.

@sffc
Copy link
Member

sffc commented Sep 6, 2022

POD types like enums and integers are undefined until you set them in C++.

@sffc
Copy link
Member

sffc commented Sep 6, 2022

If we want C++ to initialize the values to zero, that's code we need to write (or which Diplomat needs to generate).

@sffc
Copy link
Member

sffc commented Sep 6, 2022

I think what we should do is:

  1. In docs, encourage people to use the initializer syntax ICU4XCollatorOptions options = {};
  2. Delete the default constructor to prevent ICU4XCollatorOptions options; which creates unitialized memory and easily creates undefined behavior

@Manishearth
Copy link
Member

Ah, right, {} is different from the default constructor. Let's do that then.

@Manishearth
Copy link
Member

Hmm, I tried doing this and it disables brace-initialization like return ICU4XFixedDecimalFormatOptions{ .grouping_strategy = ......}

@sffc sffc added A-ffi Area: FFI, WebAssembly, Transpilation C-ffi-infra Component: Diplomat, horizontal FFI labels Oct 17, 2022
@sffc
Copy link
Member

sffc commented Oct 17, 2022

@Manishearth Make sure this issue is tracked correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ffi Area: FFI, WebAssembly, Transpilation C-ffi-infra Component: Diplomat, horizontal FFI
Projects
None yet
Development

No branches or pull requests

3 participants