proto-attr Compile Error Showcase

Unknown Extension Attribute

Using an unknown ORM attribute like indexed produces a clear error
listing all available attributes (skip, rename, column).

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::indexed)]
    id: i64,
}

fn main() {}

Compiler Error

error: unknown attribute `indexed`; did you mean `index`?
 --> src/main.rs:5:24
  |
5 |     #[faket(proto_ext::indexed)]
  |                        ^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Typo in Attribute Name

Common typos like skp instead of skip are caught at compile time
with a helpful "did you mean?" suggestion.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::skp)]
    password_hash: String,
}

fn main() {}

Compiler Error

error: unknown attribute `skp`; did you mean `skip`?
 --> src/main.rs:5:24
  |
5 |     #[faket(proto_ext::skp)]
  |                        ^^^

error: could not compile test (bin "test") due to 1 previous error

Unit Attribute with Arguments

The skip attribute is a unit variant that takes no arguments.
Passing arguments produces a clear error explaining the correct usage.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::skip("serialization"))]
    password_hash: String,
}

fn main() {}

Compiler Error

error: `skip` does not take arguments; use just `skip`
 --> src/main.rs:5:24
  |
5 |     #[faket(proto_ext::skip("serialization"))]
  |                        ^^^^

error: could not compile test (bin "test") due to 1 previous error

Newtype Attribute Missing Value

The rename attribute requires a string value to specify the new name.
Omitting the value produces an error showing the expected syntax.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::rename)]
struct UserProfile {
    email: String,
}

fn main() {}

Compiler Error

error: `rename` requires a string value: `rename("name")` or `rename = "name"`
 --> src/main.rs:4:20
  |
4 | #[faket(proto_ext::rename)]
  |                    ^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Unknown Field in Struct Attribute

Typos in field names like nam instead of name are caught
with a "did you mean?" suggestion and list of valid fields
(name, nullable, sql_type, primary_key, auto_increment).

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(nam = "user_id", primary_key))]
    id: i64,
}

fn main() {}

Compiler Error

error: unknown field `nam`; did you mean `name`? Known fields: name, nullable, sql_type, primary_key, auto_increment
 --> src/main.rs:5:31
  |
5 |     #[faket(proto_ext::column(nam = "user_id", primary_key))]
  |                               ^^^

error: could not compile test (bin "test") due to 1 previous error

Struct Field Missing Value

The name field in column requires a string value.
Using it as a flag produces an error showing the correct syntax.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(name, primary_key))]
    id: i64,
}

fn main() {}

Compiler Error

error: `name` requires a string value: `name = "value"`
         = help: Override the database column name; use `name = "col_name"` (defaults to Rust field name)
 --> src/main.rs:5:31
  |
5 |     #[faket(proto_ext::column(name, primary_key))]
  |                               ^^^^

error: could not compile test (bin "test") due to 1 previous error

Index Field Typo (list_string)

Typos in field names like column instead of columns are caught
with a helpful "did you mean?" suggestion.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(column = ["id", "email"]))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: unknown field `column`; did you mean `columns`? Known fields: name, columns, unique
 --> src/main.rs:4:26
  |
4 | #[faket(proto_ext::index(column = ["id", "email"]))]
  |                          ^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Index Wrong Type for List

The columns field expects a list like ["a", "b"], not a string.
Using the wrong type produces a clear error explaining the expected format.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(columns = "email"))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: `columns` expects a list, not a single string; try `columns = ["email"]`
         = help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
 --> src/main.rs:4:36
  |
4 | #[faket(proto_ext::index(columns = "email"))]
  |                                    ^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Range Wrong Type for Integer

The min and max fields in range expect integers, not strings.
Using a string produces an error showing the correct syntax.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::range(min = "zero", max = 100))]
    age: i32,
}

fn main() {}

Compiler Error

error: `min` expected integer literal, got `"zero"`
 --> src/main.rs:5:36
  |
5 |     #[faket(proto_ext::range(min = "zero", max = 100))]
  |                                    ^^^^^^

error: could not compile test (bin "test") due to 1 previous error

OnDelete String Instead of Identifier

The action field expects a bare identifier like cascade, not a string.
The error message suggests removing the quotes: action = cascade.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct Post {
    #[faket(proto_ext::on_delete(action = "cascade"))]
    author_id: i64,
}

fn main() {}

Compiler Error

error: `action` expects a bare identifier, not a string; try `action = cascade` (without quotes)
         = help: What happens when referenced row is deleted; use `action = cascade` (delete), `set_null`, `restrict` (prevent), or `no_action`
 --> src/main.rs:5:43
  |
