Helin Wang
Helin Wang

Reputation: 4202

Syntax meaning for `impl<'a> Config<'a> {`

For the following code:

struct Config<'a> {
    query: &'a str,
    filename: &'a str,
    case_sensitive: bool,
}

impl<'a> Config<'a> {
    pub fn new(args: &'a [String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = &args[1];
        let filename = &args[2];

        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

        Ok(Config {
            query,
            filename,
            case_sensitive,
        })
    }
}

Why impl<'a> Config<'a> { is required, rather than impl Config<'a> {?

What is the syntactic meaning of the first and second 'a? I know 'a is a lifetime annotation, but don't know why it's placed after both impl and Config. What does the first 'a do and what does the second 'a do?

Upvotes: 0

Views: 814

Answers (2)

Peter Hall
Peter Hall

Reputation: 58815

The first <'a> declares a context which introduces variables which are universally quantified. In other words, impl<'a> ... means "implement for any possible lifetime 'a ... ".

Once the variables are introduced, the second 'a is the application of the variable to a type.

You can read the syntax impl<'a> Config<'a> as: "for any possible lifetime 'a these methods are defined for Config<'a>".

In a more complex situation the context is where you can place constraints on the parameters. For lifetimes this is always an "outlives" relationship, for example <'a, 'b: 'a> ("for all lifetimes 'a and 'b where 'b outlives 'a"). For types, this could include both trait or lifetime bounds, e.g. <'a, T: + Debug + 'a> ("for all lifetimes, 'a and all types T, where T implements Debug and does not outlive 'a").

Upvotes: 3

E_net4
E_net4

Reputation: 30042

All generic lifetimes and types need to be declared somewhere.

Try to compile your code to use impl Config<'a> and you'll get this error message:

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:9:13
  |
9 | impl Config<'a> {
  |             ^^ undeclared lifetime

Like type parameters, generic lifetime parameters such as the 'a in Config<'a> need to be declared on every function, type definition or trait implementation that they are used. They do not even have to have exactly the same name as how the parameter was declared originally:

impl<'c> Config<'c> {
    ... // use 'c instead of 'a
}

See also:

Upvotes: 3

Related Questions