diesel-rs/diesel · error · syn::Error

last statement should be an expression for auto_type

Error message

last statement should be an expression for auto_type

What it means

After locating the last statement, auto_type requires it to be an expression (or a bare `return expr;`) because the macro infers the function's `-> _` return type from that final expression. Any other trailing statement (a let binding, an item, an empty `return;`, a statement with a semicolon producing ()) triggers this compile error.

Solutions

  1. Make the last statement a plain expression without a trailing semicolon: end with `value` instead of `value;`.
  2. Convert a final `return expr;` into a trailing expression, or keep `return expr;` (ExprReturn with expr) which is supported.
  3. Move any trailing let/item statements before the final expression.

Example fix

// before
#[auto_type]
fn f() -> _ {
    let x = 1;
}
// after
#[auto_type]
fn f() -> _ {
    let x = 1;
    x
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the body ends with an expression (no trailing semicolon on last stmt):
fn ends_with_expr(stmts: &[syn::Stmt]) -> bool {
    matches!(stmts.last(), Some(syn::Stmt::Expr(_, None)) | Some(syn::Stmt::Expr(syn::Expr::Return(_), _)))
}

Prevention

When it happens

Trigger: Function body ending in e.g. `let x = 1;` as the last statement, or `return;` with no value, under #[auto_type].

Common situations: Writing a function in statement style then annotating it with auto_type; forgetting that a trailing semicolon turns the expression into a statement; early-refactor leftovers.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07). Data as JSON: /api/errors/657cca5387a2ec86. Report an issue: GitHub.

Appendix: source

Thrown at dsl_auto_type/src/auto_type/mod.rs:162

                        Ok(()) => {}
                        Err(e) => errors.push(Rc::new(e)),
                    }
                };
            }

            // Add local variables from the function body, and finally infer the type
            local_variables_map.infer_block_expression_type(
                return_expression,
                Some(&return_type),
                &input_function.block,
                &mut errors,
            )
        }
        _ => {
            // This error message is not strictly correct: we also support
            // partially-specified return types that involve `_`, but for simplicity we just
            // put the overwhelmingly most common case in this error message
            return Err(syn::Error::new(
                input_function.sig.output.span(),
                "Function return type should be explicitly specified as `-> _` for auto_type",
            )
            .into());
        }
    };

    let type_alias = match type_alias {
        Some(type_alias) => {
            // We're generating a type alias so we need to extract the necessary lifetimes and
            // generic type parameters for that type alias
            let type_alias_generics = referenced_generics::extract_referenced_generics(
                &return_type,
                &input_function.sig.generics,
                &mut errors,
            );

            let vis = &input_function.vis;

View on GitHub (pinned to 6fa6ed01b2)