E4053#
Invalid type for “self”: must be a type constructor.
This error happens when you want to define a method for implement a trait for a type that is not a type constructor.
Types that are type constructors:
Tuple:
(Int, Bool)
enum
s,struct
s,trait
s, new types (type
), and error types (type!
).
Types that are not type constructors:
Function:
(Int) -> Bool
Type parameter:
T
infn f[T](x : T) -> T
错误示例#
Defining a method for a type that is not type constructor.
fn f[T](self : T) -> Int { // Error: Invalid type for "self": must be a type constructor. ignore(self) 0 } fn g(self : (Int) -> Unit) -> Unit { // Error: Invalid type for "self": must be a type constructor. self(0) }
Implementing a method for a type that is not a type constructor.
pub trait A { f(Self) -> Int } // Without constraints impl[X] A for X with f(self : X) -> Int { // Error: Invalid type for "self": must be a type constructor. ignore(self) 0 } // With constraints impl[X: Default] A for X with f(self : X) -> Int { // Error: Invalid type for "self": must be a type constructor. ignore(self) 0 }
建议#
When you want to define a method for a type that is not a type constructor, you may use new type to wrap the type.
pub(all) type Wrap[T] T
fn f[T](self : Wrap[T]) -> Int {
ignore(self)
0
}
fn g(self : Wrap[(Int) -> Unit]) -> Unit {
(self._)(0)
}
impl[X] A for Wrap[X] with f(self : Wrap[X]) -> Int {
ignore(self)
0
}
However, this means you may have to wrap the value with Wrap
every time you
want to call the method.
If you find yourself implementing a trait for a type parameter, you may also want to consider using default implementation for the trait.
impl A with f(self : Self) -> Int {
ignore(self)
0
}
If you want to provide the implementation for types with specific constraints, you can add these constraints to the trait definition.
trait A: Default {
f(Self) -> Int
}
impl A with f(self : Self) -> Int {
ignore(self)
0
}