How to use Rust structs from other mods - rust

I defined a structure in a separate file. When I want to use this I do something like this at the top of the file:
use other_file::StructName;
mod other_file;
When I created a function that uses
fn test(other : StructName) {};
I get a warning about using a private type, which is fixed when I use
fn test(other : other_file::StructName) {};
This requires a lot of extra typing though. I can also reexport the module with pub use but I would really like to keep it hidden.
How do I correctly include modules to save typing? The Python equivalent to what I want is
from other_file import StructName
The following code explains this in two files. It is a stripped down version of some matrix math utils.
geometry.rs:
use geometry::{Vec3};
mod geometry;
#[deriving(Eq, Clone, Show)]
pub struct Mat4 {
data : ~[f32]
}
impl Mat4 {
fn apply_Vec3(&self, other : &Vec3) -> Vec3{
let x = self.data[0] * other.x + self.data[1] * other.y + self.data[2] * other.z;
let y = self.data[4] * other.x + self.data[5] * other.y + self.data[6] * other.z;
let z = self.data[8] * other.x + self.data[9] * other.y + self.data[10]* other.z;
Vec3::new(x, y, z)
}
}
#[deriving(Eq, Clone, Show)]
pub struct Transform {
mat : Mat4
}
impl Transform {
pub fn apply_Vec3(&self, vec : &Vec3) -> Vec3 {
self.mat.apply_Vec3(vec)
}
}
transform.rs:
#[deriving(Eq, Clone, Show)]
pub struct Vec3 {
x : f32,
y : f32,
z : f32
}
impl Vec3 {
pub fn new(x : f32, y : f32, z : f32) -> Vec3 {
Vec3{x : x, y : y, z : z}
}
}
When compiling with rustc --test transform.rs I get two errors:
transform.rs:25:39: 25:43 warning: private type in exported type signature, #[warn(visible_private_types)] on by default
transform.rs:25 pub fn apply_Vec3(&self, vec : &Vec3) -> Vec3 {
^~~~
transform.rs:25:48: 25:52 warning: private type in exported type signature, #[warn(visible_private_types)] on by default
transform.rs:25 pub fn apply_Vec3(&self, vec : &Vec3) -> Vec3 {
^~~~

I'm assuming that you're actually returning an other_file::StructName; you wouldn't get that warning otherwise.
The problem is that from somewhere else, you can't actually access the type for other_file::StructName. As you are accessing it, I presume that StructName is public, but that's not enough for things outside this module to access it: the module other_file needs to be public as well.
Replace
mod other_file;
with
pub mod other_file;
Your use statement is correct and does indeed correspond to the Python from x import y statement. (Approximately only; it's an absolute path unless self or super come into it—those that would be .foo or ..foo in Python.)

In Rust, everything is private by default with only a few exceptions; see Visibility and Privacy in the docs for more information. So, the problem is perhaps that your struct StructName is private to the other_file module.
If you declare the struct as public in b.rs:
pub struct StructName {x: int, y: int}
You can successfully use it in a.rs as you wrote:
use b::StructName;
mod b;
fn test (s: StructName) -> int {return s.x + s.y;}
fn main () {
let s = StructName {x: 1, y: 2};
let t = test (s);
println! ("{:i}", t);
}
This successfully compiles with Rust 0.9 and outputs 3.

Related

Nativecall Segfaults Getting Tuple from Rust

Per the Rust FFI Omnibus the following should work.
This is a rust cdylib lib.rs named "foo" made with cargo build...
use std::convert::From;
// Rust FFI Omnibus: Tuples
// http://jakegoulding.com/rust-ffi-omnibus/tuples/
// A Rust function that accepts a tuple
fn flip_things_around_rust(tup: (u32, u32)) -> (u32, u32) {
let (a, b) = tup;
(b + 1, a - 1)
}
// A struct that can be passed between C and Rust
#[repr(C)]
pub struct Tuple {
x: u32,
y: u32,
}
// Conversion functions
impl From<(u32, u32)> for Tuple {
fn from(tup: (u32, u32)) -> Tuple {
Tuple { x: tup.0, y: tup.1 }
}
}
impl From<Tuple> for (u32, u32) {
fn from(tup: Tuple) -> (u32, u32) {
(tup.x, tup.y)
}
}
// The exported C method - ORIG
//#[no_mangle]
//pub extern "C" fn flip_things_around(tup: Tuple) -> Tuple {
// flip_things_around_rust(tup.into()).into()
//}
// The exported C method - EDIT per Christoph
#[no_mangle]
pub extern "C" fn flip_things_around(tup: Tuple) -> *const Tuple {
&flip_things_around_rust(tup.into()).into()
}
And this is the raku script ffi-omnibus.raku that consumes the library via Nativecall
use NativeCall;
constant $n-path = './ffi-omnibus/target/debug/foo';
## Rust FFI Omnibus: Tuples
## http:##jakegoulding.com/rust-ffi-omnibus/tuples/
class Tuple is repr('CStruct') {
has uint32 $.x;
has uint32 $.y;
}
sub flip_things_around(Tuple) returns Tuple is native($n-path) { * }
my \initial = Tuple.new( x => 10, y => 20 );
my \result = flip_things_around(initial);
dd result;
say result.x, result.y;
There are 6 types of examples in the Rust FFI Omnibus and this is the only one that I cannot debug. It kinda works if you remove the returns Tuple and just have a Tuple argument, but no return type.
I have made a DRAFT raku module over here that has simple guidance of how to set this up (Dockerfile, cargo new ...) so you can just git clone https://github.com/p6steve/raku-Inline-Rust.git and uncomment the failing code in these two files.
Oh, and the error is Segmentation fault (core dumped) (on ubuntu)
Welcome to Rakudo™ v2022.04.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.04.
Any help / guidance much appreciated!
EDIT - Thanks to Christoph comment the segfault is now fixed.
BUT - I now have a new issue, the result is jumbled like this:
Tuple.new(x => 4252849424, y => 65535) #I added a dd
425284942465535
So looks like there is some error still ;-(
As before any help much appreciated!

In Rust, is it possible to return a static function from a function?

Suppose I have the following type in Rust:
type UnOp = fn(u64) -> u64;
That type allows me to create different unary operations:
const add1 : UnOp = |x| x + 1;
const mul2 : UnOp = |x| x * 2;
Now, suppose that I needed add2, add3, add4 (...), for different numbers, in different places of my code. Writing all definitions would be cumbersome, so, instead, I write a generic adder function:
fn adder(add : u64) -> UnOp {
|x| x + add
}
This would allow me to write add(2), add(3), etc., for any number:
// Prints 2 + 40
println!("result is: {}", adder(2)(40))
The problem is: adder is actually not valid Rust code, since |x| ... is a closure, not a static function. In order for adder to work as I want, I need to modify UnOp to be a closure instead:
type UnOp = Box<dyn Fn(u64) -> u64>;
fn adder(add : u64) -> UnOp {
Box::new(move |x| x + add)
}
The problem is: what if I know every usage of adder(N) is applied to a static value?
In that case, creating dynamic closures would be wasteful, computation-wise. Not only that, Box<dyn ...> greatly complicates the code, and may even need lifetime annotations. My question is:
Is it possible to create adder, without modifying the original definition of UnOp? That is, letting UnOp be a static function, NOT a closure?
Logically, there is no reason it shouldn't be possible, as long as the arguments of adder are static, Rust should be able to just expand it at compile time, to generate each particular instance.
Edit: additional details
A great solution, proposed by #Netwave's answer, is to use Generic consts, which solves this problem for the specific example I gave. Sadly, it doesn't work in case UnOp is polymorphic, or if the constant argument is itself a function:
type UnOp<A> = fn(A) -> A;
pub fn adder<const ADD: u64>() -> UnOp<u64> {
|x| ADD + x
}
pub fn apply<A, const op : UnOp<A>, const x : A>() -> A {
return op(x);
}
This raises 2 errors:
- the type of const parameters must not depend on other generic parameters
- using function pointers as const generic parameters is forbidden
You can do it using const Generics:
type UnOp = fn(u64) -> u64;
const fn adder<const ADD: u64>(x: u64) -> u64 {
ADD + x
}
fn main() {
let add_1: UnOp = adder::<1>;
println!("{}", add_1(1));
}
Playground
Is it possible to create adder, without modifying the original definition of UnOp? That is, letting UnOp be a static function, NOT a closure?
Since you don't explain why I will ignore this requirement. As I think you limit you option for nothing.
You could prefer a clever use of generic and trait:
trait UnOp {
fn call(&self, _: u64) -> u64;
}
impl<F> UnOp for F
where
F: Fn(u64) -> u64,
{
fn call(&self, x: u64) -> u64 {
self(x)
}
}
fn adder(add: u64) -> impl UnOp {
move |x| x + add
}

What is going on with `unconstrained generic constants` in Rust?

I was experimenting with const generics when this strange error came out: error: unconstrained generic constant. What does it mean?
Maybe I should describe what was I tried to do before actual code - I wanted to treat types as numbers, using Lisp-like Cons and Nil.
Here's an example:
use core::marker::PhantomData;
struct Nil;
struct Cons <N> (PhantomData <N>);
So '1' is Cons <Nil>, '2' - Cons <Cons <Nil>>, etc.
Then I tried to implement extracting normal number from this.
trait Len {
const N: usize;
}
impl <N: Len> Len for Cons <N> {
const N: usize = 1 + N::N;
}
impl Len for Nil {
const N: usize = 0;
}
And it works.
Then I started doing actual job: my true task was not to just experiment with generic types, but to implement mathematical vecs, just like(maybe you know) in shaders.
So I tried to implement such powerful constructor:
vec3 i = vec3(1.0, 1.0, 1);
vec4 v = vec4(i);
I have decided to treat any value as 'Piece' and then just compound pieces together.
trait Piece <T> {
type Size: Len;
fn construct(self) -> [T; Self::Size::N];
}
No problems so far. Next step is to define few auxiliary traits(since rust does not yet support negative bounds):
pub auto trait NotTuple {}
impl <T> !NotTuple for (T,) {}
pub auto trait NotList {}
impl <T, const N: usize> !NotList for [T; N] {}
I am using nightly rust, so few #![feature]-s is not a problem.
Then, we can use it:
type One = Cons <Nil>;
impl <T: Copy + From <U>, U: Copy + NotTuple + NotList> Piece <T> for U {
type Size = One;
fn construct(self) -> [T; Self::Size::N] {
[T::from(self)]
}
}
This one constructs piece from an argument.
Everything is still good.
impl <T: Copy, U: Piece <T>> Piece <T> for (U,) {
type Size = U::Size;
fn construct(self) -> [T; Self::Size::N] {
self.0.construct()
}
}
And this is where problem occurs. Compiler says that Self::Size::N is an unconstrained generic constant, and tries to help with this: try adding a 'where' bound using this expression: 'where [(); Self::Size::N]:', but this is just useless.
Can anyone explain me what is going on and how to fix this issue?

Operator overloading involving complex and float values

Update: This bug has been fixed by https://github.com/rust-lang/rust/pull/23673 . The code below now works.
In math and numerical programming, it is expected that complex numbers interoperate seamlessly with real (floating point) values. Is it possible in Rust to define a struct Complex<T: Float> that allows symmetric math operations involving values of type T?
For example, one can define the operator * for inputs (Complex<T>, Complex<T>) and (Complex<T>, T) as follows:
use std::ops::Mul;
use std::num::Float;
#[derive(Copy, Debug)]
pub struct Complex<T: Float> {
pub re: T, pub im: T
}
impl<T: Float> Complex<T> {
pub fn new(re: T, im: T) -> Complex<T> {
Complex { re: re, im: im }
}
}
impl<T: Float> Mul<Complex<T>> for Complex<T> {
type Output = Complex<T>;
fn mul(self, other: Complex<T>) -> Complex<T> {
Complex::new(self.re * other.re - self.im * other.im,
self.re * other.im + self.im * other.re)
}
}
impl<T: Float> Mul<T> for Complex<T> {
type Output = Complex<T>;
fn mul(self, other: T) -> Complex<T> {
Complex::new(self.re * other, self.im * other)
}
}
Is it possible to overload * to also work on the inputs (T, Complex<T>)? For example, the following doesn't work:
impl Mul<Complex<f64>> for f64 {
type Output = Complex<f64>;
fn mul(self, other: Complex<f64>) -> Complex<f64> {
Complex::new(self * other.re, self * other.im)
}
}
fn main() {
let x = Complex::new(1.0, 1.0);
let y = x*x;
let z = x*4.0;
let w = 4.0*x;
}
I get the error message:
error: mismatched types:
expected `_`,
found `Complex<_>`
(expected floating-point variable,
found struct `Complex`) [E0308]
src/main.rs:61 let w = 4.0*x;
^
In Scala, one might work around this problem with an implicit conversion from T to Complex<T>. Are there similar tricks in Rust? Is there a better way to define an efficient, generalized * operation? Thanks.
This should be allowed, but there's an outstanding issue that prevents built-in types (u8, f32, etc) from being used on the left-hand side of the operation when a custom implementation is in play.
The suggested workaround for now is to put the custom type on the left-hand side and the built-in type on the right.

trait constraint on specific function rather than whole implementation

I'm trying to implement a generic struct that can take any type parameter.
struct Position<T>{
x: T,
y: T,
}
impl<T:Num> Position<T>{
fn add(&self, other: &Position<T>) -> Box<Position<T>>{
box Position{x:self.x + other.x, y:self.y + other.y}
}
fn display(&self) -> String{
"WELCOME ".to_string()
}
}
now I can define
let original_position = Position::<int>{x: 2, y:23};
let another_postion = original_position.add(&original_position);
let welcome = original_postion.display();
without any error
similarly, i can do the following without any error.
let string_position = Position::<String>{x: "x_pos".to_string(), y: "y_pos".to_string()};
now due to the Num trait constraint i cannot call the following (which is obvious ).
string_position.add(&original_position);
but,my problem is that now i cannot call the following because of the same Num trait constraint
string_position.display()
the above function has noting to do with Num type, it simply returns the string "WELCOME"
how do i need to rewrite the implemetation so that add method can be called only by Position<Num> and display can be called by any other generic implementation.
You should create separate implementations, one with the bound and the other without, like this:
impl<T:Num> Position<T>{
fn add(&self, other: &Position<T>) -> Box<Position<T>>{
box Position{x:self.x + other.x, y:self.y + other.y}
}
}
impl<T> Position<T>{
fn display(&self) -> String{
"WELCOME ".to_string()
}
}
You can see that it works here.

Resources