Skip to content

lifetime variables in type bounds not properly enforced #12857

Closed
@dwrensha

Description

@dwrensha

Please see the MessageReader::get_root function below and the call to it in main(). It seems that 'a is not properly constrained.

This is related to #5121 and #12807.

// lifetimes.rs


// Like a slice.
pub struct StructReader<'a> {
    buf : *u8,
    len : uint,
    marker : std::kinds::marker::ContravariantLifetime<'a>,
}

// Something that can be constructed from a StructReader<'a>,
// and will have the same lifetime 'a.
pub trait FromStructReader<'a> {
    fn new(struct_reader : StructReader<'a>) -> Self;
}

pub struct MessageReader {
    buf : ~[u8],
}

impl MessageReader {

    // borrow `self` with lifetime `'a`, and construct a `T` that lives no longer than `'a`.
    pub fn get_root<'a, T : FromStructReader<'a>>(&'a self) -> T {
        FromStructReader::<'a>::new(
            StructReader {buf : self.buf.as_ptr(),
                          len : self.buf.len(),
                          marker : std::kinds::marker::ContravariantLifetime::<'a>,
            })
    }
}

pub struct FooReader<'a> {
    reader : StructReader<'a>
}

impl <'a> FromStructReader<'a> for FooReader<'a> {
    fn new(struct_reader : StructReader<'a>) -> FooReader<'a> {
        FooReader { reader : struct_reader}
    }
}

impl <'a> FooReader<'a> {
    pub fn get(&self, idx : uint) -> u8 {
        assert!(idx < self.reader.len);
        unsafe {
            *self.reader.buf.offset(idx as int)
        }
    }

}

pub fn main () {
    let bar = {
        let message = MessageReader {buf : ~[1,2,3,4,5]};
        let foo : FooReader = message.get_root();
        foo
    }; // this shouldn't typecheck, because `foo` cannot outlive `message`

    let _x : ~[u8] = ~[9,9,9,9,9,9,9,9,9,9,9,9];

    println!("bar.get(0) = {}", bar.get(0));
}

I expect this program not to typecheck, because it allows a FooReader to live longer than the StructReader it was constructed from.

However, we get:

$ rustc lifetimes.rs 
$ ./lifetimes 
bar.get(0) = 9

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions