Skip to content

io.ReaderWriter cannot be casted to io.Writer #26298

@Te4nick

Description

@Te4nick

Describe the bug

The net.TcpConn implements io.ReaderWriter, as of https://github.com/vlang/v/blob/master/vlib/io/readerwriter.v#L6 the io.ReaderWriter contain io.Writer so it inherits all methods.
(I need both io.Reader and io.Writer capabilities in full code)
If I try to pass field of type io.ReaderWriter to field of type io.Writer I get an error:

D:\Programming\V\rpcrud [main +2 ~2 -0 !]> ../v/v run .\examples\interfaces.v
examples/interfaces.v:34:7: error: cannot implement interface `io.Writer` with a different interface `io.ReaderWriter`
   32 |             writers: [
   33 |                 InterceptorWriter{ interceptors: s.interceptors },
   34 |                 s.stream
      |                   ~~~~~~
   35 |             ]
   36 |         }
D:\Programming\V\rpcrud [main +2 ~2 -0 !]> ../v/v --version
V 0.5.0 e3616f2

Reproduction Steps

v code:

module main

import io
import net

@[heap]
pub struct Server {
pub mut:
	stream       io.ReaderWriter
	interceptors []Interceptor
}

pub fn (s &Server) writer() &ResponseWriter {
	return &ResponseWriter{
		server: s
		writer: io.MultiWriter{
			writers: [
				InterceptorWriter{ interceptors: s.interceptors },
				s.stream
			]
		}
	}
}

pub struct ResponseWriter {
pub mut:
	server &Server
	writer io.Writer
}

pub interface Interceptor {
mut:
	on_encoded_response(resp []u8)
}

fn handle_conn(mut conn net.TcpConn) {
	defer { conn.close() or {} }

	mut srv := Server{
		stream: conn
		interceptors: []
	}

	srv.writer()
}

struct InterceptorWriter {
mut:
	interceptors []Interceptor
}

fn (mut wr InterceptorWriter) write(buf []u8) !int {
	for mut interceptor in wr.interceptors {
		interceptor.on_encoded_response(buf)
	}
	return buf.len
}


fn main() {
	addr := '127.0.0.1:42228'
	mut l := net.listen_tcp(.ip, addr)!
	println('TCP JSON-RPC server on ${addr} (Content-Length framing)')

	for {
		mut c := l.accept()!
		println("Accepted")
		go handle_conn(mut c)
	}
}

python3 script I use to trigger go handle_conn(mut c):

import socket


HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 42228        # The port used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall("test".encode("utf-8"))        
data = s.recv(409600)
print(data.decode())

Run v code, run python script (more in Current Behavior)

Expected Behavior

io.ReaderWriter as a superset of io.Writer should be casted to io.Writer as it contains all methods of io.Writer. For now I guess compiler is uncapable of that

Current Behavior

Errors either in runtime or compile time unable to use io.ReaderWriter as io.Writer
to reproduce: run v code, get an error:

examples/interfaces.v:19:7: error: cannot implement interface `io.Writer` with a different interface `io.ReaderWriter`
   17 |             writers: [
   18 |                 InterceptorWriter{ interceptors: s.interceptors },
   19 |                 s.stream
      |                   ~~~~~~
   20 |             ]
   21 |         }

If I as cast s.stream to io.Writer and run (pub fn (s &Server) writer() &ResponseWriter replacement):

pub fn (s &Server) writer() &ResponseWriter {
	return &ResponseWriter{
		server: s
		writer: io.MultiWriter{
			writers: [
				InterceptorWriter{ interceptors: s.interceptors },
				s.stream as io.Writer
			]
		}
	}
}

I get an error:

TCP JSON-RPC server on 127.0.0.1:42228 (Content-Length framing)
Accepted
V panic: `as_cast`: cannot convert net.TcpConn to io.Writer
 v hash: e3616f2
    pid: 0000000000000C14
    tid: 00000000000031A4
C:/Users/Te4nick/AppData/Local/Temp/v_0/interfaces.01KEH09VF1D4BJPKC3VE1K48MA.tmp.c:7710: at builtin___v_panic: Backtrace
C:/Users/Te4nick/AppData/Local/Temp/v_0/interfaces.01KEH09VF1D4BJPKC3VE1K48MA.tmp.c:3211: by I_io__ReaderWriter_as_I_io__Writer     
C:/Users/Te4nick/AppData/Local/Temp/v_0/interfaces.01KEH09VF1D4BJPKC3VE1K48MA.tmp.c:10939: by main__Server_writer
C:/Users/Te4nick/AppData/Local/Temp/v_0/interfaces.01KEH09VF1D4BJPKC3VE1K48MA.tmp.c:10943: by main__handle_conn
C:/Users/Te4nick/AppData/Local/Temp/v_0/interfaces.01KEH09VF1D4BJPKC3VE1K48MA.tmp.c:3356: by main__handle_conn_thread_wrapper       
00452f8e : by ???
0044f1be : by ???
00452fc8 : by ???
7ffc7f817374 : by ???

Trying to wrap it into if s.stream is io.Writer { ... } also gives no effect.

Possible Solution

Compiler supports casting superset Interfaces to subsets Interfaces normally (io.ReaderWriter as io.Writer)

Additional Information/Context

No response

V version

V 0.5.0 e6e28f1

Environment details (OS name and version, etc.)

V full version V 0.5.0 e3616f2.e6e28f1
OS windows, Windows 10 Pro 19045 64-bit
Processor 32 cpus, 64bit, little endian, Intel(R) Core(TM) i9-14900KF
Memory 17.03GB/31.77GB
V executable D:\Programming\V\v\v.exe
V last modified time 2026-01-09 09:15:53
V home dir OK, value: D:\Programming\V\v
VMODULES OK, value: C:\Users\Te4nick.vmodules
VTMP OK, value: C:\Users\Te4nick\AppData\Local\Temp\v_0
Current working dir OK, value: D:\Programming\V\rpcrud
Git version git version 2.45.1.windows.1
V git status weekly.2026.02-24-ge6e28f16
.git/config present true
cc version N/A
gcc version gcc (tdm64-1) 10.3.0
clang version N/A
msvc version N/A
tcc version tcc version 0.9.27 (x86_64 Windows)
tcc git status N/A
emcc version N/A
glibc version N/A

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugThis tag is applied to issues which reports bugs.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions