ink_codegen/enforced_error.rs
1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use impl_serde::serialize as serde_hex;
16use quote::format_ident;
17
18/// Errors which may occur when forwarding a call is not allowed.
19///
20/// We insert markers for these errors in the generated contract code.
21/// This is necessary since we can't check these errors at compile time
22/// of the contract.
23/// `cargo-contract` checks the contract code for these error markers
24/// when building a contract and fails if it finds markers.
25#[derive(scale::Encode, scale::Decode)]
26pub enum EnforcedErrors {
27 /// The below error represents calling a `&mut self` message in a context that
28 /// only allows for `&self` messages. This may happen under certain circumstances
29 /// when ink! trait implementations are involved with long-hand calling notation.
30 #[codec(index = 1)]
31 CannotCallTraitMessage {
32 /// The trait that defines the called message.
33 trait_ident: String,
34 /// The name of the called message.
35 message_ident: String,
36 /// The selector of the called message.
37 message_selector: [u8; 4],
38 /// Is `true` if the `self` receiver of the ink! message is `&mut self`.
39 message_is_mut: bool,
40 },
41}
42
43impl EnforcedErrors {
44 /// Create the identifier of an enforced ink! compilation error.
45 fn into_ident(self) -> syn::Ident {
46 format_ident!(
47 "__ink_enforce_error_{}",
48 serde_hex::to_hex(&scale::Encode::encode(&self), false)
49 )
50 }
51
52 /// Creates an enforced linker error to signal that an invalid
53 /// implementation of an ink! trait message has been called.
54 pub fn cannot_call_trait_message(
55 trait_ident: &syn::Ident,
56 message_ident: &syn::Ident,
57 message_selector: ir::Selector,
58 message_is_mut: bool,
59 ) -> syn::Ident {
60 Self::CannotCallTraitMessage {
61 trait_ident: trait_ident.to_string(),
62 message_ident: message_ident.to_string(),
63 message_selector: message_selector.to_bytes(),
64 message_is_mut,
65 }
66 .into_ident()
67 }
68}