@@ -966,6 +966,19 @@ impl TypeCheckingVisitor<'_> {
966966 // Check that the operation is invoked in a `finalize` or `async` block.
967967 self . check_access_allowed ( "Mapping::get" , true , function_span) ;
968968
969+ // The receiver must be a path. Codegen lowers `Mapping::get` to an Aleo
970+ // `get` instruction whose first operand is a mapping name, so non-path
971+ // receivers (e.g. a ternary over mappings) cannot be lowered.
972+ if !matches ! ( map_expr, Expression :: Path ( _) ) {
973+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
974+ "Mapping" ,
975+ "get" ,
976+ "mapping" ,
977+ map_expr. span ( ) ,
978+ ) ) ;
979+ return Type :: Err ;
980+ }
981+
969982 * value. clone ( )
970983 }
971984 Intrinsic :: MappingSet => {
@@ -979,6 +992,18 @@ impl TypeCheckingVisitor<'_> {
979992 // Check that the operation is invoked in a `finalize` or `async` block.
980993 self . check_access_allowed ( "Mapping::set" , true , function_span) ;
981994
995+ // Receiver must be a path. Codegen emits an Aleo `set` whose first
996+ // operand is a mapping name.
997+ if !matches ! ( map_expr, Expression :: Path ( _) ) {
998+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
999+ "Mapping" ,
1000+ "set" ,
1001+ "mapping" ,
1002+ map_expr. span ( ) ,
1003+ ) ) ;
1004+ return Type :: Err ;
1005+ }
1006+
9821007 // Argument 0 must be a local path (cannot modify external mappings).
9831008 if !is_local_path ( map_expr) {
9841009 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1005,6 +1030,18 @@ impl TypeCheckingVisitor<'_> {
10051030 return Type :: Err ;
10061031 } ;
10071032
1033+ // The receiver must be a path. Codegen lowers `Mapping::get_or_use` to an
1034+ // Aleo `get.or_use` instruction whose first operand is a mapping name.
1035+ if !matches ! ( map_expr, Expression :: Path ( _) ) {
1036+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1037+ "Mapping" ,
1038+ "get_or_use" ,
1039+ "mapping" ,
1040+ map_expr. span ( ) ,
1041+ ) ) ;
1042+ return Type :: Err ;
1043+ }
1044+
10081045 value. deref ( ) . clone ( )
10091046 }
10101047 Intrinsic :: MappingRemove => {
@@ -1021,6 +1058,18 @@ impl TypeCheckingVisitor<'_> {
10211058 return Type :: Err ;
10221059 } ;
10231060
1061+ // Receiver must be a path. Codegen emits an Aleo `remove` whose first
1062+ // operand is a mapping name.
1063+ if !matches ! ( map_expr, Expression :: Path ( _) ) {
1064+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1065+ "Mapping" ,
1066+ "remove" ,
1067+ "mapping" ,
1068+ map_expr. span ( ) ,
1069+ ) ) ;
1070+ return Type :: Err ;
1071+ }
1072+
10241073 // Argument 0 must be a local path (cannot modify external mappings).
10251074 if !is_local_path ( map_expr) {
10261075 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1047,6 +1096,18 @@ impl TypeCheckingVisitor<'_> {
10471096 return Type :: Err ;
10481097 } ;
10491098
1099+ // The receiver must be a path. Codegen lowers `Mapping::contains` to an
1100+ // Aleo `contains` instruction whose first operand is a mapping name.
1101+ if !matches ! ( map_expr, Expression :: Path ( _) ) {
1102+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1103+ "Mapping" ,
1104+ "contains" ,
1105+ "mapping" ,
1106+ map_expr. span ( ) ,
1107+ ) ) ;
1108+ return Type :: Err ;
1109+ }
1110+
10501111 Type :: Boolean
10511112 }
10521113 Intrinsic :: OptionalUnwrap => {
@@ -1082,6 +1143,19 @@ impl TypeCheckingVisitor<'_> {
10821143 // Check that the operation is invoked in a `finalize` or `async` block.
10831144 self . check_access_allowed ( "Vector::get" , true , function_span) ;
10841145
1146+ // The receiver must be a path. storage_lowering looks up the backing
1147+ // mappings by name, so non-path receivers (e.g. a ternary over storage
1148+ // vectors) cannot be lowered.
1149+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1150+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1151+ "Vector" ,
1152+ "get" ,
1153+ "storage vector" ,
1154+ vec_expr. span ( ) ,
1155+ ) ) ;
1156+ return Type :: Err ;
1157+ }
1158+
10851159 Type :: Optional ( OptionalType { inner : Box :: new ( * element_type. clone ( ) ) } )
10861160 }
10871161 Intrinsic :: VectorSet => {
@@ -1095,6 +1169,18 @@ impl TypeCheckingVisitor<'_> {
10951169 // Check that the operation is invoked in a `finalize` or `async` block.
10961170 self . check_access_allowed ( "Vector::set" , true , function_span) ;
10971171
1172+ // Receiver must be a path (storage_lowering needs to identify the backing
1173+ // mappings by name).
1174+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1175+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1176+ "Vector" ,
1177+ "set" ,
1178+ "storage vector" ,
1179+ vec_expr. span ( ) ,
1180+ ) ) ;
1181+ return Type :: Err ;
1182+ }
1183+
10981184 // Argument 0 must be a local path (cannot modify external vectors).
10991185 if !is_local_path ( vec_expr) {
11001186 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1123,6 +1209,18 @@ impl TypeCheckingVisitor<'_> {
11231209 // Check that the operation is invoked in a `finalize` or `async` block.
11241210 self . check_access_allowed ( "Vector::push" , true , function_span) ;
11251211
1212+ // Receiver must be a path (storage_lowering needs to identify the backing
1213+ // mappings by name).
1214+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1215+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1216+ "Vector" ,
1217+ "push" ,
1218+ "storage vector" ,
1219+ vec_expr. span ( ) ,
1220+ ) ) ;
1221+ return Type :: Err ;
1222+ }
1223+
11261224 // Argument 0 must be a local path (cannot modify external vectors).
11271225 if !is_local_path ( vec_expr) {
11281226 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1141,12 +1239,25 @@ impl TypeCheckingVisitor<'_> {
11411239 // Check that the operation is invoked in a `finalize` or `async` block.
11421240 self . check_access_allowed ( "Vector::len" , true , function_span) ;
11431241
1144- if vec_ty. is_vector ( ) {
1145- Type :: Integer ( IntegerType :: U32 )
1146- } else {
1242+ if !vec_ty. is_vector ( ) {
11471243 self . assert_vector_type ( vec_ty, vec_expr. span ( ) ) ;
1148- Type :: Err
1244+ return Type :: Err ;
1245+ }
1246+
1247+ // The receiver must be a path. storage_lowering looks up the backing
1248+ // mappings by name, so non-path receivers (e.g. a ternary over storage
1249+ // vectors) cannot be lowered.
1250+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1251+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1252+ "Vector" ,
1253+ "len" ,
1254+ "storage vector" ,
1255+ vec_expr. span ( ) ,
1256+ ) ) ;
1257+ return Type :: Err ;
11491258 }
1259+
1260+ Type :: Integer ( IntegerType :: U32 )
11501261 }
11511262 Intrinsic :: VectorPop => {
11521263 let ( vec_ty, vec_expr) = & arguments[ 0 ] ;
@@ -1159,6 +1270,18 @@ impl TypeCheckingVisitor<'_> {
11591270 return Type :: Err ;
11601271 } ;
11611272
1273+ // Receiver must be a path (storage_lowering needs to identify the backing
1274+ // mappings by name).
1275+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1276+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1277+ "Vector" ,
1278+ "pop" ,
1279+ "storage vector" ,
1280+ vec_expr. span ( ) ,
1281+ ) ) ;
1282+ return Type :: Err ;
1283+ }
1284+
11621285 // Argument 0 must be a local path (cannot modify external vectors).
11631286 if !is_local_path ( vec_expr) {
11641287 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1182,6 +1305,18 @@ impl TypeCheckingVisitor<'_> {
11821305 return Type :: Err ;
11831306 } ;
11841307
1308+ // Receiver must be a path (storage_lowering needs to identify the backing
1309+ // mappings by name).
1310+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1311+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1312+ "Vector" ,
1313+ "swap_remove" ,
1314+ "storage vector" ,
1315+ vec_expr. span ( ) ,
1316+ ) ) ;
1317+ return Type :: Err ;
1318+ }
1319+
11851320 // Argument 0 must be a local path (cannot modify external vectors).
11861321 if !is_local_path ( vec_expr) {
11871322 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
@@ -1202,6 +1337,18 @@ impl TypeCheckingVisitor<'_> {
12021337 return Type :: Err ;
12031338 }
12041339
1340+ // Receiver must be a path (storage_lowering needs to identify the backing
1341+ // mappings by name).
1342+ if !matches ! ( vec_expr, Expression :: Path ( _) ) {
1343+ self . state . handler . emit_err ( crate :: errors:: type_checker:: storage_op_requires_path_receiver (
1344+ "Vector" ,
1345+ "clear" ,
1346+ "storage vector" ,
1347+ vec_expr. span ( ) ,
1348+ ) ) ;
1349+ return Type :: Err ;
1350+ }
1351+
12051352 // Argument 0 must be a local path (cannot modify external vectors).
12061353 if !is_local_path ( vec_expr) {
12071354 self . state . handler . emit_err ( crate :: errors:: type_checker:: cannot_modify_external_container (
0 commit comments