Discussing with @paulrberg and @leo on this twitter thread:
Currently, declaration of variables of certain types is rather verbose, especially when it comes to complex types that typically need a constructor (i.e. you have the type there already).
Examples:
contract MyContract {}
function foo() {
// constructor already tells us the type of the contract
MyContract _contract = new MyContract();
}
contract HasStruct {
// again, we already know B is type MyStruct storage
MyStruct B = MyStruct({
bar: "baz"
});
}
I’d like to suggest a better alternative would be type inference for certain types, namely Contracts and Structs declared in contract storage. The compiler should be able to infer the type of the Contract or Struct from the constructor (or struct constructor).
This only would make sense in any situation where a variable is declared at the same time as being initialised.
Examples:
function proposedFoo() {
// _contract is inferred to be of type MyContract
_contract = new MyContract();
}
contract ProposedHasStruct {
// B is inferred to be of type MyStruct storage
B = MyStruct({bar: "baz"});
}
contract ProposedContract {
// inferred type MyContract (storage)
_contract = new MyContract();
}
The above examples reduce verbosity. Although it might seem trivial in a small example like above, extra verbosity is a pain especially in larger codebases and when refactoring. Problem gets worse when tests are also written in solidity so this would be a nice win for developer experience.
Some examples that would NOT work:
- Structs declared inside function scopes - memory or storage must be explicitly defined so we definitely still need the type.
- Variables declared but then later initialised
Leo raises a good point that contract inheritance introduces ambiguity into the contract type. My suggestion would therefore be to default to the type of the constructor, then allow for explicit type declarations for parent classes:
contract MyChildContract is MyContract {}
function inferred() {
// infer child as type MyChildContract in memory
child = new MyChildContract();
}
function explicit() {
// allow declaring of parent classes as an override
MyContract child = new MyChildContract();
}
function prohibited() {
// not allowed - must wrap the address in this scenario
UnknownContract child = new MyChildContract();
}
Would welcome thoughts, comments criticisms