 
       let selfSym: Symbol? = node.innerScope?.symbols["self"]?[0]
       if node.kind == .constructor {
-        guard selfSym != nil
-          else { fatalError("no symbol for 'self' in constructor scope") }
+        assert(selfSym != nil, "missing symbol for 'self' in constructor")
         locals.top![selfSym!] = builder.buildAlloc(type: fnTy.codomain, id: 0)
+      } else if node.symbol!.isMethod {
+        assert(selfSym != nil, "missing symbol for 'self' in method")
+        locals.top![selfSym!] = AIRParameter(
+          type: builder.unit.getType(of: selfSym!.type!),
+          id: builder.currentBlock!.nextRegisterID())
       }
 
       // Create the function parameters.

  public func visit(_ node: FunDecl) throws {
    // Get the type of the declared function.
    var fnTy = builder.unit.getFunctionType(of: node.type! as! FunctionType)
    if !node.captures.isEmpty {
      // If the function captures symbols, we need to emit a context-free version of the it, which
      // gets the captured values as parameters. This boils down to extending the domain.
      assert(node.captures.duplicates(groupedBy: { $0.name }).isEmpty)
      let additional = node.captures
        .sorted(by: { a, b in a.name < b.name })
        .map({ builder.unit.getType(of: $0.type!) })
      fnTy = builder.unit.getFunctionType(from: additional + fnTy.domain, to: fnTy.codomain)
    }


      // Restore the insertion point.
      builder.currentBlock = previousBlock
      locals.pop()
    }

    // NOTE: Generic functions are represented unspecialized in AIR, so that borrow checking can be
