Skip to content

Invalid error message about lifetimes when pattern matching with constants #18352

Closed
@netvl

Description

@netvl

On the latest nightly (previously it worked fine) Rust fails to compile this code:

pub struct Namespace(pub HashMap<Option<String>, String>);

impl Namespace {
...
    pub fn is_essentially_empty(&self) -> bool {
        let Namespace(ref hm) = *self;
        for (k, v) in hm.iter() {
            match (k.as_ref().map(|k| k.as_slice()), v.as_slice()) {
                (None, NS_EMPTY_URI) |
                (Some(NS_XMLNS_PREFIX), NS_XMLNS_URI) |
                (Some(NS_XML_PREFIX), NS_XML_URI) => {},
                _ => return false
            }
        }
        true
    }
...
}

It emits this error message:

   Compiling rust-xml v0.1.0 (file:///home/dpx-infinity/dev/lang/rust/projects/rust-xml)
src/namespace.rs:41:23: 41:29 error: cannot infer an appropriate lifetime for pattern due to conflicting requirements
src/namespace.rs:41         let Namespace(ref hm) = *self;
                                          ^~~~~~
src/namespace.rs:43:54: 43:55 note: first, the lifetime cannot outlive the expression at 43:53...
src/namespace.rs:43             match (k.as_ref().map(|k| k.as_slice()), v.as_slice()) {
                                                                         ^
src/namespace.rs:43:54: 43:55 note: ...so that pointer is not dereferenced outside its lifetime
src/namespace.rs:43             match (k.as_ref().map(|k| k.as_slice()), v.as_slice()) {
                                                                         ^
src/namespace.rs:42:23: 42:25 note: but, the lifetime must be valid for the expression at 42:22...
src/namespace.rs:42         for (k, v) in hm.iter() {
                                          ^~
src/namespace.rs:42:23: 42:25 note: ...so that pointer is not dereferenced outside its lifetime
src/namespace.rs:42         for (k, v) in hm.iter() {
                                          ^~

I managed to strip it down to this example:

const X: &'static str = "12345";

pub fn test(s: String) -> bool {
    match s.as_slice() {
        X => true,
        _ => false
    }
}

It fails to compile with this error:

/tmp/rs/lifetimes/src/lib.rs:18:11: 18:12 error: `s` does not live long enough
/tmp/rs/lifetimes/src/lib.rs:18     match s.as_slice() {
                                          ^
note: reference must be valid for the static lifetime...
/tmp/rs/lifetimes/src/lib.rs:17:32: 22:2 note: ...but borrowed value is only valid for the block at 17:31
/tmp/rs/lifetimes/src/lib.rs:17 pub fn test(s: String) -> bool {
/tmp/rs/lifetimes/src/lib.rs:18     match s.as_slice() {
/tmp/rs/lifetimes/src/lib.rs:19         X => true,
/tmp/rs/lifetimes/src/lib.rs:20         _ => false
/tmp/rs/lifetimes/src/lib.rs:21     }
/tmp/rs/lifetimes/src/lib.rs:22 }

If X => is replaced with "12345" =>, then it compiles fine, so the error seems to be related to matching on consts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions