E4053

E4053#

无效的 "self" 类型:必须是类型构造器。

当你试图为一个不是类型构造器的类型定义方法或实现 trait 时,会出现这个错误。

属于类型构造器的类型:

  • 元组:(Int, Bool)

  • enums, structs, traits, new types (type), and error types (type!).

不属于类型构造器的类型:

  • 函数类型:(Int) -> Bool

  • 类型参数:如 fn f[T](x : T) -> T 中的 T

错误示例#

  • 为非类型构造器的类型定义方法。

    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)
    }
    
  • 为非类型构造器的类型实现方法。

    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
    }
    

建议#

当你希望为一个非类型构造器的类型定义方法时,可以使用新类型将其包装起来。

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
}

但这样一来,每次调用方法时你都需要用 Wrap 来包装该值。

如果你需要为类型参数实现特征(trait),也可以考虑使用特征(trait)的默认实现。

impl A with f(self : Self) -> Int {
  ignore(self)
  0
}

如果你希望只为满足特定约束的类型提供实现,可以将这些约束添加到特征(trait)的定义中。

trait A: Default {
  f(Self) -> Int
}

impl A with f(self : Self) -> Int {
  ignore(self)
  0
}