You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中能否判断函数参数是否为编译时常量?

实现仅接受编译时常量字符串的类型

问题分析

你需要创建一个只能存储源码字面量(或编译时计算的常量)字符串的类型,作为纵深防御机制,避免运行时生成的字符串被注入。现有尝试用const断言跨函数边界失效,且仅依赖'static生命周期无法区分运行时生成的字符串(如Box::leak创建的)。

稳定版解决方案:使用宏限制字面量输入

稳定版Rust中,最可靠的方式是用宏代替直接调用const fn,宏可以强制参数必须是字符串字面量或编译时常量表达式:

#[derive(Debug, Clone, Copy)]
struct StringLiteral(&'static str);

impl StringLiteral {
    // 私有内部构造函数,仅通过宏调用
    const fn new_inner(s: &'static str) -> Self {
        StringLiteral(s)
    }
}

// 宏仅接受字符串字面量或编译时常量表达式
macro_rules! string_literal {
    ($s:literal) => {
        StringLiteral::new_inner($s)
    };
}

// 合法用法:编译时常量/字面量
const EXAMPLE_LIT: StringLiteral = string_literal!("hello world");
const CONCAT_LIT: StringLiteral = string_literal!(concat!("foo", "bar"));

// 非法用法:运行时生成的字符串(编译报错)
// fn main() {
//     let runtime_str = Box::leak(String::from("attacker input").into_boxed_str());
//     let invalid = string_literal!(runtime_str); // 编译错误:expected a literal
// }

这个方案的核心是宏的$s:literal匹配器,它只接受字符串字面量或编译时可求值为字面量的表达式(如concat!),直接在编译阶段阻止运行时传入的值。

Nightly版解决方案:利用const_eval_select区分编译/运行时

如果你可以使用nightly Rust,可通过const_eval_select内置函数,在运行时调用时触发panic(或结合其他特性实现编译时错误):

#![feature(const_eval_select)]
#![feature(core_intrinsics)]

use std::intrinsics::const_eval_select;

#[derive(Debug, Clone, Copy)]
struct StringLiteral(&'static str);

impl StringLiteral {
    const fn new(s: &'static str) -> Self {
        // 编译时调用执行正常逻辑,运行时调用触发panic
        const_eval_select((),
            |_| StringLiteral(s),
            |_| panic!("StringLiteral::new can only be called in const context")
        )
    }
}

// 合法用法:编译时调用
const LIT: StringLiteral = StringLiteral::new("safe literal");

// 非法用法:运行时调用(编译通过但运行时panic)
// fn main() {
//     let runtime_str = Box::leak(String::from("malicious").into_boxed_str());
//     let invalid = StringLiteral::new(runtime_str); // 运行时panic
// }

补充说明

  • 若你的场景允许编译时计算的常量(如concat!生成的字符串),宏方案完全满足需求,且是稳定、安全的选择。
  • 仅依赖'static生命周期确实无法区分运行时生成的字符串,因为Box::leak可以将堆内存转为'static,必须通过编译阶段的检查来限制输入来源。

内容的提问来源于stack exchange,提问作者ais523

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:32:42