diff --git a/sway-core/src/language/parsed/expression/mod.rs b/sway-core/src/language/parsed/expression/mod.rs index 90d41fbf19b..24883d349d4 100644 --- a/sway-core/src/language/parsed/expression/mod.rs +++ b/sway-core/src/language/parsed/expression/mod.rs @@ -461,7 +461,6 @@ pub enum ExpressionKind { DelineatedPath(Box), /// A cast of a hash to an ABI for calling a contract. AbiCast(Box), - ArrayIndex(ArrayIndexExpression), StorageAccess(StorageAccessExpression), IntrinsicFunction(IntrinsicFunctionExpression), /// A control flow element which loops continually until some boolean expression evaluates as @@ -532,7 +531,6 @@ impl PartialEqWithEngines for ExpressionKind { lhs.eq(rhs, ctx) } (ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx), - (ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx), (ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => { lhs.eq(rhs, ctx) } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs index 0df9f72e458..8d7594f08b0 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs @@ -209,54 +209,83 @@ fn type_check_slice( _type_arguments: &[TypeArgument], span: Span, ) -> Result<(ty::TyIntrinsicFunctionKind, TypeId), ErrorEmitted> { - if arguments.len() != 3 { - return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs { - name: kind.to_string(), - expected: 3, - span, - })); - } - + // if arguments.len() != 3 { + // return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs { + // name: kind.to_string(), + // expected: 3, + // span, + // })); + // } + // let type_engine = ctx.engines.te(); let engines = ctx.engines(); - // start index argument - let start_type = type_engine.insert( + let uint64 = type_engine.insert( engines, TypeInfo::UnsignedInteger(IntegerBits::SixtyFour), None, ); - let start_ty_expr = { + + // check first argument + let first_argument_span = arguments[0].span.clone(); + let first_argument_type = type_engine.insert(engines, TypeInfo::Unknown, None); + let first_argument_ty_expr = { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(first_argument_type); + ty::TyExpression::type_check(handler, ctx, &arguments[0])? + }; + + // start index argument + let start_ty_expr = if arguments.get(1).is_some() { + let start_type = type_engine.insert( + engines, + TypeInfo::UnsignedInteger(IntegerBits::SixtyFour), + None, + ); + let ctx = ctx .by_ref() .with_help_text("") .with_type_annotation(start_type); ty::TyExpression::type_check(handler, ctx, &arguments[1])? + } else { + ty::TyExpression { + expression: ty::TyExpressionVariant::Literal(Literal::U64(0)), + return_type: uint64, + span: Span::dummy(), + } }; // end index argument - let end_type = type_engine.insert( - engines, - TypeInfo::UnsignedInteger(IntegerBits::SixtyFour), - None, - ); - let end_ty_expr = { + let end_ty_expr = if arguments.get(2).is_some() { + let end_type = type_engine.insert( + engines, + TypeInfo::UnsignedInteger(IntegerBits::SixtyFour), + None, + ); let ctx = ctx .by_ref() .with_help_text("") .with_type_annotation(end_type); ty::TyExpression::type_check(handler, ctx, &arguments[2])? - }; + } else { + let len = match &*type_engine.get(first_argument_ty_expr.return_type) { + TypeInfo::Ref { + referenced_type, .. + } => match &*type_engine.get(referenced_type.type_id) { + TypeInfo::Array(_, len) => len.val(), + x => unreachable!("{x:?}"), + }, + _ => unreachable!(), + }; - // check first argument - let first_argument_span = arguments[0].span.clone(); - let first_argument_type = type_engine.insert(engines, TypeInfo::Unknown, None); - let first_argument_ty_expr = { - let ctx = ctx - .by_ref() - .with_help_text("") - .with_type_annotation(first_argument_type); - ty::TyExpression::type_check(handler, ctx, &arguments[0])? + ty::TyExpression { + expression: ty::TyExpressionVariant::Literal(Literal::U64(len as u64)), + return_type: uint64, + span: Span::dummy(), + } }; // statically check start and end, if possible diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 47478b59e7b..47115ec611e 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -324,13 +324,6 @@ impl ty::TyExpression { ExpressionKind::Array(array_expression) => { Self::type_check_array(handler, ctx.by_ref(), &array_expression.contents, span) } - ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index }) => { - let ctx = ctx - .by_ref() - .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None)) - .with_help_text(""); - Self::type_check_array_index(handler, ctx, prefix, index, span) - } ExpressionKind::StorageAccess(StorageAccessExpression { namespace_names, field_names, @@ -1883,85 +1876,6 @@ impl ty::TyExpression { }) } - fn type_check_array_index( - handler: &Handler, - mut ctx: TypeCheckContext, - prefix: &Expression, - index: &Expression, - span: Span, - ) -> Result { - let type_engine = ctx.engines.te(); - let engines = ctx.engines(); - - let mut current_prefix_te = Box::new({ - let ctx = ctx - .by_ref() - .with_help_text("") - .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None)); - - ty::TyExpression::type_check(handler, ctx, prefix)? - }); - - let mut current_type = type_engine.get_unaliased(current_prefix_te.return_type); - - let prefix_type_id = current_prefix_te.return_type; - let prefix_span = current_prefix_te.span.clone(); - - // Create the prefix part of the final array index expression. - // This might be an expression that directly evaluates to an array type, - // or an arbitrary number of dereferencing expressions where the last one - // dereference to an array type. - // - // We will either hit an array at the end or return an error, so the - // loop cannot be endless. - while !current_type.is_array() { - match &*current_type { - TypeInfo::Ref { - referenced_type, .. - } => { - let referenced_type_id = referenced_type.type_id; - - current_prefix_te = Box::new(ty::TyExpression { - expression: ty::TyExpressionVariant::Deref(current_prefix_te), - return_type: referenced_type_id, - span: prefix_span.clone(), - }); - - current_type = type_engine.get_unaliased(referenced_type_id); - } - TypeInfo::ErrorRecovery(err) => return Err(*err), - _ => { - return Err(handler.emit_err(CompileError::NotIndexable { - actually: engines.help_out(prefix_type_id).to_string(), - span: prefix_span, - })) - } - }; - } - - let TypeInfo::Array(array_type_argument, _) = &*current_type else { - panic!("The current type must be an array."); - }; - - let index_te = { - let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour); - let ctx = ctx - .with_help_text("Array index must be of type \"u64\".") - .with_type_annotation(type_engine.insert(engines, type_info_u64, None)); - - ty::TyExpression::type_check(handler, ctx, index)? - }; - - Ok(ty::TyExpression { - expression: ty::TyExpressionVariant::ArrayIndex { - prefix: current_prefix_te, - index: Box::new(index_te), - }, - return_type: array_type_argument.type_id, - span, - }) - } - fn type_check_intrinsic_function( handler: &Handler, ctx: TypeCheckContext, @@ -2224,27 +2138,6 @@ impl ty::TyExpression { indices.push(ty::ProjectionKind::TupleField { index, index_span }); expr = prefix; } - ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index }) => { - let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour); - let ctx = ctx - .by_ref() - .with_help_text("Array index must be of type \"u64\".") - .with_type_annotation(type_engine.insert( - engines, - type_info_u64, - None, - )); - let typed_index = - ty::TyExpression::type_check(handler, ctx, index.as_ref()) - .unwrap_or_else(|err| { - ty::TyExpression::error(err, span.clone(), engines) - }); - indices.push(ty::ProjectionKind::ArrayIndex { - index: Box::new(typed_index), - index_span: index.span(), - }); - expr = prefix; - } _ => { return Err( handler.emit_err(CompileError::InvalidExpressionOnLhs { span }) diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 1b8e993e323..1ff1e07b273 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -586,9 +586,6 @@ impl Dependencies { .gather_from_iter(array_expression.contents.iter(), |deps, expr| { deps.gather_from_expr(engines, expr) }), - ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index, .. }) => self - .gather_from_expr(engines, prefix) - .gather_from_expr(engines, index), ExpressionKind::Struct(struct_expression) => { let StructExpression { call_path_binding, diff --git a/sway-core/src/semantic_analysis/symbol_resolve.rs b/sway-core/src/semantic_analysis/symbol_resolve.rs index 60ac3da6a53..51941d362ff 100644 --- a/sway-core/src/semantic_analysis/symbol_resolve.rs +++ b/sway-core/src/semantic_analysis/symbol_resolve.rs @@ -610,10 +610,6 @@ impl ResolveSymbols for ExpressionKind { expr.abi_name.resolve_symbols(handler, ctx.by_ref()); expr.address.resolve_symbols(handler, ctx.by_ref()); } - ExpressionKind::ArrayIndex(expr) => { - expr.index.resolve_symbols(handler, ctx.by_ref()); - expr.prefix.resolve_symbols(handler, ctx.by_ref()); - } ExpressionKind::StorageAccess(_expr) => {} ExpressionKind::IntrinsicFunction(expr) => { expr.arguments diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 4ed2e8799ab..a2d579cb871 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -2173,18 +2173,17 @@ fn expr_to_expression( let kind = expr_func_app_to_expression_kind(context, handler, engines, func, args)?; Expression { kind, span } } - Expr::Index { target, arg } => Expression { - kind: ExpressionKind::ArrayIndex(ArrayIndexExpression { - prefix: Box::new(expr_to_expression(context, handler, engines, *target)?), - index: Box::new(expr_to_expression( - context, - handler, - engines, - *arg.into_inner(), - )?), - }), - span, - }, + // this index is not "under" ref (&) or mut ref (&mut), so + // we need to deref it here + Expr::Index { target, arg } => { + let target = expr_to_expression(context, handler, engines, *target)?; + let arg = expr_to_expression(context, handler, engines, *arg.inner)?; + let expr = desugar_into_index_trait(false, arg.span(), span.clone(), target, arg)?; + Expression { + kind: ExpressionKind::Deref(Box::new(expr)), + span, + } + } Expr::MethodCall { target, path_seg, @@ -2270,12 +2269,25 @@ fn expr_to_expression( }, Expr::Ref { mut_token, expr, .. - } => Expression { - kind: ExpressionKind::Ref(RefExpression { - to_mutable_value: mut_token.is_some(), - value: Box::new(expr_to_expression(context, handler, engines, *expr)?), - }), - span, + } => match *expr { + Expr::Index { target, arg } => { + let target = expr_to_expression(context, handler, engines, *target)?; + let arg = expr_to_expression(context, handler, engines, *arg.inner)?; + desugar_into_index_trait( + mut_token.is_some(), + arg.span(), + span.clone(), + target, + arg, + )? + } + expr => Expression { + kind: ExpressionKind::Ref(RefExpression { + to_mutable_value: mut_token.is_some(), + value: Box::new(expr_to_expression(context, handler, engines, expr)?), + }), + span, + }, }, Expr::Deref { expr, .. } => Expression { kind: ExpressionKind::Deref(Box::new(expr_to_expression( @@ -2506,6 +2518,53 @@ fn expr_to_expression( Ok(expression) } +fn desugar_into_index_trait( + mutable: bool, + op_span: Span, + span: Span, + target: Expression, + arg: Expression, +) -> Result { + let target = Expression { + kind: ExpressionKind::IntrinsicFunction(IntrinsicFunctionExpression { + name: Ident::new_no_span("__slice".to_string()), + kind_binding: TypeBinding { + inner: Intrinsic::Slice, + type_arguments: TypeArgs::Regular(vec![]), + span: Span::dummy(), + }, + arguments: vec![Expression { + kind: ExpressionKind::Ref(RefExpression { + to_mutable_value: mutable, + value: Box::new(target), + }), + span: span.clone(), + }], + }), + span: span.clone(), + }; + + let name = if mutable { "index_mut" } else { "index" }; + + let call_path_binding = TypeBinding { + inner: CallPath { + prefixes: vec![], + suffix: Ident::new_with_override(name.into(), op_span.clone()), + is_absolute: true, + }, + type_arguments: TypeArgs::Regular(vec![]), + span: op_span, + }; + Ok(Expression { + kind: ExpressionKind::FunctionApplication(Box::new(FunctionApplicationExpression { + call_path_binding, + resolved_call_path_binding: None, + arguments: vec![target, arg], + })), + span, + }) +} + fn op_call( name: &'static str, op_span: Span, @@ -4441,24 +4500,34 @@ fn assignable_to_expression( kind: ExpressionKind::Variable(name), span, }, - ElementAccess::Index { target, arg } => Expression { - kind: ExpressionKind::ArrayIndex(ArrayIndexExpression { - prefix: Box::new(element_access_to_expression( - context, - handler, - engines, - *target, - span.clone(), - )?), - index: Box::new(expr_to_expression( - context, - handler, - engines, - *arg.into_inner(), - )?), - }), - span, - }, + ElementAccess::Index { target, arg } => { + let target = + element_access_to_expression(context, handler, engines, *target, span.clone())?; + let arg = expr_to_expression(context, handler, engines, *arg.inner)?; + let call = desugar_into_index_trait(true, arg.span(), span.clone(), target, arg)?; + Expression { + kind: ExpressionKind::Deref(Box::new(call)), + span, + } + } + // ElementAccess::Index { target, arg } => Expression { + // kind: ExpressionKind::ArrayIndex(ArrayIndexExpression { + // prefix: Box::new(element_access_to_expression( + // context, + // handler, + // engines, + // *target, + // span.clone(), + // )?), + // index: Box::new(expr_to_expression( + // context, + // handler, + // engines, + // *arg.into_inner(), + // )?), + // }), + // span, + // }, ElementAccess::FieldProjection { target, name, .. } => { let mut idents = vec![&name]; let mut base = &*target; diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index 7dd28960cb3..fc4fb7713e9 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -1258,3 +1258,55 @@ pub fn ok_str_eq() { assert("" != "a"); assert("a" != "b"); } + +// Index +pub trait Index { + type Output; + fn index(self, index: T) -> &Self::Output; +} + +pub trait IndexMut { + type Output; + fn index_mut(self, index: T) -> &mut Self::Output; +} + +impl Index for &__slice[T] { + type Output = T; + + fn index(self, index: u64) -> &Self::Output { + if index >= self.len() { + __revert(999); + } + __elem_at(self, index) + } +} + +impl Index for &mut __slice[T] { + type Output = T; + + fn index(self, index: u64) -> &Self::Output { + if index >= self.len() { + __revert(999); + } + __elem_at(self, index) + } +} + +impl IndexMut for &mut __slice[T] { + type Output = T; + + fn index_mut(self, index: u64) -> &mut T { + if index >= self.len() { + __revert(999); + } + __elem_at(self, index) + } +} + +pub fn index(target: &__slice[T], index: u64) -> &T { + target.index(index) +} + +pub fn index_mut(target: &mut __slice[T], index: u64) -> &mut T { + target.index_mut(index) +} diff --git a/sway-lsp/src/traverse/parsed_tree.rs b/sway-lsp/src/traverse/parsed_tree.rs index 880915f915b..c079b7f475b 100644 --- a/sway-lsp/src/traverse/parsed_tree.rs +++ b/sway-lsp/src/traverse/parsed_tree.rs @@ -18,20 +18,19 @@ use sway_core::{ decl_engine::parsed_id::ParsedDeclId, language::{ parsed::{ - AbiCastExpression, AbiDeclaration, AmbiguousPathExpression, ArrayExpression, - ArrayIndexExpression, AstNode, AstNodeContent, ConfigurableDeclaration, - ConstantDeclaration, Declaration, DelineatedPathExpression, EnumDeclaration, - EnumVariant, Expression, ExpressionKind, ForLoopExpression, - FunctionApplicationExpression, FunctionDeclaration, FunctionParameter, IfExpression, - ImplItem, ImplSelfOrTrait, ImportType, IncludeStatement, IntrinsicFunctionExpression, - LazyOperatorExpression, MatchExpression, MethodApplicationExpression, MethodName, - ParseModule, ParseProgram, ParseSubmodule, QualifiedPathType, ReassignmentExpression, - ReassignmentTarget, RefExpression, Scrutinee, StorageAccessExpression, - StorageDeclaration, StorageEntry, StorageField, StorageNamespace, StructDeclaration, - StructExpression, StructExpressionField, StructField, StructScrutineeField, - SubfieldExpression, Supertrait, TraitDeclaration, TraitFn, TraitItem, - TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, UseStatement, - VariableDeclaration, WhileLoopExpression, + AbiCastExpression, AbiDeclaration, AmbiguousPathExpression, ArrayExpression, AstNode, + AstNodeContent, ConfigurableDeclaration, ConstantDeclaration, Declaration, + DelineatedPathExpression, EnumDeclaration, EnumVariant, Expression, ExpressionKind, + ForLoopExpression, FunctionApplicationExpression, FunctionDeclaration, + FunctionParameter, IfExpression, ImplItem, ImplSelfOrTrait, ImportType, + IncludeStatement, IntrinsicFunctionExpression, LazyOperatorExpression, MatchExpression, + MethodApplicationExpression, MethodName, ParseModule, ParseProgram, ParseSubmodule, + QualifiedPathType, ReassignmentExpression, ReassignmentTarget, RefExpression, + Scrutinee, StorageAccessExpression, StorageDeclaration, StorageEntry, StorageField, + StorageNamespace, StructDeclaration, StructExpression, StructExpressionField, + StructField, StructScrutineeField, SubfieldExpression, Supertrait, TraitDeclaration, + TraitFn, TraitItem, TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, + UseStatement, VariableDeclaration, WhileLoopExpression, }, CallPathTree, HasSubmodules, Literal, }, @@ -308,10 +307,6 @@ impl Parse for Expression { ExpressionKind::AbiCast(abi_cast_expression) => { abi_cast_expression.parse(ctx); } - ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index, .. }) => { - prefix.parse(ctx); - index.parse(ctx); - } ExpressionKind::StorageAccess(StorageAccessExpression { field_names, namespace_names, diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_intrinsics/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_intrinsics/src/main.sw index 8b094c836ab..1ccaeed6607 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_intrinsics/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_intrinsics/src/main.sw @@ -1,101 +1,24 @@ script; -use utils::*; - -fn alloc_slice(len: u64) -> &mut __slice[T] { - let size_in_bytes = len * __size_of::(); - let ptr = asm(size_in_bytes: size_in_bytes) { - aloc size_in_bytes; - hp: raw_ptr - }; - asm(buf: (ptr, len)) { - buf: &mut __slice[T] - } -} - -fn realloc_slice(old: &mut __slice[T], len: u64) -> &mut __slice[T] { - let old_ptr = old.ptr(); - let old_len_in_bytes = old.len() * __size_of::(); - - let new_len_in_bytes = len * __size_of::(); - let new_ptr = asm(new_len_in_bytes: new_len_in_bytes, old_ptr: old_ptr, old_len_in_bytes: old_len_in_bytes) { - aloc new_len_in_bytes; - mcp hp old_ptr old_len_in_bytes; - hp: raw_ptr - }; - - asm(buf: (new_ptr, len)) { - buf: &mut __slice[T] - } -} - -pub struct Vec { - buf: &mut __slice[T], - len: u64, -} - -impl Dbg for Vec { - fn dbg(self) { - ( - "Vec { buf: (ptr: ", - asm(v: self.buf.ptr()) { v: u64 }, - ", len: ", - self.buf.len(), - "), len: ", - self.len, - ")" - ).dbg(); +fn assert_refs(l: &T, r: &T) +where + T: Eq + AbiEncode +{ + if *l != *r { + __log(*l); + __log(*r); + __revert(1) } } - -impl Vec { - pub fn new() -> Self { - Self { - buf: alloc_slice::(0), - len: 0 - } - } - - pub fn push(ref mut self, item: T) { - "Vec::push(...)".dbgln(); - (" ", self).dbgln(); - - let new_item_idx = self.len; - let current_cap = self.buf.len(); - if new_item_idx >= current_cap { - let new_cap = if current_cap == 0 { - 1 - } else { - current_cap * 2 - }; - self.buf = realloc_slice(self.buf, new_cap); - (" After realloc: ", self).dbgln(); - } - - let v: &mut T = __elem_at(self.buf, new_item_idx); - - let buffer_addr = asm(v: self.buf.ptr()) { v: u64 }; - let elem_addr = asm(v: v) { v: u64 }; - (" elem ", new_item_idx, " at ", elem_addr, " buffer offset (in bytes): ", elem_addr - buffer_addr).dbgln(); - *v = item; - - self.len += 1; - - (" ", self).dbgln(); - } - - pub fn get(self, index: u64) -> T { - ("Vec::get(", index, ")").dbgln(); - (" ", self).dbgln(); - - let item: &mut T = __elem_at(self.buf, index); - - let buffer_addr = asm(v: self.buf.ptr()) { v: u64 }; - let elem_addr = asm(v: item) { v: u64 }; - (" element ", index, " at ", elem_addr, " buffer offset (in bytes): ", elem_addr - buffer_addr).dbgln(); - - *item +fn assert_mut_refs(l: &mut T, r: &mut T) +where + T: Eq + AbiEncode +{ + if *l != *r { + __log(*l); + __log(*r); + __revert(1) } } @@ -110,74 +33,16 @@ where } } -fn type_check() { - let immutable_array: [u64; 5] = [1, 2, 3, 4, 5]; - let _: &u64 = __elem_at(&immutable_array, 0); - - let mut mutable_array: [u64; 5] = [1, 2, 3, 4, 5]; - let _: &u64 = __elem_at(&mutable_array, 0); - let _: &mut u64 = __elem_at(&mut mutable_array, 0); - let _: &u64 = __elem_at(&mut mutable_array, 0); - - let immutable_slice: &__slice[u64] = __slice(&immutable_array, 0, 5); - let _: &u64 = __elem_at(immutable_slice, 0); - - let mutable_slice: &mut __slice[u64] = __slice(&mut mutable_array, 0, 5); - let _: &mut u64 = __elem_at(mutable_slice, 0); - let _: &u64 = __elem_at(mutable_slice, 0); -} - fn main() { - type_check(); - - // index arrays - let some_array: [u64; 5] = [1, 2, 3, 4, 5]; - assert(1, *__elem_at(&some_array, 0)); - assert(2, *__elem_at(&some_array, 1)); - assert(3, *__elem_at(&some_array, 2)); - assert(4, *__elem_at(&some_array, 3)); - assert(5, *__elem_at(&some_array, 4)); - - // slice arrays - let some_slice: &__slice[u64] = __slice(&some_array, 0, 5); - assert(1, *__elem_at(some_slice, 0)); - assert(2, *__elem_at(some_slice, 1)); - assert(3, *__elem_at(some_slice, 2)); - assert(4, *__elem_at(some_slice, 3)); - assert(5, *__elem_at(some_slice, 4)); - - // slice another slice - let another_slice: &__slice[u64] = __slice(some_slice, 1, 4); - assert(2, *__elem_at(another_slice, 0)); - assert(3, *__elem_at(another_slice, 1)); - assert(4, *__elem_at(another_slice, 2)); - - // Vec impl using slices - let mut v: Vec = Vec::new(); - v.push(1); - assert(v.get(0), 1); - - v.push(2); - v.push(3); - assert(v.get(0), 1); - assert(v.get(1), 2); - assert(v.get(2), 3); - - v.push(4); - v.push(5); - v.push(6); - v.push(7); - assert(v.get(0), 1); - assert(v.get(1), 2); - assert(v.get(2), 3); - assert(v.get(3), 4); - assert(v.get(4), 5); - assert(v.get(5), 6); - assert(v.get(6), 7); + let mut a: [u64; 5] = [1, 2, 3, 4, 5]; - //indices as expressions - assert(2, *__elem_at(&some_array, v.get(0))); + assert(a[0], 1); + assert_refs(&a[0], &1); + assert_mut_refs(&mut a[0], &mut 1); + a[0] = 2; + assert(a[0], 2); + assert_refs(&a[0], &2); + assert_mut_refs(&mut a[0], &mut 2); - let _some_slice: &__slice[u64] = __slice(&some_array, v.get(0), v.get(4)); - assert(2, *__elem_at(some_slice, v.get(0))); + //a[5] = 2; }