This is mostly for Jonathan Drolet but there's also a lesson here.
Note that parameter argument to my_function supplies a type mark with a subtype indication. This is valid in VHDL.
entity myfunc is
architecture foo of myfunc is
function my_function(lv: std_logic_vector(3 downto 0))
return std_logic_vector is
return lv & "000";
constant fumble: std_logic_vector (3 downto 0) := x"E";
signal humble: std_logic_vector (6 downto 0);
humble <= my_function(fumble);
This code analyzes, elaborates and simulates.
Note that the return mark is an unconstrained subtype and the result value is assigned to a declared signal with a subtype indication (supplying an index constraint).
There are rules specifically for determining the effective value of a signal that require the bounds be checked after an implicit subtype conversion. Providing a return value that doesn't match the bounds of
humble would result in a run time error causing simulation to end without successfully completing.
In other words a constraint isn't necessary here. The return value subtype indication is derived internally, and as is shown in this from the input parameter.