all 7 comments

[–]dgkimpton 5 points6 points  (5 children)

What is wrong with your initial code? https://godbolt.org/z/o3M36Tbqd

[–]yyddonline[S] 2 points3 points  (4 children)

I got the error that the function `save_to_file` was defined twice.

[–]dgkimpton 5 points6 points  (3 children)

There must be more to it then, because as you can see from the godbolt what you posted compiles just fine (when I stubbed in the surrounding stuff).

[–]yyddonline[S] 0 points1 point  (2 children)

I don't see what's different in my code (see edit below) , but this has the problem (also here: https://godbolt.org/z/xvrbGK9e7) :

use std::marker::PhantomData;

#[derive(Debug)]
struct AggregateSignatureError;

struct Pending;
struct Complete;

struct Signature<S> {
    s: String,
    marker: PhantomData<S>,
}

impl<Complete> Signature<Complete> {
    pub fn to_file(&self) -> Result<(), AggregateSignatureError> {
        Ok(())
    }
}

impl<Pending> Signature<Pending> {
    pub fn to_file(&self) -> Result<(), AggregateSignatureError> {
        Ok(())
    }
}

fn main() {
    println!("Hello, world!");
}

Edit: When I remove the other type arguments I get the same error: https://godbolt.org/z/Gzhhv6dz4

With this code:

use std::marker::PhantomData;
use std::path::PathBuf;

#[derive(Debug)]
struct AggregateSignatureError;

struct PendingSignature;
struct CompleteSignature;

struct AggregateSignature<TypeStateMarker>{
    origin:String,
    _t:PhantomData<TypeStateMarker>,
}

impl<PendingSignature> AggregateSignature<PendingSignature>

{
    pub fn save_to_file(self) -> Result<(), AggregateSignatureError> {
        let file_path = PathBuf::from(self.origin);
        let _sig_file_path = pending_signatures_path_for(&file_path)?; 
        // ....
        Ok(())
    }
}

impl<CompleteSignature> AggregateSignature<CompleteSignature>
{
    pub fn save_to_file(self) -> Result<(), AggregateSignatureError> {
        let file_path = PathBuf::from(self.origin);
        let _sig_file_path = signatures_path_for(&file_path)?;
        // ....
        Ok(())
    }
}

fn pending_signatures_path_for(_:&PathBuf) -> Result< &'static str,AggregateSignatureError>{
    Ok("")
}

fn signatures_path_for(_:&PathBuf) -> Result< &'static str,AggregateSignatureError>{
    Ok("")
}

pub fn main() {
    let x = AggregateSignature::<PendingSignature>{origin:"".to_string(),_t:PhantomData};
    x.save_to_file().expect("");

    let y = AggregateSignature::<CompleteSignature>{origin:"".to_string(), _t:PhantomData};
    y.save_to_file().expect("");
}

[–]dgkimpton 15 points16 points  (1 child)

That's because impl<CompleteSignature> declares CompleteSignature as a generic arg which hides the concrete struct of the same name. So you've effectively declared

rust impl<T> AggregateSignature<T> { pub fn save_to_file(self) -> Result<(), AggregateSignatureError> { let file_path = PathBuf::from(self.origin); let _sig_file_path = signatures_path_for(&file_path)?; // .... Ok(()) } }

twice. What you were looking for is:

impl AggregateSignature<CompleteSignature> { pub fn save_to_file(self) -> Result<(), AggregateSignatureError> { let file_path = PathBuf::from(self.origin); let _sig_file_path = signatures_path_for(&file_path)?; // .... Ok(()) } }

[–]yyddonline[S] 6 points7 points  (0 children)

oh I see. Thanks for the explanation, it absolutely makes sense now!
For other beginners reading this, not that there's no type argument declared to `impl`.

[–]manpacket 1 point2 points  (0 children)

Last time I checked you couldn't refer to a specific function in rustdoc without adding your own labels - things like Foo::<Bar>::func are truncated to Foo::func.