5 |     #[faket(proto_ext::on_delete(action = "cascade"))]
  |                                           ^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Duplicate Field

Specifying the same field twice in an attribute is an error.
Each field can only appear once in an attribute.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(name = "user_id", name = "id"))]
    id: i64,
}

fn main() {}

Compiler Error

error: duplicate field `name`; each field can only be specified once
 --> src/main.rs:5:49
  |
5 |     #[faket(proto_ext::column(name = "user_id", name = "id"))]
  |                                                 ^^^^

error: could not compile test (bin "test") due to 1 previous error

Mixed Types in List

List fields require all elements to be the same type.
A string list like columns cannot contain integers.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(columns = ["email", 123]))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: expected string literal in list, got `123`
 --> src/main.rs:4:46
  |
4 | #[faket(proto_ext::index(columns = ["email", 123]))]
  |                                              ^^^

error: could not compile test (bin "test") due to 1 previous error

Wrong Bracket Type for List

Lists use square brackets [...], not curly braces {...}.
The error specifically tells you to use square brackets.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(columns = {"email"}))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: `columns` expects square brackets `[]`, not curly braces `{}`; try `columns = ["a", "b"]`
         = help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
 --> src/main.rs:4:36
  |
4 | #[faket(proto_ext::index(columns = {"email"}))]
  |                                    ^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Integer Overflow

The error shows the field name, the value, and the schema-defined type.
Each integer field in the grammar specifies its type (here: i64).

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::range(min = 99999999999999999999999))]
    score: i32,
}

fn main() {}

Compiler Error

error: `min` value `99999999999999999999999` is too large; this field accepts i64 (range -9223372036854775808 to 9223372036854775807)
 --> src/main.rs:5:36
  |
5 |     #[faket(proto_ext::range(min = 99999999999999999999999))]
  |                                    ^^^^^^^^^^^^^^^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Bool Field with String Value

Boolean fields expect true or false literals, not strings.
The error suggests removing the quotes: primary_key = true.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(primary_key = "true"))]
    id: i64,
}

fn main() {}

Compiler Error

error: `primary_key` expects `true` or `false`, not a string; try `primary_key = true` (without quotes)
         = help: Mark as primary key; use `primary_key` or `primary_key = true` (tables typically have one primary key)
 --> src/main.rs:5:45
  |
5 |     #[faket(proto_ext::column(primary_key = "true"))]
  |                                             ^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Integer Field Used as Flag

Integer fields require a value; they cannot be used as flags.
Using min without = value produces an error.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::range(min, max = 100))]
    age: i32,
}

fn main() {}

Compiler Error

error: `min` requires an integer value: `min = 42`
         = help: Minimum allowed value (inclusive); use `min = 0` to reject negative numbers
 --> src/main.rs:5:30
  |
5 |     #[faket(proto_ext::range(min, max = 100))]
  |                              ^^^

error: could not compile test (bin "test") due to 1 previous error

Identifier Instead of String

String fields require quoted values, not bare identifiers.
The error suggests adding quotes: name = "user_id".

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(name = user_id))]
    id: i64,
}

fn main() {}

Compiler Error

error: `name` expects a string literal, not an identifier; try `name = "user_id"` (with quotes)
         = help: Override the database column name; use `name = "col_name"` (defaults to Rust field name)
 --> src/main.rs:5:38
  |
5 |     #[faket(proto_ext::column(name = user_id))]
  |                                      ^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Single String Instead of List

List fields require [...] syntax even for a single element.
The error suggests wrapping in brackets: columns = ["email"].

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(columns = "email"))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: `columns` expects a list, not a single string; try `columns = ["email"]`
         = help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
 --> src/main.rs:4:36
  |
4 | #[faket(proto_ext::index(columns = "email"))]
  |                                    ^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Help Text: Column Primary Key

Error messages include contextual help explaining the field AND how to use it.
The help shows: correct syntax, typical usage, and semantic meaning.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::column(primary_key = "yes"))]
    id: i64,
}

fn main() {}

Compiler Error

error: `primary_key` expects `true` or `false`, not a string; try `primary_key = true` (without quotes)
         = help: Mark as primary key; use `primary_key` or `primary_key = true` (tables typically have one primary key)
 --> src/main.rs:5:45
  |
5 |     #[faket(proto_ext::column(primary_key = "yes"))]
  |                                             ^^^^^

error: could not compile test (bin "test") due to 1 previous error

