code: func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
  	//
  	// loop:                                   (target of continue)
  	//      ko = <-x                           (key, ok)
  	//      ok = extract ko #1
  	//      if ok goto body else done
  	// body:
  	//      k = extract ko #0
  	//      ...
  	//      goto loop
  	// done:                                   (target of break)
  
  	loop = fn.newBasicBlock("rangechan.loop")
  	emitJump(fn, loop)
  	fn.currentBlock = loop
  	recv := &UnOp{
  		Op:      token.ARROW,
  		X:       x,
  		CommaOk: true,
  	}
  	recv.setPos(pos)
  	recv.setType(types.NewTuple(
  		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
  		varOk,
  	))
  	ko := fn.emit(recv)
  	body := fn.newBasicBlock("rangechan.body")
  	done = fn.newBasicBlock("rangechan.done")
  	emitIf(fn, emitExtract(fn, ko, 1), body, done)
  	fn.currentBlock = body
  	if tk != nil {
  		k = emitExtract(fn, ko, 0)
  	}
  	return
  }
docs: // rangeChan emits to fn the header for a loop that receives from
  // channel x until it fails.
  // tk is the channel's element type, or nil if the k result is
  // not wanted
  // pos is the position of the '=' or ':=' token.
  //