Question: The documentation on Arduino's website shows `SoftwareSerial::read()` as returning a `char`. ([link](https://www.arduino.cc/en/Reference/SoftwareSerialRead))

The header shows that the method returns an `int`. ([link](https://github.com/arduino/ArduinoCore-avr/blob/7a2e1cd815266fef3012a5c9b48f88d78551f838/libraries/SoftwareSerial/src/SoftwareSerial.h#L103))

The cpp definition shows `SoftwareSerial::read()` returning the value from a buffer array of `uint8_t` values. ([link](https://github.com/arduino/ArduinoCore-avr/blob/7a2e1cd815266fef3012a5c9b48f88d78551f838/libraries/SoftwareSerial/src/SoftwareSerial.cpp#L402-L404))

Given all of this:

1. Why would the interface return an `int` instead of a `uint8_t`?
2. Why do the Arduino docs show it as returning a `char`?
3. Is it safe to send/receive 8-bits at a time using this library?

For (3) I'm using an HC-06 if that matters.

Answer: 
1. You'll see in the code just above your third link that the function can return a value of `-1` if there is no data present. Thus a 16-bit value is used to cover the range of 8-bit `uint8_t`s, plus one extra value to show 'no valid data available'.
2. For simplicity, I guess.
3. Yes. This is what it's designed for.

In short, for all intents and purposes, only an 8-bit value is returned, but if you were to read into an `int`, you couldn't differentiate between a valid and invalid value.
Stream declares `read` as returning `int` (look in `hardware/arduino/avr/cores/arduino/Stream.h`). `SofrtwareSerial` inherits from `Stream`, so they have to override that declaration, otherwise there would be two `read()` methods, one returning `int` and one returning `uint8_t`. Since `SoftwareSerial::read()` would onlyreturn an `int` between 0 and 255, which would fit in a `uint8_t`, there is no problem.

As for the Arduino docs, you get what you pay for :)