Help Text: Index Columns

The help text explains that columns specifies which columns
to include in the index: "Columns to include in the index".

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(proto_ext::index(columns))]
struct UserIndex {
    id: i64,
    email: String,
}

fn main() {}

Compiler Error

error: `columns` requires a list value: `columns = ["a", "b"]`
         = help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
 --> src/main.rs:4:26
  |
4 | #[faket(proto_ext::index(columns))]
  |                          ^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Help Text: Range Min

The help text clarifies that min is the "Minimum value (inclusive)".
Doc comments in the grammar DSL become contextual help in errors.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct User {
    #[faket(proto_ext::range(min = "zero"))]
    age: i32,
}

fn main() {}

Compiler Error

error: `min` expected integer literal, got `"zero"`
 --> src/main.rs:5:36
  |
5 |     #[faket(proto_ext::range(min = "zero"))]
  |                                    ^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Valid Usage

When ORM attributes are used correctly, everything compiles smoothly.
This shows realistic usage patterns:
• skip - exclude structs/fields from generation
• rename - map to different table/column names
• column - full control: name, nullable, sql_type, primary_key, auto_increment
• index - database indexes with columns list (list_string field type)
• range - validation bounds with min/max (opt_i64 field type)
• on_delete - foreign key behavior with bare identifiers (ident field type)

Rust Input

use proto_attr::Faket;

/// A table we want to exclude from ORM generation
#[derive(Faket)]
#[faket(proto_ext::skip)]
struct InternalCache {
    data: Vec<u8>,
}

/// Map to a different table name
#[derive(Faket)]
#[faket(proto_ext::rename("user_profiles"))]
struct UserProfile {
    email: String,
}

/// Full ORM column configuration example
#[derive(Faket)]
#[faket(proto_ext::index(name = "idx_user_email", columns = ["email"], unique))]
struct User {
    /// Primary key with auto-increment
    #[faket(proto_ext::column(name = "id", primary_key, auto_increment))]
    id: i64,

    /// Custom column name
    #[faket(proto_ext::column(name = "user_name"))]
    name: String,

    /// Nullable TEXT field for bio
    #[faket(proto_ext::column(nullable, sql_type = "TEXT"))]
    bio: Option<String>,

    /// Non-nullable timestamp
    #[faket(proto_ext::column(nullable = false, sql_type = "TIMESTAMP"))]
    created_at: i64,

    /// Skip sensitive field from serialization
    #[faket(proto_ext::skip)]
    password_hash: String,

    /// Rename field for API compatibility
    #[faket(proto_ext::rename("email_address"))]
    email: String,

    /// Validation: age must be between 0 and 150
    #[faket(proto_ext::range(min = 0, max = 150, message = "Age must be realistic"))]
    age: i32,
}

/// Foreign key with ON DELETE behavior
#[derive(Faket)]
struct Post {
    #[faket(proto_ext::column(primary_key, auto_increment))]
    id: i64,

    /// When author is deleted, cascade delete their posts
    #[faket(proto_ext::on_delete(action = cascade))]
    author_id: i64,

    /// When category is deleted, set to null
    #[faket(proto_ext::on_delete(action = set_null))]
    category_id: Option<i64>,

    title: String,
}

/// Composite index example
#[derive(Faket)]
#[faket(proto_ext::index(columns = ["user_id", "created_at"]))]
#[faket(proto_ext::index(name = "idx_status", columns = ["status"], unique))]
struct Order {
    #[faket(proto_ext::column(primary_key))]
    id: i64,
    user_id: i64,
    status: String,
    created_at: i64,
}

fn main() {
    println!("Compiles successfully!");
}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Basic Attributes

Top-level facet attributes like transparent, untagged, and rename_all
work without a namespace prefix.

Rust Input

use proto_attr::Faket;

/// A newtype wrapper (transparent)
#[derive(Faket)]
#[faket(transparent)]
struct UserId(i64);

/// An untagged enum
#[derive(Faket)]
#[faket(untagged)]
enum Message {
    Text(String),
    Number(i64),
}

/// Struct with rename_all for field case conversion
#[derive(Faket)]
#[faket(rename_all = "kebab-case")]
struct Config {
    api_key: String,
    max_retries: i32,
}

fn main() {}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Multiple Attrs Combined

Multiple top-level attributes can be combined in a single #[faket(...)].
Commas separate distinct attributes, respecting balanced parentheses.

Rust Input

use proto_attr::Faket;

