Do structs inside Box::new need curly braces - rust

Do empty structures inside Box::new() need curly braces? If not, is there a preferred style?
struct Empty;
// are these equivalent?
fn get_empty_box() -> Box<Empty> {
Box::new(Empty)
}
fn get_empty_box_alt() -> Box<Empty> {
Box::new(Empty {})
}

Depends on how they are defined.
If they are defined as struct Foo {} then yes.
If they are defined as struct Foo(); then they need parentheses or braces, but it's uncommon to see them with braces.
If they're defined as struct Foo; then they don't need braces (although they can accept them) and usually instantiated without braces.
The technical reason for that is that struct Foo; defines, in addition to the struct itself, a constant with the same name that contains an instance of the struct. That is, const Foo: Foo = Foo {};. When you spell Foo without braces you just copy this constant.
In a similar fashion, tuple structs (struct Foo();) define, in addition to the struct itself, a function that instantiates it: fn Foo() -> Foo { Foo {} }.

Related

How to `use` function scoped structs?

Consider the following contrived example:
mod Parent {
fn my_fn() {
struct MyStruct;
mod Inner {
use super::MyStruct; //Error: unresolved import `super::MyStruct`. No `MyStruct` in `Parent`
}
}
}
How can I import MyStruct here from the inner module?
Motivation
While the above is code that you'll never write manually, it is code that is useful to generate. A real-world use-case would be a derive-macro. Let's say I want this:
#[derive(Derivative)]
struct MyStruct;
Now it's useful to isolate the generated code in its own module, to isolate the generated code from the source code (e.g. to avoid naming collisions, leaking of use declarations, etc.). So I want the generated code to be something like this:
mod _Derivative_MyStruct {
use super::MyStruct;
impl Derivative for MyStruct { }
}
However, the example above fails if the struct is defined in a function, due to the problem at the top. e.g. this won't work:
fn my_fn() {
#[derive(Derivative)];
struct MyStruct;
}
as it expands into:
fn my_fn() {
#[derive(Derivative)];
struct MyStruct;
mod _Derivative_MyStruct {
use super::MyStruct; // error
impl Derivative for MyStruct {}
}
}
This is especially troublesome for doctests, as these are implicitly wrapped in a function. E.g. this will give the unresolved import problem:
/// Some interesting documentation
/// ```
/// #[derive(Derivative)]
/// struct MyStruct;
/// ```
Without the ability to refer to the outer scope, I either need to give up isolation, or require wrapping in modules at the call site. I'd like to avoid this.
This is issue #79260. I don't think there is a solution.
However, you can define the nested items inside an unnamed const (const _: () = { /* code */ };) instead of a module. This prevents name collisions and is the idiomatic thing to do in macros that need to define names. Do note however that this does not have a way to refer to items inside the const from outside it.

Why do curly braces for struct instantiation not define a scope?

I have the following code I am surprised works:
struct S<'a> {
value: &'a String,
}
fn foo(s: &S) {
println!("{}", s.value);
}
#[allow(dead_code)]
fn main() {
let s = S {
value: &String::from("ABC"),
};
foo(&s);
}
If I see a pair of curly braces, I imagine them as a scope. So for me, the line S { value: &String::from("ABC") }; and, more importantly, the part between the curly braces represents a scope. Inside this scope, an anonymous string is created and a reference to it is taken. After the brace is closed, the string should be destroyed and the next line foo(&s) should tell me something about lifetimes, but this is not the case! Why?
In Rust, curly braces for structs do not denote a scope, simply the fields of a struct. It's like how you can use curly braces when invoking a macro, but those curly braces do not create a scope. If they do create a scope, it would be incredibly inconvenient, as you couldn't do something like &String::from("ABC").

Writing a Rust struct type that contains a string and can be used in a constant

