Skip to content

NLL breaks functions with intermingled lifetimes in return type when returned value is a (non-borrowed) associated type #49354

Closed
@daboross

Description

@daboross

Code which returns this kind of complicated expression involving two different lifetimes compiles under normal compilation conditions, but fails with #![feature(nll)].

Minified example (courtesy of @matthewjasper).

#![feature(nll)]
trait Visitor<'de> {
    type Value;
}

impl<'a, 'de: 'a> Visitor<'de> for &'a () {
    type Value = ();
}

//error: free region `'a` does not outlive free region `'de`
fn visit_seq<'de: 'a, 'a>() -> <&'a () as Visitor<'de>>::Value {}
//                                                             ^^

fn main() {}

working playground: https://play.rust-lang.org/?gist=5f08095fda551daa89fadf0b8566989e&version=nightly
broken playground: https://play.rust-lang.org/?gist=a5d0d7619f610d94fe316c80b0f1dfbb&version=nightly

Original post / serde_derive generated code example

The source code is anything like the following:

#![feature(nll)]
extern crate sede;
#[macro_use]
extern crate serde_derive;

#[derive(Deserialize)]
struct X<'a> {
    #[serde(borrow)]
    field: &'a [u8]
}

Pared down generated code:

#![feature(nll)]
extern crate serde;
pub struct X<'a> {
    pub field: &'a [u8],
}
impl<'de: 'a, 'a> serde::Deserialize<'de> for X<'a> {
    fn deserialize<__D>(__deserializer: __D) -> serde::export::Result<Self, __D::Error>
    where
        __D: serde::Deserializer<'de>,
    {
        struct __Visitor<'de: 'a, 'a> {
            marker: serde::export::PhantomData<X<'a>>,
            lifetime: serde::export::PhantomData<&'de ()>,
        }
        impl<'de: 'a, 'a> serde::de::Visitor<'de> for __Visitor<'de, 'a> {
            type Value = X<'a>;
            fn expecting(
                &self,
                formatter: &mut serde::export::Formatter,
            ) -> serde::export::fmt::Result {
                serde::export::Formatter::write_str(formatter, "struct X")
            }
            #[inline]
            fn visit_seq<__A>(
                self,
                mut __seq: __A,
            ) -> serde::export::Result<Self::Value, __A::Error>
            where
                __A: serde::de::SeqAccess<'de>,
            {
                let __field0 = match serde::de::SeqAccess::next_element::<&'a [u8]>(&mut __seq)? {
                    Some(__value) => __value,
                    None => {
                        return Err(serde::de::Error::invalid_length(
                            0usize,
                            &"tuple of 1 elements",
                        ));
                    }
                };
                Ok(X { field: __field0 })
            }
        }
        unimplemented!()
    }
}
fn main() {}

This code compiles without NLL enabled, but with NLL, fails with:

error: free region `'a` does not outlive free region `'de`
  --> src/main.rs:31:21
   |
31 |                 let __field0 = match serde::de::SeqAccess::next_element::<&'a [u8]>(&mut __seq)? {
   |                     ^^^^^^^^

Playground working: https://play.rust-lang.org/?gist=cb213e15287e06e85fb7a55412967b23&version=nightly

Playground failing: https://play.rust-lang.org/?gist=c4745b7f9e40f16bd7fe62f27d9c534b&version=nightly

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)NLL-completeWorking towards the "valid code works" goal

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions