GithubHelp home page GithubHelp logo

Comments (11)

greyblake avatar greyblake commented on August 15, 2024 2

@schneiderfelipe hi!

is there a way to build const values at present?
Unfortunately no

Correct me if I'm wrong, but new_unchecked doesn't seem to be const either:
You're right, it does not.

One of the challenges with const is that it doesn't allow any arbitrary rust code. So to say, when we generate ::new const function, we have to be sure that everything what is within is const-compliant, but it is not very easy.

It's practically impossible to say upfront if a generated implementation will be const-compliant or not.

In order to avoid situation when nutype generates code with const fn new(), but by some reason, the new function cannot be const, I'd prefer either to introduce an extra attribute to the nutype macro, so users have control over that attribute.

from nutype.

greyblake avatar greyblake commented on August 15, 2024 1

@schneiderfelipe

For your example to compile MyType::new must be defined as const fn new(..), which is not the case at the moment (new_unchecked does not help here)

from nutype.

helgoboss avatar helgoboss commented on August 15, 2024 1

I have the same use case as @schneiderfelipe and I think new_unchecked would help here. The body of the new_unchecked function doesn't contain any validation logic, it just wraps the given value into the newtype. As a result it can be trivially made const, which would make it usable for associated constants. I don't think doing that would break any existing code.

Having associated constants can be very useful. I would love to migrate my newtypes (with existing constants) to nutype but not being able to migrate the constants turns out to be a showstopper.

from nutype.

greyblake avatar greyblake commented on August 15, 2024 1

@helgoboss It's not that simple as it may seems.

  1. You don't wanna use nutype to easily avoid the validation constraints (if that's your case, you don't need nutype at all)
  2. Having const fn works very well for non-heap allocated things (like i32 or f64). It will not compile with String.

from nutype.

schneiderfelipe avatar schneiderfelipe commented on August 15, 2024

@greyblake is there a way to build const values at present? Correct me if I'm wrong, but new_unchecked doesn't seem to be const either:

/// Creates a value of type skipping the sanitization and validation
/// rules. Generally, you should avoid using `::new_unchecked()` without a real need.
/// Use `::new()` instead when it's possible.
pub unsafe fn new_unchecked(inner_value: #inner_type) -> #type_name {
#type_name(inner_value)
}

from nutype.

schneiderfelipe avatar schneiderfelipe commented on August 15, 2024

I understand. +1 for having users control whether ::new is const.

What about new_unchecked? It looks to me it could be const by default, what do you think?

from nutype.

greyblake avatar greyblake commented on August 15, 2024

I am not sure why you're asking about new_unchecked again, it looks like you misunderstand it.
Please read Breaking constraints with new_unchecked

new_unchecked is to have a loophole to bypass sanitizers and validators (which I don't recommend normally).

It has nothing to do with const functions. It won't work for heap allocated types (e.g. String or anything else).

So if we take a very simplified code similar to what nutype generates:

struct Email(String);

impl Email {
    const fn new(email: &str) -> Email {
        Email(email.to_string())
    }
}

This won't compile:

error[E0015]: cannot call non-const fn `<str as ToString>::to_string` in constant functions
 --> src/main.rs:7:21
  |
7 |         Email(email.to_string())
  |                     ^^^^^^^^^^^
  |

@schneiderfelipe I am not sure what you're doing, but I guess you can just use either

So going forward with the Email example, the following code works as expected.

use nutype::nutype;
use once_cell::sync::Lazy;

#[nutype(
    sanitize(trim, lowercase),
    validate(not_empty, len_char_max = 50),
    derive(Debug, PartialEq, Clone, Display),
)]
struct Email(String);

static DEFAULT_EMAIL: Lazy<Email> =
    Lazy::new(|| Email::new("[email protected]").unwrap());

fn main() {
    println!("Default email is {}", *DEFAULT_EMAIL);
}

DEFAULT_EMAIL is initialized only once on start.

from nutype.

schneiderfelipe avatar schneiderfelipe commented on August 15, 2024

Sorry, I may have mixed up things and I should have mentioned my use case from the start.

I would like to fill up an associated const value to my type, so I would be building values up at compile time, e.g.,

impl MyType {
    const my_value: MyType = MyType::new_([1, 2, 3]);
    // ...
}

I'm 100% sure those initializations won't break invariants. Since new is not const, I was expecting some other way of initializing those values at compile-time and new_unchecked just came to mind. Is there a way to do that?

from nutype.

greyblake avatar greyblake commented on August 15, 2024

But I see a demand for that. A solution could be at least partial support of const fn, where it's possible.

from nutype.

helgoboss avatar helgoboss commented on August 15, 2024

Thanks for considering it. BTW, at this occasion, I really love the idea of nutype and how it's implemented. It makes writing robust and coherent newtypes much easier.

  1. You don't wanna use nutype to easily avoid the validation constraints (if that's your case, you don't need nutype at all)

I'm aware that new_unchecked is a compromise. I would certainly prefer new for this use case but there's no way to make it const at the moment (hopefully one day).

I appreciate that you want to make it hard to construct invalid types. On the other hand ... having some well-defined popular constants (with the author of the crate "promising" that they are correct) can actually contribute to safety for the consumers of this crate because constants can be used basically everywhere and are very convenient to use.

  1. Having const fn works very well for non-heap allocated things (like i32 or f64). It will not compile with String.

Declaring the function as const is not a problem, even if it takes a String argument. It compiles. What you can't do is actually using the function from a const context, simply because there's no way to create a const String. But I don't think that hurts.

I think adding a const is all it takes to make this work. Tried it with my own newtypes including a String wrapper:

helgoboss@e9f2538#diff-a50c55e38c78545fe73f1b3fb129600fd97bb29ce5e2afd4b95f5940132bcd12R17

from nutype.

helgoboss avatar helgoboss commented on August 15, 2024

A potential alternative would be to add a dedicated syntax for adding associated constants and checking the validity of the wrapped values in the same way as the default value is checked at the moment (a unit test).

from nutype.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.