Do they work like const T& in C++ with additional safeguards? (For example, explicit copy is needed). Or they are just copied, like regular parameters, literally having no effect (except not being consumable or implicitly copyable inside of the callee?).
Edit: Correct me if I am wrong, but the purpose of borrowing it to forbid consumption (and modification) of the parameters? Since let y = x and foo(x) can either copy x or forward x, borrowing strictly forbids forwarding and modification of the parameter. Whether x is copied as passed a reference to constant value is an implementation detail in case of Copyable arguments, but since x can not be modified or forwarded within the function, in general it should be safe to pass the argument as a reference to a constant, since borrowing implies that parameters stay alive during the execution of the function?
borrowing parameters are passed similarly to C++ const T & parameters, with the difference that Swift strictly prevents mutable aliasing of the parameter for the duration of the function call. This means that small values can transparently be passed by value without indirection, and that if the argument to a function call is not mutated in the caller, then the caller can pass along its borrow without copying. As you noted, the caller may still implicitly copy if the compiler thinks it needs to.
borrowing corresponds to the default calling convention for most functions, so from a caller's perspective, it doesn't have much effect. Inside of the callee, though, the parameter has implicit copies suppressed, so uses of that parameter binding that aren't able to borrow will raise errors unless you explicitly copy the value.
Is it correct to say that the consuming modifier on a parameter forces the consumption (i.e., a move, invalidating the original) of that parameter by the callee during an assignment, and also allows its mutation, while borrowing strictly forbids both its consumption and mutation? Consequently, as assignment is a potentially consuming operation, borrowing parameters cannot be directly used in assignments to prevent accidental consumption, unless they are explicitly copied using a copy operator.
Yeah, consuming has the analogous effect on the callee of suppressing implicit copies of the parameter, so assignment or other consuming operations will render the value unusable afterward unless you explicit copy it.