cairo-lang-semantic 2.21.0

Cairo semantic model.
Documentation
//! > different S3 and @S3 derefs.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
#[derive(Drop, Copy)]
struct S1 {
    a: usize,
    b: felt252,
}

#[derive(Drop, Copy)]
struct S2 {
    inner: S1,
    c: usize,
}

#[derive(Drop)]
struct S3 {
    inner: S2,
}


impl S2Deref of core::ops::Deref<S2> {
    type Target = S1;
    fn deref(self: S2) -> S1 {
        self.inner
    }
}

impl S3Deref of core::ops::Deref<S3> {
    type Target = S2;
    fn deref(self: S3) -> S2 {
        self.inner
    }
}

impl S3SnapDeref of core::ops::Deref<@S3> {
    type Target = S1;
    fn deref(self: @S3) -> S1 {
        *self.inner.inner
    }
}
fn foo() {
    let s1 = S1 { a: 1, b: 2 };
    let s2 = S2 { inner: s1, c: 5 };
    let s3 = S3 { inner: s2 };

    (@s3).a;
    s3.c;
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Test method call through deref.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
#[derive(Drop, Copy)]
struct S1 {
    a: usize,
    b: felt252,
}

#[derive(Drop, Copy)]
struct S2 {
    inner: S1,
    c: usize,
}

impl S2Deref of core::ops::Deref<S2> {
    type Target = S1;
    fn deref(self: S2) -> S1 {
        self.inner
    }
}

#[generate_trait]
impl MyImpl of MyTrait {
    fn foo(self: @S1) {}
}
fn foo() {
    let s1 = S1 { a: 1, b: 2 };
    let s2 = S2 { inner: s1, c: 5 };

    s2.foo();
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Test method call through box.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
fn foo() {
    let a = BoxTrait::new(@array![1_u32]);
    let _ = a.len();
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Calling deref on a box.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
fn foo() {
    let mut a = BoxTrait::new(@array![1_u32]);
    let _ = (*a);
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Calling deref on DerefMut.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
struct S1 {
    inner: usize,
}

impl S1DerefMut of core::ops::DerefMut<S1> {
    type Target = usize;
    fn deref_mut(ref self: S1) -> Self::Target {
        self.inner
    }
}
fn foo() {
    let mut a = S1 { inner: 1 };
    let _ = (*a);
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Calling deref on DerefMut with non mutable variable.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > cairo_code
struct S1 {
    inner: usize,
}

impl S1DerefMut of core::ops::DerefMut<S1> {
    type Target = usize;
    fn deref_mut(ref self: S1) -> Self::Target {
        self.inner
    }
}
fn foo() {
    let a = S1 { inner: 1 };
    let _ = (*a);
}

//! > expected_diagnostics
error[E2135]: Type `S1` cannot be dereferenced
 --> lib.cairo:13:14
    let _ = (*a);
             ^

//! > ==========================================================================

//! > Final deref return values should decide the number of snapshots - single snapshot.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
struct A {
    a: usize,
    b: usize,
}
fn foo(a: Box<@A>) -> @usize {
    a.b
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Final deref return values should decide the number of snapshots - multiple snapshots.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > cairo_code
struct A {
    a: usize,
    b: usize,
}
fn foo(a: Box<@@@A>) -> @@@usize {
    a.b
}

//! > expected_diagnostics

//! > ==========================================================================

//! > Deref impl missing its associated type reports the trait-item mismatch instead of an ICE.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > cairo_code
#[derive(Drop)]
struct Inner {}

#[derive(Drop)]
struct MyBox {}

// `type Target` is missing: resolving a method through the deref chain used to ICE.
impl MyDeref of core::ops::Deref<MyBox> {
    fn deref(self: MyBox) -> Inner {
        Inner {}
    }
}
fn foo() {
    let b = MyBox {};
    b.get();
}

//! > expected_diagnostics
error[E0004]: Not all trait items are implemented. Missing: 'Target'.
 --> lib.cairo:8:6
impl MyDeref of core::ops::Deref<MyBox> {
     ^^^^^^^

error[E0002]: Method `get` could not be called on type `MyBox`.
Candidate `ArrayTrait::get` inference failed with: Type mismatch: `MyBox` and `@Array::<?0>`.
Candidate `SpanTrait::get` inference failed with: Type mismatch: `MyBox` and `Span::<?0>`.
Candidate `Felt252DictTrait::get` inference failed with: Type mismatch: `MyBox` and `Felt252Dict::<?0>`.
 --> lib.cairo:15:7
    b.get();
      ^^^

//! > ==========================================================================

//! > Deref chain where a downstream impl is missing its associated type.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > cairo_code
#[derive(Drop)]
struct A {}

#[derive(Drop)]
struct B {}

#[derive(Drop)]
struct C {}

impl ADeref of core::ops::Deref<A> {
    type Target = B;
    fn deref(self: A) -> B {
        B {}
    }
}

// `type Target` is missing on the second hop of the deref chain.
impl BDeref of core::ops::Deref<B> {
    fn deref(self: B) -> C {
        C {}
    }
}

//! > expected_diagnostics
error[E0004]: Not all trait items are implemented. Missing: 'Target'.
 --> lib.cairo:18:6
impl BDeref of core::ops::Deref<B> {
     ^^^^^^

//! > ==========================================================================

//! > Deref chain where a downstream impl has more than one associated type.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > cairo_code
#[derive(Drop)]
struct A {}

#[derive(Drop)]
struct B {}

#[derive(Drop)]
struct C {}

impl ADeref of core::ops::Deref<A> {
    type Target = B;
    fn deref(self: A) -> B {
        B {}
    }
}

// An extra associated type on the second hop of the deref chain.
impl BDeref of core::ops::Deref<B> {
    type Target = C;
    type Extra = C;
    fn deref(self: B) -> C {
        C {}
    }
}

//! > expected_diagnostics
error[E2014]: Impl item type `BDeref::Extra` is not a member of trait `Deref`.
 --> lib.cairo:20:5
    type Extra = C;
    ^^^^^^^^^^^^^^^