/// Tagged enum with custom tag and content field names
#[derive(Faket)]
#[faket(tag = "type", content = "payload")]
enum Event {
    Click { x: i32, y: i32 },
    KeyPress(String),
}

/// Struct with multiple top-level attrs
#[derive(Faket)]
#[faket(deny_unknown_fields, default, rename_all = "camelCase")]
struct ApiRequest {
    user_id: i64,
    request_type: String,
}

fn main() {}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Mixed with Namespaced

Top-level facet attributes and namespaced extension attributes can be
freely mixed in the same #[faket(...)] or on different lines.

Rust Input

use proto_attr::Faket;

/// Mix top-level facet attrs with extension attrs on a struct
#[derive(Faket)]
#[faket(rename_all = "snake_case", proto_ext::index(columns = ["id", "name"]))]
struct User {
    #[faket(proto_ext::column(primary_key, auto_increment))]
    id: i64,

    #[faket(default, proto_ext::column(name = "user_name"))]
    name: String,

    #[faket(proto_ext::skip, proto_ext::rename("ignored"))]
    internal_cache: Vec<u8>,
}

fn main() {}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Field-Level Attrs

Top-level attributes like default and untagged can also be used
at the field level, mixed with extension attributes.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
struct Settings {
    /// Field uses default if missing
    #[faket(default)]
    timeout_ms: i64,

    /// Multiple field attrs: default + extension
    #[faket(default, proto_ext::range(min = 1, max = 100))]
    max_retries: i32,

    /// Combining untagged with column config (field-level)
    #[faket(untagged, proto_ext::column(nullable))]
    optional_data: Option<String>,
}

fn main() {}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Complex Real-World Example

A complete real-world example combining:
• Struct-level: deny_unknown_fields, rename_all, index
• Field-level: default, column, range, skip, rename, on_delete
• Enum: tag, content, rename_all

Rust Input

use proto_attr::Faket;

/// A complete API model with all attribute types
#[derive(Faket)]
#[faket(deny_unknown_fields, rename_all = "camelCase")]
#[faket(proto_ext::index(name = "idx_api_model", columns = ["id", "created_at"], unique))]
struct ApiModel {
    #[faket(proto_ext::column(primary_key, auto_increment, name = "model_id"))]
    id: i64,

    #[faket(default, proto_ext::column(sql_type = "TIMESTAMP"))]
    created_at: i64,

    #[faket(proto_ext::rename("modelName"), proto_ext::column(name = "name"))]
    model_name: String,

    #[faket(default, proto_ext::range(min = 0, max = 1000000))]
    score: i64,

    #[faket(proto_ext::skip)]
    internal_state: Vec<u8>,

    #[faket(proto_ext::on_delete(action = cascade))]
    parent_id: Option<i64>,
}

/// Enum with adjacently tagged representation
#[derive(Faket)]
#[faket(tag = "kind", content = "data", rename_all = "SCREAMING_SNAKE_CASE")]
enum ApiResponse {
    Success { value: i64 },
    Error { code: i32, message: String },
    Pending,
}

fn main() {}

Compiler Error

✓ Compilation successful! No errors.

Top-Level: Unknown Attribute Error

Using an unknown top-level attribute produces a helpful error
with suggestions for valid attributes.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(unknown_attr)]
struct Bad {
    field: i32,
}

fn main() {}

Compiler Error

error: unknown attribute `unknown_attr`; expected one of: transparent, untagged, rename_all, tag, content, deny_unknown_fields, default, skip, rename, column, index, range, on_delete
 --> src/main.rs:4:9
  |
4 | #[faket(unknown_attr)]
  |         ^^^^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Top-Level: Wrong Syntax Error

Top-level unit attributes like transparent don't take arguments.
The error message explains the correct usage.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(transparent("value"))]
struct Bad(i64);

fn main() {}

Compiler Error

error: `transparent` does not take arguments; use just `transparent`
 --> src/main.rs:4:9
  |
4 | #[faket(transparent("value"))]
  |         ^^^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error

Top-Level: Missing Value Error

Newtype attributes like rename_all require a value.
Omitting it produces a clear error.

Rust Input

use proto_attr::Faket;

#[derive(Faket)]
#[faket(rename_all)]
struct Bad {
    field: i32,
}

fn main() {}

Compiler Error

error: `rename_all` requires a string value: `rename_all("name")` or `rename_all = "name"`
 --> src/main.rs:4:9
  |
4 | #[faket(rename_all)]
  |         ^^^^^^^^^^

error: could not compile test (bin "test") due to 1 previous error