Reputation: 1516
I'm struggling with this error rustc
gives me:
error: method `create_shader_explicit` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime
My trait declaration is pretty much this:
pub trait GraphicsContext<R: Resources> {
/// Creates a shader object
fn create_shader<'a>(&'a self, shader::Stage, source: &str) ->
Result<handle::Shader<R>, shader::CreateError>;
}
Here's my implementation,
pub struct OpenGLResources<'a> {
phantom: PhantomData<&'a u32>
}
impl<'a> Resources for OpenGLResources<'a> {
type Shader = Shader<'a>;
}
impl<'z> GraphicsContext<OpenGLResources<'z>> for OpenGLGraphicsContext {
/// Creates a shader object
fn create_shader<'a>(&'a self, stage: shader::Stage, source: &str) ->
Result<handle::Shader<OpenGLResources>, shader::CreateError> {
let shader = Shader::new(self, stage);
try!(shader.compile_from_source(source));
Ok(shader)
}
}
In other questions on StackOverflow, they are missing things like <'a>
between create_shader
and ()
, however when I compare the fn definitions in mine they look identical.
EDIT:
Changing the definition inside impl
to the following fixes that issue
fn create_shader<'a>(&'a self, stage: shader::Stage, source: &str) ->
Result<handle::Shader<OpenGLResources**<'z>**>, shader::CreateError>
But then the issue is that 'a
and 'z
need to be the same lifetime. If I change it to this:
fn create_shader(**&'z** self, stage: shader::Stage, source: &str) ->
Result<handle::Shader<OpenGLResources<'z>>, shader::CreateError>
The impl
block works, but then I need a way of specifying the 'z
lifetime in the trait definition. I tried the following:
pub trait<'z> GraphicsContext<R: Resources<'z>>
But it didn't work.
Upvotes: 1
Views: 155
Reputation: 1516
Thanks the hints of @Chris Morgan I managed to implement this functionality and its now working fine.
If we start with the base trait with the 'a
lifetime included:
trait Resources<'a> {
type Shader: Shader;
type ShaderProgram: ShaderProgram;
}
Then implement it for OpenGL. (note the PhantomData
struct)
struct OpenGLResources<'a> {
phantom: PhantomData<&'a u32> // 'a is the lifetime of the context reference
}
impl<'a> ResourcesTrait<'a> for Resources<'a> {
type Shader = Shader<'a>;
type ShaderProgram = ShaderProgram<'a>;
type CommandBuffer = CommandBuffer;
type CommandBufferBuilder = CommandBufferBuilder;
}
Its a bit verbose, but the GraphicsContext
trait works fine too now. The 'a
lifetime goes in the type parameters part.
trait GraphicsContext<'a, R: Resources<'a>> {
fn create_shader(&'a self, ty: Type, source: &str) -> Result<R::Shader, ShaderCreationError>
}
Finally this is the required code in the graphics context implementation.
It is extremely verbose with the 'a
lifetimes sprinkled everywhere but at least it works!
impl<'a> GraphicsContext<'a, Resources<'a>> for OpenGLGraphicsContext
Upvotes: 0
Reputation: 90882
When comparing things like this, you need to remember to expand all the generics so that you can actually compare it all. In this case, you haven’t expanded R
. If you do, the answer becomes obvious: R
is OpenGLResources<'z>
, linking the OpenGLResources
to the impl
block, whereas your method definition has elided the lifetime on OpenGLResources
, causing it to be inferred as self
’s lifetime, which is 'a
.
Upvotes: 1