Вполне себе для этого PhantomData и предназначен. Это один из основных кейсов использования, когда нужно “подвязать” “болтающийся” тайп-параметр или лайфтайм-параметр.
Но, я бы это дело не подвязывал на структуру. Пусть структура будет просто:
struct ZeroOrOne<P> {
p: P
}
А P: Parser<'a> баунд уже декларируйте в impl'ах, а не на самой struct.
Выражаясь более прямолинейно: bound behaviour, not data.
Если Вы делаете баунды на самой структуре, то их тогда приходится тянуть во всеimpl'ы для этой структуры, что нехило так бьёт по чистоте кода. Здесь об этом можно тоже почитать.