I'm getting started with Rust. I want to have a struct that contains (among other things) a string:
#[derive(Clone, Debug)]
struct Foo {
string_field: &str, // won't compile, but suppose String or Box<str> or &'a str or &'static str...
}
And I want to be able to declare constants or statics of it:
static FOO1: Foo = Foo {
string_field: "",
};
And I also want to be able to have it contain a string constructed at runtime:
let foo2 = Foo {
string_field: ("a".to_owned() + "b").as_str(),
};
I could add a lifetime parameter to Foo so that I can declare that the string reference has the same lifetime. That's fine, except that it then seems to require an explicit lifetime parameter for everything that contains a Foo, which means that it complicates the rest of my program (even parts that don't care about being able to use constant expressions).
I could write
enum StringOfAdequateLifetime {
Static(&'static str),
Dynamic(Box<str>), // or String, if you like
}
struct Foo {
string_field: StringOfAdequateLifetime,
}
and that seems to work so far but clutters up writing out literal Foos.
It seems obvious enough that the desired runtime behavior is sound: when you drop a Foo, drop the string it contains — and if it's static it's never dropped, so no extra information is needed to handle the two cases. Is there a clean way to ask Rust for just that?
(It seems like what I could use is some kind of "smart pointer" type to hold the string that can also be written as a constant expression for the static case, but I haven't seen one in the standard library, and when I tried to genericize StringOfAdequateLifetime to apply to any type, I ran into further complications with implementing and using the various standard traits like Deref, which I suspect were due to something about the differences between Sized and non-Sized types.)
The rust standard library has a built-in type for this exact use case, Cow. It's an enum that can represent either a reference or an owned value, and will clone the value if necessary to allow mutable access. In your particular use case, you could define the struct like so:
struct Foo {
string_field: Cow<'static, str>
}
Then you could instantiate it in one of two ways, depending on whether you want a borrowed constant string or an owned runtime-constructed value:
const BORROWED: Foo = Foo { string_field: Cow::Borrowed("some constant") };
let owned = Foo { string_field: Cow::Owned(String::from("owned string")) };
To simplify this syntax, you can define your own constructor functions for the type using a const fn to allow using the borrowed constructor in a constant context:
impl Foo {
pub const fn new_const(value: &'static str) -> Self {
Self { string_field: Cow::borrowed(value) }
}
pub fn new_runtime(value: String) -> Self {
Self { string_field: Cow::Owned(value) }
}
}
This allows you to use a simpler syntax for initializing the values:
const BORROWED: Foo = Foo::new_const("some constant");
let owned = Foo::new_runtime(String::from("owned string"));

How to store a struct into a variable in Rust?

Rust allows declaring a structure inside a function but it doesn't allow assigning a variable with it in a simple way.
fn f1() -> (something) {
struct mystruct {
x: i32,
}
let s = mystruct;
s
}
fn f2(s: something) {
let obj = s { x: 5 };
println!(obj.x);
}
fn main() {
let s = f1();
f2(s);
}
Is it possible to store a struct into a variable in a different way? How do I write the struct type correctly? In my project, I want to declare a struct inside a function and create instances inside of another one.
How to store a struct into a variable in Rust?
Rust is a statically typed language, and as such it is not possible to store a type into a variable, then use this variable to construct an instance of the type.
This is the reason you are not able to express what the type of s is; there is simply no vocabulary in the language for this.
Depending on what you want to do, you may wish to look into:
Generics: fn f2<T: Default>() would allow creating an instance of any type T implementing the Default trait.
Run-time polymorphism: A factory function FnOnce(i32) -> Box<Trait> could produce an instance of any type implementing Trait from a i32.

How do I specify a generic type where one of the types is not needed?

I'm trying to use a generic datatype where one of the types is not needed (edge weights in a graph). I've been thinking to use the never type for this, which would look something like this:
#![feature(never_type)]
struct Foo<T> {
bar: T
}
impl<T> Foo<T> {
fn foo(&mut self, bar: T) {
self.bar = bar;
}
}
fn main() {
let mut foo: Foo<!> = Foo { bar: "nada" };
foo.foo("nada");
}
This obviously results in a type-mismatch for the "nada" placeholders, but just typing nothing will cause other errors. Is ! the right type to use here, and if so, what's the correct syntax?
I've gotten it to work using () instead of !, but I'm a bit unsure as to whether that's the proper choice of type. I believe in terms of efficiency it should make no difference, as () has no memory footprint?
() is the right choice. It is a type with a single value (also named ()), so it has a value, but contains no information.
! doesn't have any value, so if you put it in a struct the struct type doesn't have a value either and is basically unusable.

Resources