Citing the Language Guide - Properties - Lazy Stored Properties [emphasis mine]:
A lazy stored property is a property whose initial value is not
calculated until the first time it is used.
I.e., the value is mutated upon first usage. Since foo has been blueprinted in the Foo protocol as get, implicitly nonmutating get, the value type Bar does not fulfil this promise with its lazy property foo, a property with a mutating getter.
Changing Bar to a reference type will allow it to fulfil the Foo blueprint (as mutating a property of a reference type doesn't mutate the type instance itself):
protocol Foo {
var foo: String { get }
}
class Bar: Foo {
lazy var foo: String = "Hello World"
}
Alternative, specify in the blueprint of the foo property of Foo that it has a mutating getter.
protocol Foo {
var foo: String { mutating get }
}
struct Bar: Foo {
lazy var foo: String = "Hello World"
}
See the following Q&A for some additional details of the mutating/nonmutating specifiers for getters and setters: