简体   繁体   中英

cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements

I am getting this error - "cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements". However, I've tried to enforce start_duty requirements explicitly.

error.rs:45:1: 55:2 note: consider using an explicit lifetime parameter as shown: fn start_duty<'dutylife>(duty: &'dutylife Duty) -> &'dutylife Job<'dutylife>
error.rs:45 fn start_duty<'dutylife> (duty: &'dutylife Duty) -> &'dutylife Job {
error.rs:46 
error.rs:47     let j : Job = Job {
error.rs:48         duty: duty,
error.rs:49         output: "".to_string(),
error.rs:50         success: JobNotDone
            ...
error.rs:48:15: 48:19 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
error.rs:48         duty: duty,
                          ^~~~
error: aborting due to previous error

A somewhat expurgated version of my code inducing the error. Conceptually, what I am trying to do is generate a new Job referencing a Duty. Jobs can only exist for the lifetime of the Duty; when the Duty goes away, the Job should as well.

enum Source {
    Nothing,                        // Nothing
    Git(String, String),            // reponame, refname
    Hg(String, String),             // reponame, csid
    Url(String)                     // curl down what's here
}

enum JobResult {
    JobNotDone,
    JobSuccess,
    JobFailure,
    JobError
}

/*
Jobs

Jobs are always attached to the Duty that spawned them; there can be
no Job without the duty. So we take a lifetime param of the duty reference
*/
struct Job<'r> {
    duty:  &'r Duty,            // pointer back to
    output: String,             // no output = ""
    success: JobResult
}

enum Action {
    BashScript(String)
}

struct Duty {
    name: String,
    source: Source,
    action: Action,
    comment: Option<String>
}

struct Agent<'r> {
    hostname : String,
    uid : u64,
    job : Option<Job<'r>>,                  // mutable, agents
}

// returns new Job, but with duty referenced.
fn start_duty<'dutylife> (duty: &'dutylife Duty) -> &'dutylife Job {

    let j : Job = Job {
        duty: duty,
        output: "".to_string(),
        success: JobNotDone

    };

    return &j;
}


fn main () {
}

This function signature promises to return a reference to a Job.

fn start_duty<'dutylife> (duty: &'dutylife Duty) -> &'dutylife Job

What you probably wanted to do was returning a Job that contains a reference to a Duty :

fn start_duty<'dutylife> (duty: &'dutylife Duty) -> Job<'dutylife> {

    Job {
        duty: duty,
        output: "".to_string(),
        success: JobNotDone
    }

}

There was also another error, the code was trying to return a reference to the Job created in this function. I fixed that as well and the code now compiles. Let me know if this was what you were trying to do.

Edit: to respond to the "Jobs can only exist for the lifetime of the Duty; when the Duty goes away, the Job should as well." part.

This cannot be done in the way you've tried because the Job object will cease to exist when the function ends, and any references to it would become invalid.

The simplest way would be to let a Duty own the Job (s) working on it (by giving it a Option<Job> or Option<Vec<Job>> field). This is a single owner approach. Multiple owners are significantly more complex and would involve reference counted pointers, or raw pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM