cairo-lang-semantic 2.18.0

Cairo semantic model.
Documentation
//! > Negative impls

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > function_code
fn foo(a: u8) -> Option<u8> {
    let b: Option<u8> = a.try_into();
    b
}

//! > function_name
foo

//! > module_code
use core::traits::TryInto;
pub trait DowncastableInt<Type>;

impl DowncastableIntU8 of DowncastableInt<u8> {}

pub trait TypeEq<S, T> {}

impl ImplTypeEq<T> of TypeEq<T, T> {}

impl DowncastableTryInto<
    From, To, +DowncastableInt<From>, +DowncastableInt<To>, -TypeEq<From, To>,
> of TryInto<From, To> {
    fn try_into(self: From) -> Option<To> {
        core::integer::downcast(self)
    }
}

//! > expected_diagnostics

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

//! > Negative impls with generic args.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo(a: u8) -> u8 {
    bar(a)
}

//! > function_name
foo

//! > module_code
trait MyTrait<T> {
    fn f(t: T) -> T;
}
impl MyImpl<T, -Drop<T>> of MyTrait<T> {
    fn f(t: T) -> T {
        t
    }
}

fn bar<T>(t: T) -> T {
    MyTrait::f(t)
}

//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: test::MyTrait::<T>.
 --> lib.cairo:11:14
    MyTrait::f(t)
             ^

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

//! > Test negative impls infer impl with existing negative impl.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo() -> u32 {
    MyTrait2::foo(5_u32)
}

//! > function_name
foo

//! > module_code
pub trait MyTrait<T> {}

impl I of MyTrait<u32> {}

pub trait MyTrait2<T> {
    fn foo(self: T) -> T;
}

impl I2<T, -MyTrait<T>> of MyTrait2<T> {
    fn foo(self: T) -> T {
        self
    }
}

//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: test::MyTrait2::<core::integer::u32>.
 --> lib.cairo:15:15
    MyTrait2::foo(5_u32)
              ^^^

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

//! > Test negative impls use impl with existing negative impl.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo() -> u32 {
    I2::foo(5_u32)
}

//! > function_name
foo

//! > module_code
pub trait MyTrait<T> {}

impl I of MyTrait<u32> {}

pub trait MyTrait2<T> {
    fn foo(self: T) -> T;
}

impl I2<T, -MyTrait<T>> of MyTrait2<T> {
    fn foo(self: T) -> T {
        self
    }
}

//! > expected_diagnostics
error[E2312]: Trait has implementation in context: test::MyTrait::<core::integer::u32>.
 --> lib.cairo:15:5
    I2::foo(5_u32)
    ^^

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

//! > Test negative impls infer impl with generic param.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > function_code
fn foo() {}

//! > function_name
foo

//! > module_code
pub trait Consumer<T> {
    fn consume(self: T, input: u32);
    fn bar(x: T);
}

pub trait Producer<T> {
    fn produce(self: T) -> u32;
}

pub struct ProducerType {}

impl ProducerImpl of Producer<ProducerType> {
    fn produce(self: ProducerType) -> u32 {
        3_u32
    }
}

impl TConsumerImpl<T, +core::fmt::Debug<T>, +Drop<T>, -Producer<T>> of Consumer<T> {
    fn consume(self: T, input: u32) {
        println!("{:?} consumed value: {}", self, input);
    }
    fn bar(x: T) {
        let producer = ProducerType {};

        let production = producer.produce();
        Consumer::consume(x, production);
    }
}

//! > expected_diagnostics

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

//! > Test negative impls infer negative impl

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo() {
    Trait3::bar();
}

//! > function_name
foo

//! > module_code
trait Trait<T> {}

impl I of Trait<u32> {}

trait Trait2 {
    fn foo();
}

impl Unusable<-Trait<u32>> of Trait2 {
    fn foo() {}
}

trait Trait3 {
    fn bar();
}

impl I3<-Trait<u32>> of Trait3 {
    fn bar() {
        // The following line works because `I3` has the same negative impl as `Unusable`.
        Trait2::foo();
    }
}

//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: test::Trait3.
 --> lib.cairo:24:13
    Trait3::bar();
            ^^^

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

//! > Test negative impl failure with generic fixed size array.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > function_code
fn foo() {
    bar::<felt252>();
}

//! > function_name
foo

//! > module_code
use core::metaprogramming::TypeEqual;
trait MyTrait {
    fn f();
}

impl MyImpl<T, const SIZE: usize, -TypeEqual<[T; SIZE], [T; 0]>> of MyTrait {
    #[inline]
    fn f() {}
}

fn bar<T>() {
    MyImpl::<T, 1>::f();
}

//! > expected_diagnostics

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

//! > Test anonymous impl inside negative impl.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo() {
    Bad::<u128>::bad();
}

//! > function_name
foo

//! > module_code
pub trait NegImpl<+Drop<u32>> {}

pub trait Bad<T> {
    fn bad() -> T;
}

pub impl ImplBad<T, -NegImpl<_>> of Bad<T> {
    fn bad() -> T {
        panic!("Bad::bad() called")
    }
}

//! > expected_diagnostics
error[E2196]: Negative impls may only use type or const generic parameters.
 --> lib.cairo:1:19
pub trait NegImpl<+Drop<u32>> {}
                  ^^^^^^^^^^

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

//! > Test negative impl with generic const inside a type.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)

//! > function_code
fn foo() {
    bar::<5>();
}

//! > function_name
foo

//! > module_code
use core::metaprogramming::TypeEqual;
pub trait NegImpl<T> {}

struct A<const B: u32> {}

fn bar<const B: u32>() {
    Bad::bad();
}

pub trait Bad {
    fn bad() -> u32;
}

pub impl ImplBad<const C: u32, -TypeEqual<A<C>, A<0>>> of Bad {
    fn bad() -> u32 {
        C
    }
}

//! > expected_diagnostics
error[E2313]: Cannot infer trait core::metaprogramming::TypeEqual::<test::A::<?0>, test::A::<0>>. First generic argument must be known.
 --> lib.cairo:7:10
    Bad::bad();
         ^^^

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

//! > Test negative impl with generic param that is not var free.

//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)

//! > function_code
fn foo(a: u32) -> (u32, u32) {
    let s0 = array![a].span();
    let s1 = array![a + 1].span();
    let cols = array![s0, s1].span();

    let [mut c0, mut c1] = (*cols.try_into().unwrap()).unbox();

    (*c0.pop_front().unwrap(), *c1.pop_front().unwrap())
}

//! > function_name
foo

//! > module_code

//! > expected_diagnostics