@@ -71,8 +71,8 @@ fn dynamic_bytes_external_parameters_are_rejected() {
7171fn static_bytes_external_parameters_are_rejected ( ) {
7272 let ns = compile_soroban (
7373 r#"contract test {
74- function len(bytes32 data) public returns (bytes32 ) {
75- return data;
74+ function len(bytes32 data) public returns (uint64 ) {
75+ return uint64( data.length) ;
7676 }
7777}"# ,
7878 ) ;
@@ -93,6 +93,104 @@ fn static_bytes_external_parameters_are_rejected() {
9393 . starts_with( "2:" ) ) ;
9494}
9595
96+ #[ test]
97+ fn string_external_returns_are_rejected ( ) {
98+ let ns = compile_soroban (
99+ r#"contract test {
100+ function public_make() public returns (string memory) {
101+ return "hello";
102+ }
103+
104+ function external_make() external returns (string memory) {
105+ return "hello";
106+ }
107+ }"# ,
108+ ) ;
109+
110+ let errors = ns
111+ . diagnostics
112+ . iter ( )
113+ . filter ( |diagnostic| diagnostic. level == Level :: Error )
114+ . collect :: < Vec < _ > > ( ) ;
115+
116+ assert_eq ! ( errors. len( ) , 2 ) ;
117+ assert ! ( errors. iter( ) . all( |diagnostic| diagnostic. message
118+ == "type 'string memory' is not supported as a Soroban external function return value" ) ) ;
119+
120+ let locations = errors
121+ . iter ( )
122+ . map ( |diagnostic| ns. loc_to_string ( PathDisplay :: None , & diagnostic. loc ) )
123+ . collect :: < Vec < _ > > ( ) ;
124+
125+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "2:" ) ) ) ;
126+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "6:" ) ) ) ;
127+ }
128+
129+ #[ test]
130+ fn bytes_external_returns_are_rejected ( ) {
131+ let ns = compile_soroban (
132+ r#"contract test {
133+ function public_make() public returns (bytes memory) {
134+ return hex"01";
135+ }
136+
137+ function external_make() external returns (bytes32) {
138+ return bytes32(uint256(1));
139+ }
140+ }"# ,
141+ ) ;
142+
143+ let errors = ns
144+ . diagnostics
145+ . iter ( )
146+ . filter ( |diagnostic| diagnostic. level == Level :: Error )
147+ . collect :: < Vec < _ > > ( ) ;
148+
149+ assert_eq ! ( errors. len( ) , 2 ) ;
150+ assert ! ( errors. iter( ) . any( |diagnostic| diagnostic. message
151+ == "type 'bytes memory' is not supported as a Soroban external function return value" ) ) ;
152+ assert ! ( errors. iter( ) . any( |diagnostic| diagnostic. message
153+ == "type 'bytes32' is not supported as a Soroban external function return value" ) ) ;
154+
155+ let locations = errors
156+ . iter ( )
157+ . map ( |diagnostic| ns. loc_to_string ( PathDisplay :: None , & diagnostic. loc ) )
158+ . collect :: < Vec < _ > > ( ) ;
159+
160+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "2:" ) ) ) ;
161+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "6:" ) ) ) ;
162+ }
163+
164+ #[ test]
165+ fn bytes_public_accessors_are_rejected ( ) {
166+ let ns = compile_soroban (
167+ r#"contract test {
168+ bytes public dynamic_data;
169+ bytes32 public fixed_data;
170+ }"# ,
171+ ) ;
172+
173+ let errors = ns
174+ . diagnostics
175+ . iter ( )
176+ . filter ( |diagnostic| diagnostic. level == Level :: Error )
177+ . collect :: < Vec < _ > > ( ) ;
178+
179+ assert_eq ! ( errors. len( ) , 2 ) ;
180+ assert ! ( errors. iter( ) . any( |diagnostic| diagnostic. message
181+ == "type 'bytes' is not supported as a Soroban public variable accessor return value" ) ) ;
182+ assert ! ( errors. iter( ) . any( |diagnostic| diagnostic. message
183+ == "type 'bytes32' is not supported as a Soroban public variable accessor return value" ) ) ;
184+
185+ let locations = errors
186+ . iter ( )
187+ . map ( |diagnostic| ns. loc_to_string ( PathDisplay :: None , & diagnostic. loc ) )
188+ . collect :: < Vec < _ > > ( ) ;
189+
190+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "2:" ) ) ) ;
191+ assert ! ( locations. iter( ) . any( |loc| loc. starts_with( "3:" ) ) ) ;
192+ }
193+
96194#[ test]
97195fn internal_private_dynamic_bytes_parameters_are_allowed ( ) {
98196 let ns = compile_soroban (
0 commit comments