bon-3.7.1/.cargo_vcs_info.json0000644000000001410000000000100116160ustar { "git": { "sha1": "bc940a1209420d3a613f8ea4ecf1992d984b9951" }, "path_in_vcs": "bon" }bon-3.7.1/Cargo.lock0000644000000353430000000000100076050ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "backtrace" version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets", ] [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bon" version = "3.7.1" dependencies = [ "bon-macros", "expect-test", "macro_rules_attribute", "rustversion", "tokio", "trybuild", ] [[package]] name = "bon-macros" version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca5abbf2d4a4c6896197c9de13d6d7cb7eff438c63dacde1dde980569cb00248" dependencies = [ "darling", "ident_case", "prettyplease", "proc-macro2", "quote", "rustversion", "syn", ] [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "darling" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a79c4acb1fd5fa3d9304be4c76e031c54d2e92d172a393e24b19a14fe8532fe9" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74875de90daf30eb59609910b84d4d368103aaec4c924824c6799b28f77d6a1d" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", "syn", ] [[package]] name = "darling_macro" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79f8e61677d5df9167cd85265f8e5f64b215cdea3fb55eebc3e622e44c7a146" dependencies = [ "darling_core", "quote", "syn", ] [[package]] name = "dissimilar" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "expect-test" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" dependencies = [ "dissimilar", "once_cell", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "io-uring" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" dependencies = [ "bitflags", "cfg-if", "libc", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "macro_rules_attribute" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" dependencies = [ "macro_rules_attribute-proc_macro", "paste", ] [[package]] name = "macro_rules_attribute-proc_macro" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "miniz_oxide" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi", "windows-sys", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "prettyplease" version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "rustc-demangle" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" dependencies = [ "serde", ] [[package]] name = "slab" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-triple" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "tokio" version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "io-uring", "libc", "mio", "pin-project-lite", "slab", "tokio-macros", ] [[package]] name = "tokio-macros" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "toml" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "toml_parser", "toml_writer", "winnow", ] [[package]] name = "toml_datetime" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" dependencies = [ "serde", ] [[package]] name = "toml_parser" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" dependencies = [ "winnow", ] [[package]] name = "toml_writer" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" [[package]] name = "trybuild" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65af40ad689f2527aebbd37a0a816aea88ff5f774ceabe99de5be02f2f91dae2" dependencies = [ "glob", "serde", "serde_derive", "serde_json", "target-triple", "termcolor", "toml", ] [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" bon-3.7.1/Cargo.toml0000644000000137520000000000100076300ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.59.0" name = "bon" version = "3.7.1" build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Next-gen compile-time-checked builder generator, named function's arguments, and more!" homepage = "https://bon-rs.com" readme = "README.md" keywords = [ "builder", "macro", "derive", "constructor", "setter", ] categories = [ "rust-patterns", "data-structures", "asynchronous", "no-std", "no-std::no-alloc", ] license = "MIT OR Apache-2.0" repository = "https://github.com/elastio/bon" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [features] alloc = ["bon-macros/alloc"] default = ["std"] experimental-getter = [] experimental-overwritable = ["bon-macros/experimental-overwritable"] implied-bounds = ["bon-macros/implied-bounds"] std = [ "bon-macros/std", "alloc", ] [lib] name = "bon" path = "src/lib.rs" [[test]] name = "integration" path = "tests/integration/main.rs" [dependencies.bon-macros] version = "=3.7.1" [dependencies.rustversion] version = "1" [dev-dependencies.expect-test] version = "1.4.1" [dev-dependencies.macro_rules_attribute] version = "0.2" [dev-dependencies.tokio] version = "1.29.1" features = [ "macros", "rt", ] [dev-dependencies.trybuild] version = "1.0.89" [lints.clippy] assertions_on_result_states = "warn" await_holding_refcell_ref = "warn" bool_to_int_with_if = "warn" borrow_as_ptr = "warn" branches_sharing_code = "warn" cast_lossless = "warn" cast_ptr_alignment = "warn" checked_conversions = "warn" clear_with_drain = "warn" cloned_instead_of_copied = "warn" collection_is_never_read = "warn" copy_iterator = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" default_union_representation = "warn" doc_link_with_quotes = "warn" doc_markdown = "warn" empty_drop = "warn" empty_line_after_doc_comments = "warn" empty_line_after_outer_attr = "warn" expl_impl_clone_on_copy = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" float_cmp = "warn" fn_params_excessive_bools = "warn" fn_to_numeric_cast_any = "warn" format_push_string = "warn" if_then_some_else_none = "warn" implicit_clone = "warn" implicit_saturating_sub = "warn" imprecise_flops = "warn" index_refutable_slice = "warn" indexing_slicing = "warn" invalid_upcast_comparisons = "warn" iter_not_returning_iterator = "warn" iter_on_empty_collections = "warn" iter_with_drain = "warn" large_include_file = "warn" linkedlist = "warn" lossy_float_literal = "warn" manual_clamp = "warn" manual_instant_elapsed = "warn" manual_let_else = "allow" manual_ok_or = "warn" many_single_char_names = "warn" map_flatten = "warn" map_unwrap_or = "allow" match_wild_err_arm = "warn" maybe_infinite_iter = "warn" mixed_read_write_in_expression = "warn" mut_mut = "warn" naive_bytecount = "warn" needless_bitwise_bool = "warn" needless_collect = "warn" needless_continue = "warn" needless_for_each = "warn" negative_feature_names = "warn" no_effect_underscore_binding = "warn" no_mangle_with_rust_abi = "warn" non_send_fields_in_send_ty = "warn" nonstandard_macro_braces = "warn" or_fun_call = "warn" path_buf_push_overwrite = "warn" ptr_as_ptr = "warn" range_minus_one = "warn" range_plus_one = "warn" rc_buffer = "warn" rc_mutex = "warn" read_zero_byte_vec = "warn" redundant_clone = "warn" redundant_feature_names = "warn" ref_binding_to_reference = "warn" ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" same_functions_in_if_condition = "warn" string_lit_as_bytes = "warn" suboptimal_flops = "warn" suspicious_operation_groupings = "warn" suspicious_xor_used_as_pow = "warn" trailing_empty_array = "warn" trait_duplication_in_bounds = "warn" transmute_ptr_to_ptr = "warn" transmute_undefined_repr = "warn" try_err = "warn" type_repetition_in_bounds = "warn" unchecked_duration_subtraction = "warn" unicode_not_nfc = "warn" unnecessary_join = "warn" unnecessary_self_imports = "warn" unnecessary_struct_initialization = "warn" unnecessary_wraps = "warn" unnested_or_patterns = "warn" unused_async = "warn" unused_peekable = "warn" unused_rounding = "warn" useless_let_if_seq = "warn" useless_transmute = "warn" verbose_bit_mask = "warn" wildcard_dependencies = "warn" zero_sized_map_values = "warn" [lints.clippy.nursery] level = "warn" priority = -2 [lints.clippy.pedantic] level = "warn" priority = -1 [lints.rust] deprecated_safe = "warn" elided_lifetimes_in_paths = "warn" explicit_outlives_requirements = "warn" ffi_unwind_calls = "warn" let_underscore_drop = "warn" macro_use_extern_crate = "warn" meta_variable_misuse = "warn" missing_abi = "warn" missing_debug_implementations = "warn" missing_docs = "warn" missing_unsafe_on_extern = "warn" non_ascii_idents = "warn" non_local_definitions = "warn" redundant_lifetimes = "warn" single_use_lifetimes = "warn" trivial_casts = "warn" trivial_numeric_casts = "warn" unit_bindings = "warn" unnameable_types = "warn" unreachable_pub = "warn" unsafe_code = "warn" unstable_features = "warn" unused_extern_crates = "warn" unused_import_braces = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" variant_size_differences = "warn" [lints.rust.rust_2024_compatibility] level = "warn" priority = 1 [lints.rust.tail_expr_drop_order] level = "allow" priority = 2 [lints.rust.unexpected_cfgs] level = "warn" priority = 0 check-cfg = ["cfg(nightly)"] [lints.rustdoc] missing_crate_level_docs = "warn" unescaped_backticks = "warn" bon-3.7.1/Cargo.toml.orig000064400000000000000000000065671046102023000133170ustar 00000000000000[package] name = "bon" version = "3.7.1" description = "Next-gen compile-time-checked builder generator, named function's arguments, and more!" categories = [ "rust-patterns", "data-structures", "asynchronous", "no-std", "no-std::no-alloc", ] keywords = ["builder", "macro", "derive", "constructor", "setter"] edition = "2021" homepage = "https://bon-rs.com" license = "MIT OR Apache-2.0" repository = "https://github.com/elastio/bon" # This MSRV was chosen because Rust supports mixing generic type and const # parameters only starting with this version. We require this feature for the # cases when the builder is generated for a function or struct that uses const # generics. The generated builder **always** appends a generic type parameter # for the type state at the end of the Builder generics list. So for functions # or structs that use const generics the generated builder will have a generic # type parameter after the const generic parameter, which is only supported # starting from Rust 1.59.0. rust-version = "1.59.0" [package.metadata.docs.rs] all-features = true # Generate clickable links in the source code view in the docs rustdoc-args = ["--generate-link-to-definition"] # We don't need the docs to be built for every first-tier target. # This crate is not platform-specific. targets = ["x86_64-unknown-linux-gnu"] [lints] workspace = true [dependencies] # The version of the macro crate is pinned to a specific one because the code # generated by the macros uses private APIs from the runtime crate that are not # guarded by semver. bon-macros = { path = "../bon-macros", version = "=3.7.1" } rustversion = "1" [dev-dependencies] # Using a bit older version that supports our MSRV expect-test = "1.4.1" # Using a bit older version that supports our MSRV tokio = { version = "1.29.1", features = ["macros", "rt"] } macro_rules_attribute = "0.2" # Using a bit older version that supports our MSRV trybuild = "1.0.89" [features] alloc = ["bon-macros/alloc"] default = ["std"] std = ["bon-macros/std", "alloc"] # See the explanation of what this feature does in the docs here: # https://bon-rs.com/guide/typestate-api/custom-methods#implied-bounds implied-bounds = ["bon-macros/implied-bounds"] # 🔬 Experimental! There may be breaking changes to this feature between *minor* releases, # however, compatibility within patch releases is guaranteed though. # # This feature enables the #[builder(overwritable)] attribute that can be used to # allow overwriting already set fields in the builder. Without this attribute it's # not possible to set the same member twice in the builder, a compile error would be # generated. # # See more info at https://bon-rs.com/reference/builder/top-level/overwritable. # # We are considering stabilizing this attribute if you have a use for it. Please leave # a 👍 reaction under the issue https://github.com/elastio/bon/issues/149 if you need # this attribute. It would also be cool if you could leave a comment under that issue # describing your use case for it. experimental-overwritable = ["bon-macros/experimental-overwritable"] # Legacy experimental attribute. It's left here for backwards compatibility, # and it will be removed in the next major release. # # We've stabilized the MVP of this feature, so it's no longer experimental. # The tracking issue for this feature: https://github.com/elastio/bon/issues/225. experimental-getter = [] bon-3.7.1/README.md000064400000000000000000000201601046102023000116700ustar 00000000000000 bon home
github crates.io docs.rs docs.rs

📖 Guide Book Narrative introduction
🔍 API Reference Attributes API index
# Overview `bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods. If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust). ## Function Builder You can turn a function with positional parameters into a function with named parameters with `#[builder]`. ```rust use bon::builder; #[builder] fn greet(name: &str, level: Option) -> String { let level = level.unwrap_or(0); format!("Hello {name}! Your level is {level}") } let greeting = greet() .name("Bon") .level(24) // <- setting `level` is optional, we could omit it .call(); assert_eq!(greeting, "Hello Bon! Your level is 24"); ``` Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc. Many things are customizable with additional attributes described in the [API reference](https://bon-rs.com/reference/builder), but let's see what else `bon` has to offer. ## Struct Builder Use `#[derive(Builder)]` to generate a builder for a struct. ```rust use bon::Builder; #[derive(Builder)] struct User { name: String, is_admin: bool, level: Option, } let user = User::builder() .name("Bon".to_owned()) // `level` is optional, we could omit it here .level(24) // call setters in any order .is_admin(true) .build(); assert_eq!(user.name, "Bon"); assert_eq!(user.level, Some(24)); assert!(user.is_admin); ``` ## Method Builder Associated methods require `#[bon]` on top of the impl block additionally. ### Method `new` The method named `new` generates `builder()/build()` methods. ```rust use bon::bon; struct User { id: u32, name: String, } #[bon] impl User { #[builder] fn new(id: u32, name: String) -> Self { Self { id, name } } } let user = User::builder() .id(1) .name("Bon".to_owned()) .build(); assert_eq!(user.id, 1); assert_eq!(user.name, "Bon"); ``` `#[derive(Builder)]` on a struct generates builder API that is fully compatible with placing `#[builder]` on the `new()` method with a signature similar to the struct's fields (more details on the [Compatibility](https://bon-rs.com/guide/basics/compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page). ### Other Methods All other methods generate `{method_name}()/call()` methods. ```rust use bon::bon; struct Greeter { name: String, } #[bon] impl Greeter { #[builder] fn greet(&self, target: &str, prefix: Option<&str>) -> String { let prefix = prefix.unwrap_or("INFO"); let name = &self.name; format!("[{prefix}] {name} says hello to {target}") } } let greeter = Greeter { name: "Bon".to_owned() }; let greeting = greeter .greet() .target("the world") // `prefix` is optional, omitting it is fine .call(); assert_eq!(greeting, "[INFO] Bon says hello to the world"); ``` Methods with or without `self` are both supported. ## No Panics Possible Builders generated by `bon`'s macros use the typestate pattern to ensure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites. If something is wrong, a compile error will be created. | ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! | | --------------------------------------------------------------------------------------- | ## What's Next? What you've seen above is the first page of the 📖 Guide Book. If you want to learn more, jump to the [Basics](https://bon-rs.com/guide/basics) section. And remember: knowledge is power 🐱! Feel free to jump to code and use the `#[builder]` and `#[derive(Builder)]` once you've seen enough docs to get started. The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate the attributes once you feel comfortable with the basics of `bon`. Both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost identical attributes API, so the documentation for them is common. ## Installation Add `bon` to your `Cargo.toml`. ```toml [dependencies] bon = "3.7" ``` You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments. ## Acknowledgments This project was heavily inspired by such awesome crates as [`buildstructor`](https://docs.rs/buildstructor), [`typed-builder`](https://docs.rs/typed-builder) and [`derive_builder`](https://docs.rs/derive_builder). This crate was designed with many lessons learned from them. See [alternatives](https://bon-rs.com/guide/alternatives) for comparison. ## Supporters
Big thanks to `bon`'s current financial supporters ❤️ **Ethan Skowronski**\ $1/month **Julius Lungys**\ $1/month
## Past Supporters
Big thanks to `bon`'s past financial supporters ❤️ [![](https://github.com/user-attachments/assets/b0acb844-4b91-461c-95ae-90a601296500)](https://kindness.ai)\ [**Kindness**](https://kindness.ai)
## Who's Using `bon`? Some notable open-source users: [`crates.io` backend](https://github.com/rust-lang/crates.io), [`tantivy`](https://github.com/quickwit-oss/tantivy), [`apache-avro`](https://github.com/apache/avro-rs), [`google-cloud-auth`](https://github.com/googleapis/google-cloud-rust), [`comrak`](https://github.com/kivikakk/comrak), [`ractor`](https://github.com/slawlor/ractor). ## Getting Help If you can't figure something out, consult the docs and maybe use the `🔍 Search` bar on our [docs website](https://bon-rs.com). You may also create an issue or a discussion on the [Github repository](https://github.com/elastio/bon) for help or write us a message on [Discord](https://bon-rs.com/discord). ## Socials
Discord Here you can leave feedback, ask questions, report bugs, etc.
## License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. bon-3.7.1/src/__/better_errors.rs000064400000000000000000000016351046102023000150120ustar 00000000000000//! Utility functions for improving error messages in builder's generated code. //! //! These free functions are simple wrappers over the respective traits. They allow the //! generated code to pass the concrete type of the member using the turbofish syntax, //! which improves the compile errors when the member's type `T` doesn't implement //! the target trait. //! //! They improve the spans of error messages because compiler knows that it needs to //! point to the origin of the offending type (member's type T) from the turbofish //! syntax to where the type came from (original code written by the user). use core::fmt::Debug; #[inline(always)] pub fn clone_member(member: &Option) -> Option { member.clone() } #[inline(always)] pub fn as_dyn_debug(member: &T) -> &dyn Debug { member } #[inline(always)] pub fn copy_member(member: &Option) -> Option { *member } bon-3.7.1/src/__/cfg_eval.rs000064400000000000000000000115771046102023000137050ustar 00000000000000/// This is all a big embarrassing workaround, please don't oversee 😳😳😳. /// /// Anyway, if you are curious what the hell is going on here, then here is /// an explanation 😸. So... where to start 🤔. Ah! The problem! /// /// ## The problem /// /// Proc macro attributes (like `#[builder]`) see all the `#[cfg(...)]` and `#[cfg_attr(...)]` /// attributes unexpanded. For example, if you write smth like this: /// /// ``` /// #[bon::builder] /// fn func( /// #[cfg(windows)] /// windows_only_param: u32, /// ) {} /// /// ``` /// /// then the `#[builder]` macro will see the full `#[cfg(...)]` attribute with /// the `windows_only_param` it is attached to verbatim. The `#[cfg(...)]` isn't /// removed by the time the `#[builder]`'s macro expansion is invoked. /// /// It is a problem because the `#[builder]` macro needs to know the exact list /// of members it has to generate setters for. It doesn't know whether /// the `windows` predicate evaluates to `true` or `false`, especially if this was /// a more complex predicate. So it can't decide whether to generate a setter for /// the `windows_only_param` or not. /// /// ## The solution /// /// This macro allows us to evaluate the `cfg` predicates by using a variation of /// [the trick] shared by @recatek. /// /// When the `#[builder]` macro finds any usage of `#[cfg(...)]` or `#[cfg_attr(...)]` /// it generates a call to this macro with all `cfg` predicates collected from the /// item it was placed on. The `#[builder]` macro deduplicates and sorts the `cfg` /// predicates and passes them as `$pred` to this macro. /// /// This macro then dispatches to `__eval_cfg_callback_true` or `__eval_cfg_callback_false` /// by defining a conditional `use ...` statement for each predicate and collects the /// results of the evaluation in the `$results` list. /// /// For the last call to this macro (when no more `$pred` are left) the macro calls back /// to the proc macro attribute that called it with the results of the evaluation and /// the original parameters and the item which are passed through via the `$rest` macro variable. /// /// [the trick]: https://users.rust-lang.org/t/supporting-or-evaluating-cfg-in-proc-macro-parameters/93240/2 #[macro_export] #[doc(hidden)] macro_rules! __eval_cfg_callback { ( { $($results:tt)* } ( $pred_id:ident: $($pred:tt)* ) $($rest:tt)* ) => { // The `pred_id` is required to be a unique identifier for the current // predicate evaluation so that we can use it in a `use` statement to define // a new unique name for the macro to call. #[cfg($($pred)*)] #[doc(hidden)] #[allow(deprecated)] use $crate::__eval_cfg_callback_true as $pred_id; #[cfg(not($($pred)*))] #[doc(hidden)] #[allow(deprecated)] use $crate::__eval_cfg_callback_false as $pred_id; // The trick here is that `$pred_id` now resolves either to // `__eval_cfg_callback_true` or `__eval_cfg_callback_false` // depending on the evaluation of the cfg predicate, so by // invoking it as a macro, that macro internally pushes either // `true` or `false` to the `$results` list. $pred_id! { { $($results)* } $($rest)* } }; // The terminal case for the recursion when there are no more predicates left. // We have collected all the results of the cfg evaluations and now we can // delegate them to the proc macro attribute that called this macro. ( // The results of the cfg evaluation { $($results:tt)* } // The proc macro attribute to invoke with the results $final_macro:path, // The number of times this macro was called recursively from the proc macro $recursion_counter:literal, // Parameters to pass to the proc macro attribute after the cfg results ( $($macro_params:tt)* ) // The item to attach the proc macro attribute to $($item:tt)* ) => { // The special `__cfgs(...)` prefix is parsed by the proc macro attribute // to get the results of the cfg evaluations. #[$final_macro(__cfgs($recursion_counter, $($results)*) $($macro_params)*)] $($item)* }; } /// The `cfg` predicate evaluated to `true`, now push that information into /// the `$results` list. #[macro_export] #[doc(hidden)] macro_rules! __eval_cfg_callback_true { ( { $($results:tt)* } $($tt:tt)* ) => { $crate::__eval_cfg_callback! { { $($results)* true, } $($tt)* } }; } /// The `cfg` predicate evaluated to `false`, now push that information into /// the `$results` list. #[macro_export] #[doc(hidden)] macro_rules! __eval_cfg_callback_false { ( { $($results:tt)* } $($tt:tt)* ) => { $crate::__eval_cfg_callback! { { $($results)* false, } $($tt)* } }; } bon-3.7.1/src/__/ide.rs000064400000000000000000000125531046102023000126730ustar 00000000000000#![allow( non_upper_case_globals, missing_debug_implementations, clippy::wildcard_imports )] /// Completions for the top-level `builder` attribute. pub mod builder_top_level { use super::*; /// See the docs at pub const builder_type: Option = None; pub mod builder_type { use super::*; /// See the docs at pub const name: Identifier = Identifier; /// See the docs at pub const vis: VisibilityString = VisibilityString; /// See the docs at pub const doc: DocComments = DocComments; } /// See the docs at pub const finish_fn: Option = None; /// See the docs at pub mod finish_fn { use super::*; /// See the docs at pub const name: Identifier = Identifier; /// See the docs at pub const vis: VisibilityString = VisibilityString; /// See the docs at pub const doc: DocComments = DocComments; } /// See the docs at pub const start_fn: Option = None; /// See the docs at pub mod start_fn { use super::*; /// See the docs at pub const name: Identifier = Identifier; /// See the docs at pub const vis: VisibilityString = VisibilityString; /// See the docs at pub const doc: DocComments = DocComments; } /// See the docs at pub const state_mod: Option = None; /// See the docs at pub mod state_mod { use super::*; /// See the docs at pub const name: Identifier = Identifier; /// See the docs at pub const vis: VisibilityString = VisibilityString; /// See the docs at pub const doc: DocComments = DocComments; } /// See the docs at pub mod on { use super::*; /// See the docs at pub const into: Flag = Flag; /// See the docs at pub const required: Flag = Flag; /// See the docs at pub const overwritable: Flag = Flag; } /// See the docs at pub mod derive { /// See the docs at pub use core::fmt::Debug; /// See the docs at pub use core::clone::Clone; /// See the docs at pub use core::convert::Into; /// See the docs at #[rustversion::since(1.64)] pub use core::future::IntoFuture; } /// The real name of this parameter is `crate` (without the underscore). /// It's hinted with an underscore due to the limitations of the current /// completions limitation. This will be fixed in the future. /// /// See the docs at pub const crate_: Option = None; } /// Visibility inside of a string literal. Empty string means private visibility. /// /// Examples: /// /// - `""` - the symbol is private (accessible only within the same module) /// - `"pub"` - the symbol is accessible outside of the crate /// - `"pub(crate)"` - the symbol is accessible anywhere inside of the crate, but not outside of it /// /// [Rust reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html) pub struct VisibilityString; /// [Rust reference](https://doc.rust-lang.org/reference/identifiers.html) pub struct Identifier; /// The presence of this attribute enables the behavior. The attribute has no value. pub struct Flag; /// Documentation comments using the syntax `/// doc comment here`. /// /// [Rust reference](https://doc.rust-lang.org/reference/comments.html#doc-comments) pub struct DocComments; /// Simple path that is valid in a `use` statement. Example: `foo::bar::baz`. /// /// [Rust reference](https://doc.rust-lang.org/reference/paths.html?highlight=path#simple-paths) pub struct Path; bon-3.7.1/src/__/mod.rs000064400000000000000000000026131046102023000127050ustar 00000000000000#![allow( // We place `#[inline(always)]` only on very small methods where we'd event want // a guarantee of them being inlined. clippy::inline_always, // Marking every potential function as `const` is a bit too much. // Especially, this doesn't play well with our MSRV. Trait bounds // aren't allowed on const functions in older Rust versions. clippy::missing_const_for_fn, )] /// Used for providing better IDE hints (completions and syntax highlighting). pub mod ide; pub mod better_errors; mod cfg_eval; // This reexport is a private implementation detail and should not be used // directly! This reexport may change or be removed at any time between // patch releases. Use the export from your generated builder's state module // directly instead of using this reexport from `bon::__`. pub use crate::builder_state::{IsSet, IsUnset}; pub use bon_macros::__privatize; pub use rustversion; pub(crate) mod sealed { // The purpose of the `Sealed` trait **is** to be unnameable from outside the crate. #[allow(unnameable_types)] pub trait Sealed: Sized {} impl Sealed for super::Unset {} impl Sealed for super::Set {} } pub(crate) use sealed::Sealed; /// Used to implement the `alloc` feature. #[cfg(feature = "alloc")] pub extern crate alloc; #[derive(Debug)] pub struct Unset(Name); #[derive(Debug)] pub struct Set(Name); bon-3.7.1/src/builder_state.rs000064400000000000000000000027231046102023000144010ustar 00000000000000//! The items here are intentionally defined in a private module not inside of the //! [`crate::__`] module. This is because that module is marked with `#[deprecated]` //! which makes all items defined in that module also deprecated. //! //! This is not the desired behavior for the items defined here. They are not deprecated, //! and they are expected to be exposed to the users. However, the users must not reference //! them through the `bon` crate. Instead, they should use the re-exports from the state //! module generated for the builder. use crate::__::{Sealed, Set, Unset}; /// Marker trait that indicates that the member is set, i.e. at least /// one of its setters was called. #[rustversion::attr( since(1.78.0), diagnostic::on_unimplemented( message = "the member `{Self}` was not set, but this method requires it to be set", label = "the member `{Self}` was not set, but this method requires it to be set" ) )] pub trait IsSet: Sealed {} /// Marker trait that indicates that the member is unset, i.e. none /// of its setters was called. #[rustversion::attr( since(1.78.0), diagnostic::on_unimplemented( message = "the member `{Self}` was already set, but this method requires it to be unset", label = "the member `{Self}` was already set, but this method requires it to be unset" ) )] pub trait IsUnset: Sealed {} #[doc(hidden)] impl IsSet for Set {} #[doc(hidden)] impl IsUnset for Unset {} bon-3.7.1/src/collections.rs000064400000000000000000000117161046102023000140730ustar 00000000000000/// Same as [`std::vec!`] but converts each element with [`Into`]. /// /// **WARNING:** it's not recommended to import this macro into scope. Reference it /// using the full path (`bon::vec![]`) to avoid confusion with the [`std::vec!`] macro. /// /// A good example of the use case for this macro is when you want to create a /// [`Vec`] where part of the items are hard-coded string literals of type /// `&str` and the other part is made of dynamic [`String`] values. /// /// ``` /// fn convert_media(input_extension: &str, output_extension: &str) -> std::io::Result<()> { /// let ffmpeg_args: Vec = bon::vec![ /// "-i", /// format!("input.{input_extension}"), /// "-y", /// format!("output.{output_extension}"), /// ]; /// /// std::process::Command::new("ffmpeg").args(ffmpeg_args).output()?; /// /// Ok(()) /// } /// ``` /// /// This macro doesn't support `vec![expr; N]` syntax, since it's simpler to /// just write `vec![expr.into(); N]` using [`std::vec!`] instead. #[macro_export] #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] #[allow(edition_2024_expr_fragment_specifier)] macro_rules! vec { () => ($crate::__::alloc::vec::Vec::new()); ($($item:expr),+ $(,)?) => ($crate::__::alloc::vec![$(::core::convert::Into::into($item)),+ ]); } /// Creates a fixed-size array literal with each element converted with [`Into`]. /// /// You'll probably need a hint for the target type of items in the array if the /// compiler can't infer it from its usage. /// /// This is similar in spirit to the [`bon::vec!`] macro, but it's for arrays. /// See [`bon::vec!`] docs for details. /// /// Same example as in [`bon::vec!`], but using this macro. It works with array /// as well because [`Command::args`] accepts any value that implements [`IntoIterator`]: /// /// ``` /// fn convert_media(input_extension: &str, output_extension: &str) -> std::io::Result<()> { /// let ffmpeg_args: [String; 4] = bon::arr![ /// "-i", /// format!("input.{input_extension}"), /// "-y", /// format!("output.{output_extension}"), /// ]; /// /// std::process::Command::new("ffmpeg").args(ffmpeg_args).output()?; /// /// Ok(()) /// } /// ``` /// /// This macro doesn't support `[expr; N]` syntax, since it's simpler to /// just write `[expr.into(); N]` instead. /// /// [`Command::args`]: std::process::Command::args /// [`bon::vec!`]: crate::vec #[macro_export] #[allow(edition_2024_expr_fragment_specifier)] macro_rules! arr { () => ([]); ($($item:expr),+ $(,)?) => ([$(::core::convert::Into::into($item)),+]); } #[cfg(test)] mod tests { // It's okay to use indexing in tests for conciseness. #![allow(clippy::indexing_slicing)] #[cfg(feature = "alloc")] use crate::__::alloc::{string::String, vec::Vec}; use core::num::NonZeroU8; #[cfg(feature = "alloc")] #[test] fn arr_of_strings() { let actual: [String; 3] = crate::arr!["foo", "bar", "baz"]; assert_eq!(actual, ["foo", "bar", "baz"]); let actual: [String; 0] = crate::arr![]; assert!(actual.is_empty()); } #[test] fn arr_of_numbers() { let actual: [u8; 2] = crate::arr![NonZeroU8::new(1).unwrap(), NonZeroU8::new(2).unwrap()]; assert_eq!(actual, [1, 2]); let actual: [u8; 0] = crate::arr![]; assert!(actual.is_empty()); } #[cfg(feature = "alloc")] #[test] fn vec_smoke() { let actual: Vec = crate::vec!["foo", "bar", "baz"]; assert_eq!(actual, ["foo", "bar", "baz"]); let actual: Vec = crate::vec![]; assert!(actual.is_empty()); } #[cfg(feature = "std")] #[test] fn map_smoke() { use std::collections::{BTreeMap, HashMap}; let hash_strings: HashMap = crate::map! { "Hello": "World", "Goodbye": "Mars", }; assert_eq!(hash_strings["Hello"], "World"); assert_eq!(hash_strings["Goodbye"], "Mars"); let tree_strings: BTreeMap = crate::map! { "Hello": "World", "Goodbye": "Mars", }; assert_eq!(tree_strings["Hello"], "World"); assert_eq!(tree_strings["Goodbye"], "Mars"); } #[cfg(feature = "std")] #[test] fn set_smoke() { use std::collections::BTreeSet; use std::collections::HashSet; let hash_strings: HashSet = crate::set!["Hello", "World", "Goodbye", "Mars"]; assert!(hash_strings.contains("Hello")); assert!(hash_strings.contains("World")); assert!(hash_strings.contains("Goodbye")); assert!(hash_strings.contains("Mars")); let tree_strings: BTreeSet = crate::set!["Hello", "World", "Goodbye", "Mars"]; assert!(tree_strings.contains("Hello")); assert!(tree_strings.contains("World")); assert!(tree_strings.contains("Goodbye")); assert!(tree_strings.contains("Mars")); } } bon-3.7.1/src/lib.rs000064400000000000000000000023071046102023000123170ustar 00000000000000#![doc( html_logo_url = "https://bon-rs.com/bon-logo-thumb.png", html_favicon_url = "https://bon-rs.com/bon-logo-medium.png" )] #![doc = include_str!("../README.md")] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] // We mark all items from the `private` module as deprecated to signal that they are // implementation details and should not be used directly. Unfortunately, this triggers // the deprecation warnings within this crate itself everywhere we use them, so we just // suppress this lint for the entire crate. #![allow(deprecated)] // Rexport all macros from the proc-macro crate. pub use bon_macros::{bon, builder, map, set, Builder}; /// Small utility declarative macros for creating colletions with [`Into`] conversions. mod collections; #[doc(hidden)] #[deprecated = "the items from the `bon::__` module are an implementation detail; \ they should not be used directly; if you found a need for this, then you are probably \ doing something wrong; feel free to open an issue/discussion in our GitHub repository \ (https://github.com/elastio/bon) or ask for help in our Discord server \ (https://bon-rs.com/discord)"] pub mod __; mod builder_state; bon-3.7.1/tests/integration/builder/attr_bon.rs000064400000000000000000000146301046102023000177070ustar 00000000000000use crate::prelude::*; use core::pin::Pin; #[test] fn new_method_special_case() { struct Sut; #[bon] impl Sut { #[builder] fn new() {} } let _: SutBuilder = Sut::builder(); let builder: SutBuilder = Sut::builder(); builder.build(); } #[test] fn builder_method_special_case() { struct Sut; #[bon] impl Sut { #[builder] fn builder() {} } let _: SutBuilder = Sut::builder(); let builder: SutBuilder = Sut::builder(); builder.build(); } #[test] fn builder_start_fn_is_not_special_case() { struct Sut; #[bon] impl Sut { #[builder(start_fn = builder)] fn some_other_name() {} } let _: SutSomeOtherNameBuilder = Sut::builder(); let builder: SutSomeOtherNameBuilder = Sut::builder(); builder.call(); Sut::some_other_name(); } #[test] fn receiver_variations() { #[derive(Clone)] struct Sut { field: u32, } #[bon] impl Sut { #[builder] #[allow(clippy::use_self)] fn self_as_ref_sut(self: &Sut) -> u32 { self.field } #[builder] fn mut_self(mut self) -> Self { self.field += 1; self } #[builder] fn ref_mut_self(&mut self) { self.field += 1; } #[builder] fn mut_self_ref_self(#[allow(clippy::needless_arbitrary_self_type)] mut self: &Self) { #[allow(clippy::self_assignment, unused_assignments)] { self = &Self { field: 43 }; } } #[builder] fn mut_self_as_ref_mut_self( #[allow(clippy::needless_arbitrary_self_type)] mut self: &mut Self, ) { self.field = 45; #[allow(clippy::self_assignment, unused_assignments, dead_code)] { self = self; } } #[builder] fn self_as_pin_mut_self(self: Pin<&mut Self>) { let _ = self; } #[builder] fn mut_self_as_pin_mut_self(mut self: Pin<&mut Self>) { #[allow(clippy::self_assignment, unused_assignments)] { self = self; } } } let mut sut = Sut { field: 42 }; Sut::self_as_ref_sut(&sut).call(); sut.self_as_ref_sut().call(); Sut::mut_self(sut.clone()).call(); sut.clone().mut_self().call(); Sut::mut_self_ref_self(&sut).call(); sut.mut_self_ref_self().call(); Sut::ref_mut_self(&mut sut).call(); sut.ref_mut_self().call(); assert_eq!(sut.field, 44); Sut::mut_self_as_ref_mut_self(&mut sut).call(); sut.mut_self_as_ref_mut_self().call(); assert_eq!(sut.field, 45); Sut::self_as_pin_mut_self(Pin::new(&mut sut)).call(); Pin::new(&mut sut).self_as_pin_mut_self().call(); } #[cfg(feature = "alloc")] #[test] fn receiver_variations_alloc() { use core::pin::Pin; #[derive(Clone)] struct Sut { field: u32, } #[bon] impl Sut { #[builder] fn mut_self_as_box(mut self: Box) { self.field += 1; drop(self); } #[builder] fn self_as_box(self: Box) { drop(self); } #[builder] fn self_as_rc(self: Rc) { drop(self); } #[builder] fn self_as_arc(self: Arc) { drop(self); } #[builder] fn self_as_pin_box_self(self: Pin>) { drop(self); } #[builder] #[allow(clippy::use_self)] fn self_as_pin_box_sut(self: Pin>) { drop(self); } } let sut = Sut { field: 42 }; Sut::mut_self_as_box(Box::new(sut.clone())).call(); Box::new(sut.clone()).mut_self_as_box().call(); Sut::self_as_box(Box::new(sut.clone())).call(); Box::new(sut.clone()).self_as_box().call(); Sut::self_as_rc(Rc::new(sut.clone())).call(); Rc::new(sut.clone()).self_as_rc().call(); Sut::self_as_arc(Arc::new(sut.clone())).call(); Arc::new(sut.clone()).self_as_arc().call(); Sut::self_as_pin_box_self(Pin::new(Box::new(sut.clone()))).call(); Pin::new(Box::new(sut.clone())) .self_as_pin_box_self() .call(); Sut::self_as_pin_box_sut(Pin::new(Box::new(sut.clone()))).call(); Pin::new(Box::new(sut)).self_as_pin_box_sut().call(); } #[test] fn constructor() { struct Counter { val: u32, } #[bon] impl Counter { #[builder(start_fn = builder)] fn new(initial: Option) -> Self { Self { val: initial.unwrap_or_default(), } } } let counter = Counter::builder().initial(3).build(); assert_eq!(counter.val, 3); let counter = Counter::new(Some(32)); assert_eq!(counter.val, 32); } #[test] fn receiver() { #[derive(Clone)] struct Counter { val: u32, } #[bon] impl Counter { /// Docs on the method. /// Multiline #[builder] fn increment(&self, #[builder(default)] disabled: bool) -> Self { if disabled { return self.clone(); } Self { val: self.val + 1 } } } let counter = Counter { val: 0 }; let counter = counter.increment().call(); assert_eq!(counter.val, 1); } #[test] fn receiver_with_lifetimes() { struct Sut<'a, 'b> { a: &'a str, b: &'b str, } #[bon] impl Sut<'_, '_> { #[builder] fn method(&self, c: &str) -> usize { let Self { a, b } = self; a.len() + b.len() + c.len() } } let actual = Sut { a: "a", b: "b" }.method().c("c").call(); assert_eq!(actual, 3); } #[test] fn self_in_a_bunch_of_places() { struct Sut; #[bon] impl Sut where Self: Sized + 'static, { #[builder] fn method(&self, me: Option) -> impl Iterator where Self: Sized, { let _ = self; me.into_iter() } } assert_eq!(Sut.method().me(Sut).call().count(), 1); } #[test] fn impl_block_ty_contains_a_reference() { struct Sut(T); #[bon] impl Sut<&'_ T> { #[builder] fn get(&self) -> &T { self.0 } } assert_eq!(Sut(&42).get().call(), &42); } bon-3.7.1/tests/integration/builder/attr_builder.rs000064400000000000000000000013751046102023000205610ustar 00000000000000mod multiple_attributes { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] #[builder(start_fn = start)] #[builder(finish_fn = finish)] struct Sut {} let _ = Sut::start().finish(); } #[test] fn test_function() { #[builder] #[builder] #[builder(start_fn = start)] #[builder(finish_fn = finish)] fn sut() {} start().finish(); } #[test] fn test_method() { struct Sut {} #[bon] impl Sut { #[builder] #[builder] #[builder(start_fn = start)] #[builder(finish_fn = finish)] fn method() {} } Sut::start().finish(); } } bon-3.7.1/tests/integration/builder/attr_const.rs000064400000000000000000000144211046102023000202550ustar 00000000000000#[rustversion::since(1.61.0)] mod msrv_1_61 { mod smoke { use crate::prelude::*; #[test] const fn test_struct() { #[derive(Builder)] #[builder(const)] struct Sut { #[builder(start_fn)] x1: u32, // There was a bug in `#[builder(field)]` `const` support, that // this is testing for: https://github.com/elastio/bon/issues/290 #[builder(field = 11)] x2: u32, #[builder(finish_fn)] x3: u32, x4: u32, x5: Option, #[builder(default = x1 + 99)] x6: u32, #[builder(with = |a: u32, b: u32| a + b)] x7: u32, #[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })] x8: Option, #[builder(skip = 10)] x9: u32, // // This doesn't work because Rust complains about this in setters that // consume `self` and return a new instance of the builder: // ``` // destructor of `builder::attr_const::test_struct::SutBuilder` // cannot be evaluated at compile-time // ``` // x7: Vec, // x8: String, } const ACTUAL: Sut = Sut::builder(1).x4(2).x5(3).x7(4, 5).build(6); #[allow(clippy::assertions_on_constants)] { assert!(ACTUAL.x1 == 1); assert!(ACTUAL.x2 == 11); assert!(ACTUAL.x3 == 6); assert!(ACTUAL.x4 == 2); assert!(matches!(ACTUAL.x5, Some(3))); assert!(ACTUAL.x6 == 100); assert!(ACTUAL.x7 == 9); assert!(ACTUAL.x8.is_none()); assert!(ACTUAL.x9 == 10); } } #[rustversion::since(1.83.0)] #[test] const fn test_struct_msrv_1_83() { #[derive(Builder)] #[builder(const)] struct Sut { #[builder(start_fn)] #[allow(dead_code)] x1: u32, #[builder(field = 11)] #[allow(dead_code)] x2: u32, } impl SutBuilder { const fn inc(&mut self) { self.x1 += 1; self.x2 += 1; } } let mut builder = Sut::builder(1); builder.inc(); builder.inc(); assert!(builder.x1 == 3); assert!(builder.x2 == 13); } #[test] const fn test_function() { type Output = (u32, u32, u32, u32, Option, u32, u32, Option); #[builder(const)] const fn sut( #[builder(start_fn)] x1: u32, #[builder(field = 10)] x2: u32, #[builder(finish_fn)] x3: u32, x4: u32, x5: Option, #[builder(default = x1 + 99)] x6: u32, #[builder(with = |a: u32, b: u32| a + b)] x7: u32, #[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })] x8: Option, ) -> Output { (x1, x2, x3, x4, x5, x6, x7, x8) } const ACTUAL: Output = sut(1).x4(2).x5(3).x7(4, 5).call(6); #[allow(clippy::assertions_on_constants)] { assert!(ACTUAL.0 == 1); assert!(ACTUAL.1 == 10); assert!(ACTUAL.2 == 6); assert!(ACTUAL.3 == 2); assert!(matches!(ACTUAL.4, Some(3))); assert!(ACTUAL.5 == 100); assert!(ACTUAL.6 == 9); assert!(ACTUAL.7.is_none()); } } #[test] const fn test_method() { type Output = (u32, u32, u32, u32, Option, u32, u32, Option); struct Sut; #[bon] impl Sut { #[builder(const)] const fn sut( #[builder(start_fn)] x1: u32, #[builder(field = 10)] x2: u32, #[builder(finish_fn)] x3: u32, x4: u32, x5: Option, #[builder(default = x1 + 99)] x6: u32, #[builder(with = |a: u32, b: u32| a + b)] x7: u32, #[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })] x8: Option< u32, >, ) -> Output { (x1, x2, x3, x4, x5, x6, x7, x8) } } const ACTUAL: Output = Sut::sut(1).x4(2).x5(3).x7(4, 5).call(6); #[allow(clippy::assertions_on_constants)] { assert!(ACTUAL.0 == 1); assert!(ACTUAL.1 == 10); assert!(ACTUAL.2 == 6); assert!(ACTUAL.3 == 2); assert!(matches!(ACTUAL.4, Some(3))); assert!(ACTUAL.5 == 100); assert!(ACTUAL.6 == 9); assert!(ACTUAL.7.is_none()); } } } // Tests for the following bug: https://github.com/elastio/bon/issues/287 mod visibility { use crate::prelude::*; #[test] const fn test_struct() { #[derive(Builder)] #[builder(const)] #[allow(unreachable_pub)] pub struct Sut { x1: u32, } const ACTUAL: Sut = Sut::builder().x1(1).build(); #[allow(clippy::assertions_on_constants)] { assert!(ACTUAL.x1 == 1); } } #[test] const fn test_function() { #[builder(const)] pub const fn sut(#[builder(getter)] _x: u32) {} sut().x(1).call(); } #[test] const fn test_method() { struct Sut; #[bon] impl Sut { #[builder(const)] pub const fn sut(#[builder(getter)] _x: u32) {} } Sut::sut().x(1).call(); } } } bon-3.7.1/tests/integration/builder/attr_crate.rs000064400000000000000000000047701046102023000202330ustar 00000000000000use crate::prelude::*; use bon as lyra; #[test] fn test_struct() { { #[derive(Builder)] #[builder( crate = crate::builder::attr_crate::lyra, derive(Debug, Clone) )] struct Sut { _a: u32, _b: u32, } let _ = Sut::builder().a(1).b(2).build(); } { macro_rules! in_macro { () => { #[derive(Builder)] #[builder(crate = $crate::builder::attr_crate::lyra, derive(Debug, Clone))] struct Sut { _a: u32, _b: u32, } }; } in_macro!(); let _ = Sut::builder().a(1).b(2).build(); } { #[derive(Builder)] #[builder( crate = ::bon, derive(Debug, Clone) )] struct Sut { _a: u32, _b: u32, } let _ = Sut::builder().a(1).b(2).build(); } } #[test] fn test_function() { { #[builder( crate = crate::builder::attr_crate::lyra, derive(Debug, Clone) )] fn sut(_a: u32, _b: u32) {} sut().a(1).b(2).call(); } { macro_rules! in_macro { () => { #[builder(crate = $crate::builder::attr_crate::lyra, derive(Debug, Clone))] fn sut(_a: u32, _b: u32) {} }; } in_macro!(); sut().a(1).b(2).call(); } { #[builder( crate = ::bon, derive(Debug, Clone) )] fn sut(_a: u32, _b: u32) {} sut().a(1).b(2).call(); } } #[test] fn test_method() { { struct Sut; #[bon(crate = crate::builder::attr_crate::lyra)] impl Sut { #[builder(derive(Debug, Clone))] fn sut(_a: u32, _b: u32) {} } Sut::sut().a(1).b(2).call(); } { macro_rules! in_macro { () => { struct Sut; #[bon(crate = $crate::builder::attr_crate::lyra)] impl Sut { #[builder(derive(Debug, Clone))] fn sut(_a: u32, _b: u32) {} } }; } in_macro!(); Sut::sut().a(1).b(2).call(); } { struct Sut; #[bon(crate = ::bon)] impl Sut { #[builder(derive(Debug, Clone))] fn sut(_a: u32, _b: u32) {} } Sut::sut().a(1).b(2).call(); } } bon-3.7.1/tests/integration/builder/attr_default.rs000064400000000000000000000223621046102023000205560ustar 00000000000000use crate::prelude::*; use core::fmt; #[cfg(feature = "alloc")] #[test] fn fn_alloc() { #[builder] fn sut( #[builder(default = "default".to_owned())] arg1: String, #[builder(default = vec![42])] arg2: Vec, #[builder(default = "foo", into)] arg3: String, ) -> impl fmt::Debug { (arg1, arg2, arg3) } assert_debug_eq(sut().call(), expect![[r#"("default", [42], "foo")"#]]); assert_debug_eq( sut().arg1("arg1".to_owned()).call(), expect![[r#"("arg1", [42], "foo")"#]], ); assert_debug_eq( sut().maybe_arg1(None).call(), expect![[r#"("default", [42], "foo")"#]], ); assert_debug_eq( sut().maybe_arg3(None::).call(), expect![[r#"("default", [42], "foo")"#]], ); } #[cfg(feature = "alloc")] #[test] fn struct_alloc() { use bon::bon; use expect_test::expect; #[derive(Debug, Builder)] struct Sut { #[builder(default = "default".to_owned())] arg1: String, #[builder(default = vec![42])] arg2: Vec, #[builder(default = "foo", into)] arg3: String, } assert_debug_eq( Sut::builder().build(), expect![[r#"Sut { arg1: "default", arg2: [42], arg3: "foo" }"#]], ); assert_debug_eq( Sut::builder().arg1("arg1".to_owned()).build(), expect![[r#"Sut { arg1: "arg1", arg2: [42], arg3: "foo" }"#]], ); assert_debug_eq( Sut::builder().maybe_arg1(None::).build(), expect![[r#"Sut { arg1: "default", arg2: [42], arg3: "foo" }"#]], ); #[bon] #[allow(clippy::items_after_statements)] impl Sut { #[builder] fn assoc( self, #[builder(default = "default".to_owned())] arg1: String, #[builder(default = vec![43])] arg2: Vec, #[builder(default = "foo", into)] arg3: String, ) -> Self { Self { arg1: format!("{}+{arg1}", self.arg1), arg2: self.arg2.into_iter().chain(arg2).collect(), arg3: format!("{}+{arg3}", self.arg3), } } } let sut = || Sut::builder().build(); assert_debug_eq( sut().assoc().call(), expect![[r#" Sut { arg1: "default+default", arg2: [ 42, 43, ], arg3: "foo+foo", }"#]], ); assert_debug_eq( sut().assoc().arg1("arg1".to_owned()).call(), expect![[r#" Sut { arg1: "default+arg1", arg2: [ 42, 43, ], arg3: "foo+foo", }"#]], ); assert_debug_eq( sut().assoc().maybe_arg1(None).call(), expect![[r#" Sut { arg1: "default+default", arg2: [ 42, 43, ], arg3: "foo+foo", }"#]], ); assert_debug_eq( sut().assoc().maybe_arg3(None::).call(), expect![[r#" Sut { arg1: "default+default", arg2: [ 42, 43, ], arg3: "foo+foo", }"#]], ); } #[test] fn fn_no_std() { #[builder] fn sut(#[builder(default)] arg1: u32, #[builder(default = 42)] arg2: u32) -> impl fmt::Debug { (arg1, arg2) } assert_debug_eq(sut().call(), expect!["(0, 42)"]); assert_debug_eq(sut().arg1(12).call(), expect!["(12, 42)"]); assert_debug_eq(sut().maybe_arg1(None::).call(), expect!["(0, 42)"]); } #[test] fn struct_no_std() { use bon::bon; #[derive(Debug, Builder)] struct Sut { #[builder(default)] arg1: u32, #[builder(default = 42)] arg2: u32, } assert_debug_eq(Sut::builder().build(), expect!["Sut { arg1: 0, arg2: 42 }"]); assert_debug_eq( Sut::builder().arg1(12).build(), expect!["Sut { arg1: 12, arg2: 42 }"], ); assert_debug_eq( Sut::builder().maybe_arg1(None::).build(), expect!["Sut { arg1: 0, arg2: 42 }"], ); #[bon] #[allow(clippy::items_after_statements)] impl Sut { #[builder] fn assoc(self, #[builder(default)] arg1: u32, #[builder(default = 43)] arg2: u32) -> Self { Self { arg1: self.arg1 + arg1, arg2: self.arg2 + arg2, } } } let sut = || Sut::builder().build(); assert_debug_eq(sut().assoc().call(), expect!["Sut { arg1: 0, arg2: 85 }"]); assert_debug_eq( sut().assoc().arg1(12).call(), expect!["Sut { arg1: 12, arg2: 85 }"], ); assert_debug_eq( sut().assoc().maybe_arg1(None::).call(), expect!["Sut { arg1: 0, arg2: 85 }"], ); } #[test] fn fn_generic_default() { #[builder] fn sut( #[builder(default)] arg1: impl Clone + Default, #[builder(default = <_>::default())] arg2: impl Clone + Default, ) { drop(arg1); drop(arg2); } sut::<(), ()>().call(); } mod interaction_with_positional_members { use crate::prelude::*; use core::fmt; #[test] fn test_struct() { #[derive(Builder, Debug)] #[allow(dead_code)] struct Sut { #[builder(start_fn)] starter_1: u32, #[builder(start_fn)] starter_2: u32, #[builder(finish_fn)] finisher_1: u32, #[builder(finish_fn)] finisher_2: u32, #[builder(default = [starter_1, starter_2, finisher_1, finisher_2])] named_1: [u32; 4], #[builder(default = (32, named_1))] named_2: (u32, [u32; 4]), } assert_debug_eq( Sut::builder(1, 2).build(3, 4), expect![[r#" Sut { starter_1: 1, starter_2: 2, finisher_1: 3, finisher_2: 4, named_1: [ 1, 2, 3, 4, ], named_2: ( 32, [ 1, 2, 3, 4, ], ), }"#]], ); assert_debug_eq( Sut::builder(1, 2).named_1([5, 6, 7, 8]).build(3, 4), expect![[r#" Sut { starter_1: 1, starter_2: 2, finisher_1: 3, finisher_2: 4, named_1: [ 5, 6, 7, 8, ], named_2: ( 32, [ 5, 6, 7, 8, ], ), }"#]], ); } #[test] fn test_function() { #[builder] #[allow(clippy::type_complexity)] fn sut( #[builder(start_fn)] starter_1: u32, #[builder(start_fn)] starter_2: u32, #[builder(finish_fn)] finisher_1: u32, #[builder(finish_fn)] finisher_2: u32, #[builder(default = [starter_1, starter_2, finisher_1, finisher_2])] // named_1: [u32; 4], #[builder(default = (32, named_1))] named_2: (u32, [u32; 4]), ) -> impl fmt::Debug { ( starter_1, starter_2, finisher_1, finisher_2, named_1, named_2, ) } assert_debug_eq( sut(1, 2).call(3, 4), expect!["(1, 2, 3, 4, [1, 2, 3, 4], (32, [1, 2, 3, 4]))"], ); assert_debug_eq( sut(1, 2).named_1([5, 6, 7, 8]).call(3, 4), expect!["(1, 2, 3, 4, [5, 6, 7, 8], (32, [5, 6, 7, 8]))"], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] #[allow(clippy::type_complexity)] fn sut( #[builder(start_fn)] starter_1: u32, #[builder(start_fn)] starter_2: u32, #[builder(finish_fn)] finisher_1: u32, #[builder(finish_fn)] finisher_2: u32, #[builder(default = [starter_1, starter_2, finisher_1, finisher_2])] // named_1: [u32; 4], #[builder(default = (32, named_1))] named_2: (u32, [u32; 4]), ) -> impl fmt::Debug { ( starter_1, starter_2, finisher_1, finisher_2, named_1, named_2, ) } } assert_debug_eq( Sut::sut(1, 2).call(3, 4), expect!["(1, 2, 3, 4, [1, 2, 3, 4], (32, [1, 2, 3, 4]))"], ); assert_debug_eq( Sut::sut(1, 2).named_1([5, 6, 7, 8]).call(3, 4), expect!["(1, 2, 3, 4, [5, 6, 7, 8], (32, [5, 6, 7, 8]))"], ); } } bon-3.7.1/tests/integration/builder/attr_derive.rs000064400000000000000000000227131046102023000204100ustar 00000000000000// We intentionally exercise cloning from `#[builder(derive(Clone))]` here // to make sure that it works. #![allow(clippy::redundant_clone)] use crate::prelude::*; #[test] fn smoke_fn() { #[builder(derive(Clone, Debug, Into))] fn sut(_arg1: bool, _arg2: Option<()>, _arg3: Option<&str>, _arg4: Option) -> u32 { 99 } let actual = sut().arg1(true).arg3("value").maybe_arg4(None).clone(); assert_debug_eq( &actual, expect![[r#"SutBuilder { arg1: true, arg3: "value" }"#]], ); let actual: u32 = From::from(actual); assert_debug_eq(actual, expect!["99"]); } #[test] fn smoke_struct() { #[derive(Builder, Debug)] #[builder(derive(Clone, Debug, Into))] struct Sut<'a> { _arg1: bool, _arg2: Option<()>, _arg3: Option<&'a str>, _arg4: Option, } let actual = Sut::builder() .arg1(true) .arg3("value") .maybe_arg4(None) .clone(); assert_debug_eq( &actual, expect![[r#"SutBuilder { arg1: true, arg3: "value" }"#]], ); let actual: Sut<'_> = From::from(actual); assert_debug_eq( actual, expect![[r#" Sut { _arg1: true, _arg2: None, _arg3: Some( "value", ), _arg4: None, }"#]], ); } #[test] fn builder_with_receiver() { #[derive(Clone, Debug)] struct Sut { #[allow(dead_code)] name: &'static str, } #[bon] impl Sut { #[builder(derive(Clone, Debug, Into))] fn method(&self, other_name: &'static str, values: &[u8]) -> u32 { let _ = (self, other_name, values); 99 } } let actual = Sut { name: "Blackjack" } .method() .other_name("P21") .values(&[1, 2, 3]) .clone(); assert_debug_eq( &actual, expect![[r#" SutMethodBuilder { self_receiver: Sut { name: "Blackjack", }, other_name: "P21", values: [ 1, 2, 3, ], }"#]], ); let actual: u32 = From::from(actual); assert_debug_eq(actual, expect!["99"]); } #[test] fn skipped_members() { struct NoDebug; #[derive(Builder)] #[builder(derive(Debug, Clone, Into))] struct Sut { arg1: bool, #[builder(skip = NoDebug)] _arg2: NoDebug, } let actual = Sut::builder().arg1(true).clone(); assert_debug_eq(&actual, expect!["SutBuilder { arg1: true }"]); let actual: Sut = From::from(actual); assert!(actual.arg1); } #[test] fn empty_builder() { #[derive(Builder)] #[builder(derive(Clone, Debug, Into))] struct Sut {} #[allow(clippy::redundant_clone)] let actual = Sut::builder().clone(); assert_debug_eq(&actual, expect!["SutBuilder"]); let Sut {} = From::from(actual); } mod generics { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder, Debug)] #[builder(derive(Clone, Debug, Into))] struct Sut where T: Clone, { _arg1: T, } let actual = Sut::builder().arg1(42).clone(); assert_debug_eq(&actual, expect!["SutBuilder { arg1: 42 }"]); let actual: Sut<_> = From::from(actual); assert_debug_eq(actual, expect![[r#"Sut { _arg1: 42 }"#]]); } #[test] fn test_function() { #[builder(derive(Clone, Debug, Into))] fn sut(_arg1: T) -> u32 where T: Clone, { 99 } let actual = sut::().arg1(42).clone(); assert_debug_eq(&actual, expect!["SutBuilder { arg1: 42 }"]); let actual: u32 = From::from(actual); assert_debug_eq(actual, expect!["99"]); } #[test] fn test_method() { #[derive(Clone, Debug)] struct Sut(T); #[bon] impl Sut where T: Clone, { #[builder(derive(Clone, Debug, Into))] fn sut(_arg1: U) -> u32 { 99 } #[builder(derive(Clone, Debug, Into))] fn with_self(&self, _arg1: U) -> u32 { let _ = self; 99 } } let actual = Sut::<()>::sut::().arg1(42).clone(); assert_debug_eq(&actual, expect!["SutSutBuilder { arg1: 42 }"]); let actual: u32 = From::from(actual); assert_debug_eq(actual, expect!["99"]); let actual = Sut(true).with_self::().arg1(42).clone(); assert_debug_eq( &actual, expect!["SutWithSelfBuilder { self_receiver: Sut(true), arg1: 42 }"], ); let actual: u32 = From::from(actual); assert_debug_eq(actual, expect!["99"]); } } mod positional_members { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] #[builder(derive(Clone, Debug))] #[allow(dead_code)] struct Sut { #[builder(start_fn)] start_fn_arg: bool, #[builder(finish_fn)] finish_fn_arg: &'static str, named: u32, } let actual = Sut::builder(true); assert_debug_eq(actual.clone(), expect!["SutBuilder { start_fn_arg: true }"]); assert_debug_eq( actual.named(42).clone(), expect!["SutBuilder { start_fn_arg: true, named: 42 }"], ); } #[test] fn test_function() { #[builder(derive(Clone, Debug))] #[allow(unused_variables)] fn sut( #[builder(start_fn)] start_fn_arg: bool, #[builder(finish_fn)] finish_fn_arg: &'static str, named: u32, ) { } let actual = sut(true); assert_debug_eq(actual.clone(), expect!["SutBuilder { start_fn_arg: true }"]); assert_debug_eq( actual.named(42).clone(), expect!["SutBuilder { start_fn_arg: true, named: 42 }"], ); } #[test] fn test_method() { #[derive(Debug)] struct Sut; #[bon] #[allow(unused_variables)] impl Sut { #[builder(derive(Clone, Debug))] fn sut( #[builder(start_fn)] start_fn_arg: bool, #[builder(finish_fn)] finish_fn_arg: &'static str, named: u32, ) { } #[builder(derive(Clone, Debug))] fn with_self( &self, #[builder(start_fn)] start_fn_arg: bool, #[builder(finish_fn)] finish_fn_arg: &'static str, named: u32, ) { let _ = self; } } let actual = Sut::sut(true); assert_debug_eq( actual.clone(), expect!["SutSutBuilder { start_fn_arg: true }"], ); assert_debug_eq( actual.named(42).clone(), expect!["SutSutBuilder { start_fn_arg: true, named: 42 }"], ); let actual = Sut.with_self(true); assert_debug_eq( actual.clone(), expect![[r#" SutWithSelfBuilder { self_receiver: Sut, start_fn_arg: true, }"#]], ); assert_debug_eq( actual.named(42).clone(), expect![[r#" SutWithSelfBuilder { self_receiver: Sut, start_fn_arg: true, named: 42, }"#]], ); } } mod attr_bounds_empty { use crate::prelude::*; struct NoTraitImpls; #[test] fn test_struct() { #[derive(Builder)] #[builder(derive(Clone(bounds()), Debug))] struct Sut<'a, T> { _arg: &'a T, } let _ = Sut::builder().arg(&NoTraitImpls).clone(); } #[test] fn test_function() { #[builder(derive(Clone(bounds()), Debug))] fn sut(_arg: &T) {} let _ = sut::().arg(&NoTraitImpls).clone(); } #[test] fn test_method() { #[derive(Clone, Debug)] struct Sut; #[bon] impl Sut { #[builder(derive(Clone(bounds()), Debug))] fn sut(_arg: &T) {} } let _ = Sut::sut::().arg(&NoTraitImpls).clone(); } } mod attr_bounds_non_empty { use crate::prelude::*; struct NoTraitImpls; #[test] fn test_struct() { #[derive(Builder)] #[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))] struct Sut<'a, T> { _arg: &'a T, } let _ = Sut::builder().arg(&NoTraitImpls).clone(); } #[test] fn test_function() { #[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))] #[allow(clippy::needless_lifetimes, single_use_lifetimes)] fn sut<'a, T>(_arg: &'a T) {} let _ = sut::().arg(&NoTraitImpls).clone(); } #[test] fn test_method() { #[derive(Clone, Debug)] struct Sut; #[bon] impl Sut { #[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))] #[allow(clippy::needless_lifetimes, single_use_lifetimes)] fn sut<'a, T>(_arg: &'a T) {} } let _ = Sut::sut::().arg(&NoTraitImpls).clone(); } } bon-3.7.1/tests/integration/builder/attr_field.rs000064400000000000000000000102231046102023000202060ustar 00000000000000use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] #[builder(derive(Debug, Clone))] #[allow(dead_code)] struct Sut { #[builder(start_fn)] x1: u32, #[builder(start_fn, into)] x2: u32, #[builder(field)] x3: bool, #[builder(field = x1 + x2 + u32::from(x3))] x4: u32, #[builder(field = x4 * 2)] x5: u32, #[builder(field)] x6: Option, #[builder(field = core::any::type_name::())] x7: &'static str, x8: (), } // Make sure the builder is cloneable #[allow(clippy::redundant_clone)] let sut = Sut::<()>::builder(1, 2_u32).clone(); assert_debug_eq( &sut, expect![[r#" SutBuilder { x1: 1, x2: 2, x3: false, x4: 3, x5: 6, x6: None, x7: "()", }"#]], ); let _ = sut.x8(()).build(); } // This tests uses a turbofish with `impl Trait` #[rustversion::since(1.63.0)] #[test] fn test_function() { use core::fmt; #[builder(derive(Debug, Clone))] #[allow(unused_variables)] fn sut( #[builder(start_fn)] x1: u32, #[builder(start_fn, into)] x2: u32, #[builder(field)] x3: bool, #[builder(field = x1 + x2 + u32::from(x3))] x4: u32, #[builder(field = x4 * 2)] x5: u32, #[builder(field)] x6: Option, #[builder(field = core::any::type_name::())] x7: &'static str, x8: (), ) { } // Make sure the builder is cloneable #[allow(clippy::redundant_clone)] let sut = sut::<()>(1, 2_u32).clone(); assert_debug_eq( &sut, expect![[r#" SutBuilder { x1: 1, x2: 2, x3: false, x4: 3, x5: 6, x6: None, x7: "()", }"#]], ); sut.x8(()).call(); } // This tests uses a turbofish with `impl Trait` #[rustversion::since(1.63.0)] #[test] fn test_method() { use core::fmt; #[derive(Debug)] struct Sut; #[bon] impl Sut { #[builder(derive(Debug, Clone))] #[allow(unused_variables)] fn sut( #[builder(start_fn)] x1: u32, #[builder(start_fn, into)] x2: u32, #[builder(field)] x3: bool, #[builder(field = x1 + x2 + u32::from(x3))] x4: u32, #[builder(field = x4 * 2)] x5: u32, #[builder(field)] x6: Option, #[builder(field = core::any::type_name::())] x7: &'static str, x8: (), ) { } #[builder(derive(Debug, Clone))] #[allow(unused_variables)] fn with_self( &self, #[builder(start_fn)] x1: u32, #[builder(start_fn, into)] x2: u32, #[builder(field)] x3: bool, #[builder(field = x1 + x2 + u32::from(x3))] x4: u32, #[builder(field = x4 * 2)] x5: u32, #[builder(field)] x6: Option, #[builder(field = core::any::type_name::())] x7: &'static str, x8: (), ) { let _ = self; } } // Make sure the builder is cloneable #[allow(clippy::redundant_clone)] let sut = Sut::sut::<()>(1, 2_u32).clone(); assert_debug_eq( &sut, expect![[r#" SutSutBuilder { x1: 1, x2: 2, x3: false, x4: 3, x5: 6, x6: None, x7: "()", }"#]], ); sut.x8(()).call(); // Make sure the builder is cloneable #[allow(clippy::redundant_clone)] let sut = Sut.with_self::<()>(1, 2_u32).clone(); assert_debug_eq( &sut, expect![[r#" SutWithSelfBuilder { self_receiver: Sut, x1: 1, x2: 2, x3: false, x4: 3, x5: 6, x6: None, x7: "()", }"#]], ); sut.x8(()).call(); } bon-3.7.1/tests/integration/builder/attr_getter.rs000064400000000000000000000153741046102023000204310ustar 00000000000000use crate::prelude::*; #[test] fn by_ref() { #[derive(Debug, Builder)] struct Sut { #[builder(start_fn)] _x1: u32, #[builder(getter(name = x2_with_custom_name))] _x2: &'static str, #[builder(getter(vis = "pub(crate)", doc { /// Docs on the getter }))] _x3: u32, #[builder(into, getter(name = x4_override, vis = "pub(crate)", doc { /// Docs on getter }))] _x4: &'static str, _no_getter: u32, #[builder(getter)] _generic_option: Option, _x5: (), #[builder(getter, default)] _x6: u32, } let builder = Sut::builder(0u32) .x2("2") .x3(3) .x4("4") .no_getter(5) .x5(()) .maybe_generic_option(None::<()>) .x6(7); let actual = ( assert_getter::<&&'static str, _>(&builder, SutBuilder::x2_with_custom_name), assert_getter::<&u32, _>(&builder, SutBuilder::get_x3), assert_getter::<&&'static str, _>(&builder, SutBuilder::x4_override), assert_getter::, _>(&builder, SutBuilder::get_generic_option), assert_getter::, _>(&builder, SutBuilder::get_x6), ); assert_debug_eq(actual, expect![[r#"("2", 3, "4", None, Some(7))"#]]); } #[test] fn clone() { #[derive(Clone, Debug)] struct CloneNotCopy(#[allow(dead_code)] u32); #[derive(Builder)] struct Sut { #[builder(getter(clone))] _x1: CloneNotCopy, #[builder(getter(clone))] _x2: Option, #[builder(getter(clone), default = CloneNotCopy(0))] _x3: CloneNotCopy, } let sut = Sut::builder() .x1(CloneNotCopy(1)) .x2(CloneNotCopy(2)) .x3(CloneNotCopy(3)); let actual = ( assert_getter::(&sut, SutBuilder::get_x1), assert_getter::, _>(&sut, SutBuilder::get_x2), assert_getter::, _>(&sut, SutBuilder::get_x3), ); assert_debug_eq( actual, expect![[r#" ( CloneNotCopy( 1, ), Some( CloneNotCopy( 2, ), ), Some( CloneNotCopy( 3, ), ), )"#]], ); } #[test] fn copy() { #[derive(Debug, Builder)] struct Sut { #[builder(getter(copy))] _x1: u32, #[builder(getter(copy))] _x2: Option, #[builder(getter(copy), default)] _x3: u32, } let sut = Sut::builder().x1(1).x2(2).x3(3); let actual = ( assert_getter::(&sut, SutBuilder::get_x1), assert_getter::, _>(&sut, SutBuilder::get_x2), assert_getter::, _>(&sut, SutBuilder::get_x3), ); assert_debug_eq(actual, expect!["(1, Some(2), Some(3))"]); } #[test] #[cfg(feature = "std")] fn deref_implicit() { use std::borrow::Cow; use std::ffi::CStr; use std::ffi::{CString, OsStr, OsString}; use std::path::{Path, PathBuf}; #[derive(Debug, Builder)] struct Sut<'a> { #[builder(getter(deref))] _vec: Vec, #[builder(getter(deref))] _optional_vec: Option>, #[builder(getter(deref), default)] _default_vec: Vec, #[builder(getter(deref))] _box_: Box, #[builder(getter(deref))] _rc: Rc, #[builder(getter(deref))] _arc: Arc, #[builder(getter(deref))] _string: String, #[builder(getter(deref))] _c_string: CString, #[builder(getter(deref))] _os_string: OsString, #[builder(getter(deref))] _path_buf: PathBuf, #[builder(getter(deref))] _cow: Cow<'a, str>, } let builder = Sut::builder() .vec(vec![1, 2, 3]) .maybe_optional_vec(None) .default_vec(vec![0]) .box_(Box::new(4)) .rc(Rc::new(5)) .arc(Arc::new(6)) .string("7".to_string()) .c_string(CString::new("8").unwrap()) .os_string(OsString::from("9")) .path_buf(PathBuf::from("10")) .cow(Cow::Borrowed("11")); let actual = ( assert_getter::<&[u32], _>(&builder, SutBuilder::get_vec), assert_getter::, _>(&builder, SutBuilder::get_optional_vec), assert_getter::, _>(&builder, SutBuilder::get_default_vec), assert_getter::<&u32, _>(&builder, SutBuilder::get_box_), assert_getter::<&u32, _>(&builder, SutBuilder::get_rc), assert_getter::<&u32, _>(&builder, SutBuilder::get_arc), assert_getter::<&str, _>(&builder, SutBuilder::get_string), assert_getter::<&CStr, _>(&builder, SutBuilder::get_c_string), assert_getter::<&OsStr, _>(&builder, SutBuilder::get_os_string), assert_getter::<&Path, _>(&builder, SutBuilder::get_path_buf), assert_getter::<&str, _>(&builder, SutBuilder::get_cow), ); assert_debug_eq( actual, expect![[r#" ( [ 1, 2, 3, ], None, Some( [ 0, ], ), 4, 5, 6, "7", "8", "9", "10", "11", )"#]], ); } #[test] #[cfg(feature = "std")] fn deref_explicit() { use std::rc::Rc; #[derive(Debug, Builder)] #[allow(clippy::rc_buffer)] struct Sut { // Make sure a deref coercion happens through multiple layers #[builder(getter(deref(str)))] _x1: Rc, #[builder(getter(deref(str)))] _x2: Option>, #[builder(getter(deref(str)), default)] _x3: Rc, } let sut = Sut::builder() .x1(Rc::new("hello".to_owned())) .x2(Rc::new("world".to_owned())) .x3(Rc::new("!".to_owned())); let actual = ( assert_getter::<&str, _>(&sut, SutBuilder::get_x1), assert_getter::, _>(&sut, SutBuilder::get_x2), assert_getter::, _>(&sut, SutBuilder::get_x3), ); assert_debug_eq(actual, expect![[r#"("hello", Some("world"), Some("!"))"#]]); } /// Helper function that is better than just `let _: ExpectedType = builder.get_foo();` /// this notation involves an implicit deref coercion, but we want to assert the exact /// return type of the getter without any additional implicit conversions. fn assert_getter<'a, T, B>(builder: &'a B, method: fn(&'a B) -> T) -> T { method(builder) } bon-3.7.1/tests/integration/builder/attr_into.rs000064400000000000000000000027351046102023000201050ustar 00000000000000use crate::prelude::*; use core::fmt; use core::num::NonZeroU32; #[cfg(feature = "alloc")] #[test] fn into_attr_alloc() { use core::fmt; #[builder] fn sut(#[builder(into)] set: Option>, no_into: String) -> impl fmt::Debug { (set, no_into) } assert_debug_eq( sut().set([32, 43]).no_into("disabled".into()).call(), expect![[r#"(Some({32, 43}), "disabled")"#]], ); } #[test] fn into_attr_no_std() { #[builder] fn sut( #[builder(into)] str_ref: &str, /// Some docs #[builder(into)] u32: u32, ) -> impl fmt::Debug + '_ { (str_ref, u32) } struct IntoStrRef<'a>(&'a str); impl<'a> From> for &'a str { fn from(val: IntoStrRef<'a>) -> Self { val.0 } } assert_debug_eq( sut() .str_ref(IntoStrRef("vinyl-scratch")) .u32(NonZeroU32::new(32).unwrap()) .call(), expect![[r#"("vinyl-scratch", 32)"#]], ); } #[cfg(feature = "alloc")] #[test] fn into_string() { #[builder(on(String, into))] fn sut(arg1: String, arg2: Option) -> impl fmt::Debug { (arg1, arg2) } assert_debug_eq( sut().arg1("blackjack").arg2("bruh").call(), expect![[r#"("blackjack", Some("bruh"))"#]], ); assert_debug_eq( sut().arg1("blackjack").maybe_arg2(Some("bruh2")).call(), expect![[r#"("blackjack", Some("bruh2"))"#]], ); } bon-3.7.1/tests/integration/builder/attr_into_future.rs000064400000000000000000000170031046102023000214710ustar 00000000000000/// [`core::future::IntoFuture`] relies on [`Box`]. Also this trait was /// introduced in Rust 1.64, while `bon`'s MSRV is 1.59 at the time of this /// writing. #[cfg(any(feature = "std", feature = "alloc"))] #[rustversion::since(1.64)] mod tests { use crate::prelude::*; use core::future::{ready, IntoFuture}; use core::marker::PhantomData; async fn assert_send(builder: B) -> B::Output where B: IntoFuture + Send, B::IntoFuture: Send, { #[expect(clippy::incompatible_msrv)] let fut = builder.into_future(); let _: &dyn Send = &fut; fut.await } #[expect(clippy::future_not_send)] async fn non_send_future() { // By keeping `Rc` across an await point, we force the compiler to store it // as part of the future's state machine struct and thus we make it non-Send let non_send = PhantomData::>; ready(()).await; let _ = &non_send; } mod test_fn { use super::*; #[tokio::test] async fn basic() { #[builder(derive(IntoFuture(Box)))] async fn simple_async_fn(value: u32) -> u32 { ready(value * 2).await } // Test direct call. let builder = simple_async_fn().value(21).call(); assert_eq!(assert_send(builder).await, 42); // Test using IntoFuture with await. let builder = simple_async_fn().value(21); assert_eq!(assert_send(builder).await, 42); } #[tokio::test] async fn non_send() { #[builder(derive(IntoFuture(Box, ?Send)))] #[expect(clippy::future_not_send)] async fn non_send_async_fn(value: u32) -> u32 { non_send_future().await; // This future can be !Send. ready(value * 2).await } // Test with non-Send future. let result = non_send_async_fn().value(21).await; assert_eq!(result, 42); } #[tokio::test] async fn result() { #[builder(derive(IntoFuture(Box)))] async fn async_with_result(value: u32) -> Result { ready(if value > 0 { Ok(value * 2) } else { Err("Value must be positive") }) .await } // Test successful case. let builder = async_with_result().value(21); assert_eq!(assert_send(builder).await.unwrap(), 42); // Test error case. let builder = async_with_result().value(0); assert_send(builder).await.unwrap_err(); } #[tokio::test] async fn into_future_with_optional() { #[builder(derive(IntoFuture(Box)))] async fn optional_param(#[builder(default = 100)] value: u32) -> u32 { ready(value).await } // Test with value. let builder = optional_param().value(42); assert_eq!(assert_send(builder).await, 42); // Test without value (using default). let builder = optional_param(); assert_eq!(assert_send(builder).await, 100); } #[tokio::test] async fn references_in_params() { struct Dummy; #[builder(derive(IntoFuture(Box)))] async fn sut<'named1, 'named2>( _x1: &Dummy, _x2: &Dummy, x3: &'named1 Dummy, x4: &'named2 Dummy, ) -> &'named2 Dummy { let _: &'named1 Dummy = x3; ready(x4).await } // Store the dummy struct in local variables to make sure no `'static` // lifetime promotion happens let local_x1 = Dummy; let local_x2 = Dummy; let local_x3 = Dummy; let local_x4 = Dummy; let builder = sut() .x1(&local_x1) .x2(&local_x2) .x3(&local_x3) .x4(&local_x4); let &Dummy = assert_send(builder).await; } #[tokio::test] async fn anon_lifetime_in_return_type() { struct Dummy; #[builder(derive(IntoFuture(Box)))] async fn sut(x1: &Dummy) -> &Dummy { ready(x1).await } // Store the dummy struct in local variables to make sure no `'static` // lifetime promotion happens let local_x1 = Dummy; let builder = sut().x1(&local_x1); let &Dummy = assert_send(builder).await; } } mod test_method { use super::*; #[tokio::test] async fn basic() { struct Calculator; #[bon] impl Calculator { #[builder] #[builder(derive(IntoFuture(Box)))] async fn multiply(a: u32, b: u32) -> u32 { ready(a * b).await } } // Test using IntoFuture on impl method. let builder = Calculator::multiply().a(6).b(7); assert_eq!(assert_send(builder).await, 42); } #[tokio::test] async fn non_send() { struct Sut; #[bon] impl Sut { #[builder(derive(IntoFuture(Box, ?Send)))] #[expect(clippy::future_not_send)] async fn sut(self, value: u32) -> u32 { non_send_future().await; // This future can be !Send. ready(value * 2).await } } // Test with non-Send future. let result = Sut.sut().value(21).await; assert_eq!(result, 42); } #[tokio::test] async fn references_in_params() { struct Dummy; #[bon] impl Dummy { #[builder(derive(IntoFuture(Box)))] async fn sut<'named1, 'named2>( &self, _x1: &Self, _x2: &Self, x3: &'named1 Self, x4: &'named2 Self, ) -> &'named2 Self { let _: &'named1 Self = x3; ready(x4).await } } // Store the dummy struct in local variables to make sure no `'static` // lifetime promotion happens let local_self = Dummy; let local_x1 = Dummy; let local_x2 = Dummy; let local_x3 = Dummy; let local_x4 = Dummy; let builder = local_self .sut() .x1(&local_x1) .x2(&local_x2) .x3(&local_x3) .x4(&local_x4); let _: &Dummy = assert_send(builder).await; } #[tokio::test] async fn anon_lifetime_in_return_type() { struct Dummy; #[bon] impl Dummy { #[builder(derive(IntoFuture(Box)))] async fn sut(&self, _x1: &Self) -> &Self { ready(self).await } } // Store the dummy struct in local variables to make sure no `'static` // lifetime promotion happens let local_self = Dummy; let local_x1 = Dummy; let builder = local_self.sut().x1(&local_x1); let _: &Dummy = assert_send(builder).await; } } } bon-3.7.1/tests/integration/builder/attr_on.rs000064400000000000000000000025611046102023000175450ustar 00000000000000use crate::prelude::*; struct IntoBool(bool); impl From for bool { fn from(value: IntoBool) -> Self { value.0 } } struct IntoUnit; impl From for () { fn from(IntoUnit: IntoUnit) {} } struct IntoStrRef<'a>(&'a str); impl<'a> From> for &'a str { fn from(value: IntoStrRef<'a>) -> Self { value.0 } } struct Generic(T); struct IntoGeneric(T); impl From> for Generic { fn from(value: IntoGeneric) -> Self { Self(value.0) } } #[test] fn match_any() { #[builder(on(_, into))] fn sut(_arg1: bool, _arg2: Option<()>, _arg3: T) {} sut::<&str>() .arg1(IntoBool(true)) .arg2(IntoUnit) .arg3(IntoStrRef("foo")) .call(); } #[test] fn match_str_ref() { #[builder(on(&str, into))] fn sut(_arg1: bool, _arg2: Option<()>, _arg3: &str) {} sut().arg1(true).arg2(()).arg3(IntoStrRef("foo")).call(); } #[test] fn match_path() { #[builder(on(bool, into))] fn sut(_arg1: bool, _arg2: Option<()>, _arg3: T) {} sut::<&str>() .arg1(IntoBool(true)) .arg2(()) .arg3("foo") .call(); } #[test] fn match_generic() { #[builder(on(Generic<_>, into))] fn sut(_arg1: bool, _arg2: Option<()>, _arg3: Generic) {} sut().arg1(true).arg2(()).arg3(IntoGeneric("foo")).call(); } bon-3.7.1/tests/integration/builder/attr_overwritable.rs000064400000000000000000000046311046102023000216360ustar 00000000000000mod smoke { use crate::prelude::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut { #[builder(overwritable)] a: u32, #[builder(overwritable)] b: Option, #[builder(overwritable, default)] c: u32, } assert_debug_eq( Sut::builder().a(1).a(2).b(3).b(4).c(5).c(6).build(), expect!["Sut { a: 2, b: Some(4), c: 6 }"], ); } #[test] fn test_function() { #[builder] fn sut( #[builder(overwritable)] a: u32, #[builder(overwritable)] b: Option, #[builder(overwritable, default)] c: u32, ) -> impl fmt::Debug { (a, b, c) } assert_debug_eq( sut().a(1).a(2).b(3).b(4).c(5).c(6).call(), expect!["(2, Some(4), 6)"], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn sut( #[builder(overwritable)] a: u32, #[builder(overwritable)] b: Option, #[builder(overwritable, default)] c: u32, ) -> impl fmt::Debug { (a, b, c) } #[builder] fn with_self( &self, #[builder(overwritable)] a: u32, #[builder(overwritable)] b: Option, #[builder(overwritable, default)] c: u32, ) -> impl fmt::Debug { let _ = self; (a, b, c) } } assert_debug_eq( Sut::sut().a(1).a(2).b(3).b(4).c(5).c(6).call(), expect!["(2, Some(4), 6)"], ); assert_debug_eq( Sut.with_self().a(1).a(2).b(3).b(4).c(5).c(6).call(), expect!["(2, Some(4), 6)"], ); } } mod on { use crate::prelude::*; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] #[builder(on(u32, overwritable))] struct Sut { a: u32, b: Option, #[builder(default)] c: u32, } assert_debug_eq( Sut::builder().a(1).a(2).b(3).b(4).c(5).c(6).build(), expect!["Sut { a: 2, b: Some(4), c: 6 }"], ); } } bon-3.7.1/tests/integration/builder/attr_required.rs000064400000000000000000000206621046102023000207530ustar 00000000000000mod member_level { use crate::prelude::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut { #[builder(required)] regular: Option, #[builder(required)] generic: Option, #[builder(required, into)] with_into: Option, #[builder(required, default = Some(99))] with_default: Option, #[builder(required, default = Some(10))] with_default_2: Option, } assert_debug_eq( Sut::builder() .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .build(), expect![[r#" Sut { regular: Some( 1, ), generic: Some( false, ), with_into: Some( 2, ), with_default: Some( 99, ), with_default_2: Some( 3, ), }"#]], ); } #[test] fn test_function() { #[builder] fn sut( #[builder(required)] regular: Option, #[builder(required)] generic: Option, #[builder(required, into)] with_into: Option, #[builder(required, default = Some(99))] with_default: Option, #[builder(required, default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { (regular, generic, with_into, with_default, with_default_2) } assert_debug_eq( sut() .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn sut( #[builder(required)] regular: Option, #[builder(required)] generic: Option, #[builder(required, into)] with_into: Option, #[builder(required, default = Some(99))] with_default: Option, #[builder(required, default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { (regular, generic, with_into, with_default, with_default_2) } #[builder] fn with_self( &self, #[builder(required)] regular: Option, #[builder(required)] generic: Option, #[builder(required, into)] with_into: Option, #[builder(required, default = Some(99))] with_default: Option, #[builder(required, default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { let _ = self; (regular, generic, with_into, with_default, with_default_2) } } assert_debug_eq( Sut::sut() .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"], ); assert_debug_eq( Sut.with_self() .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"], ); } } mod attr_on { use crate::prelude::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(on(_, required))] #[allow(dead_code)] struct Sut { #[builder(start_fn)] start_fn: u32, regular: Option, generic: Option, #[builder(into)] with_into: Option, #[builder(default = Some(99))] with_default: Option, #[builder(default = Some(10))] with_default_2: Option, } assert_debug_eq( Sut::builder(11) .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .build(), expect![[r#" Sut { start_fn: 11, regular: Some( 1, ), generic: Some( false, ), with_into: Some( 2, ), with_default: Some( 99, ), with_default_2: Some( 3, ), }"#]], ); } #[test] fn test_function() { #[builder(on(_, required))] fn sut( #[builder(start_fn)] start_fn: u32, regular: Option, generic: Option, #[builder(into)] with_into: Option, #[builder(default = Some(99))] with_default: Option, #[builder(default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { ( start_fn, regular, generic, with_into, with_default, with_default_2, ) } assert_debug_eq( sut(11) .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(on(_, required))] fn sut( #[builder(start_fn)] start_fn: u32, regular: Option, generic: Option, #[builder(into)] with_into: Option, #[builder(default = Some(99))] with_default: Option, #[builder(default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { ( start_fn, regular, generic, with_into, with_default, with_default_2, ) } #[builder(on(_, required))] fn with_self( &self, #[builder(start_fn)] start_fn: u32, regular: Option, generic: Option, #[builder(into)] with_into: Option, #[builder(default = Some(99))] with_default: Option, #[builder(default = Some(10))] with_default_2: Option, ) -> impl fmt::Debug { let _ = self; ( start_fn, regular, generic, with_into, with_default, with_default_2, ) } } assert_debug_eq( Sut::sut(11) .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"], ); assert_debug_eq( Sut.with_self(11) .regular(Some(1)) .generic(Some(false)) .with_into(2) .maybe_with_default_2(Some(Some(3))) .call(), expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"], ); } } bon-3.7.1/tests/integration/builder/attr_setters.rs000064400000000000000000000325331046102023000206240ustar 00000000000000mod name { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] #[allow(dead_code)] struct Sut { #[builder(setters(name = arg1_renamed))] arg1: bool, #[builder(setters(name = arg2_renamed))] arg2: Option<()>, #[builder(setters(name = arg3_renamed), default)] arg3: u32, } use sut_builder::*; #[allow(type_alias_bounds)] type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3); let _ = Sut::builder().arg1_renamed(true); let _ = Sut::builder().arg2_renamed(()); let _ = Sut::builder().maybe_arg2_renamed(Some(())); let _ = Sut::builder().arg3_renamed(42); let _ = Sut::builder().maybe_arg3_renamed(Some(42)); // The name in the state must remain the same let _: SutBuilder>> = Sut::builder() .arg1_renamed(true) .arg2_renamed(()) .arg3_renamed(42); } #[test] fn test_function() { #[builder] fn sut( #[builder(setters(name = arg1_renamed))] _arg1: bool, #[builder(setters(name = arg2_renamed))] _arg2: Option<()>, #[builder(setters(name = arg3_renamed), default)] _arg3: u32, ) { } use sut_builder::*; #[allow(type_alias_bounds)] type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3); let _ = sut().arg1_renamed(true); let _ = sut().arg2_renamed(()); let _ = sut().maybe_arg2_renamed(Some(())); let _ = sut().arg3_renamed(42); let _ = sut().maybe_arg3_renamed(Some(42)); // The name in the state must remain the same let _: SutBuilder>> = sut().arg1_renamed(true).arg2_renamed(()).arg3_renamed(42); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn sut( #[builder(setters(name = arg1_renamed))] _arg1: bool, #[builder(setters(name = arg2_renamed))] _arg2: Option<()>, #[builder(setters(name = arg3_renamed), default)] _arg3: u32, ) { } #[builder] fn with_self( &self, #[builder(setters(name = arg1_renamed))] _arg1: bool, #[builder(setters(name = arg2_renamed))] _arg2: Option<()>, #[builder(setters(name = arg3_renamed), default)] _arg3: u32, ) { let _ = self; } } { use sut_sut_builder::*; #[allow(type_alias_bounds)] type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3); let _ = Sut::sut().arg1_renamed(true); let _ = Sut::sut().arg2_renamed(()); let _ = Sut::sut().maybe_arg2_renamed(Some(())); let _ = Sut::sut().arg3_renamed(42); let _ = Sut::sut().maybe_arg3_renamed(Some(42)); // The name in the state must remain the same let _: SutSutBuilder>> = Sut::sut() .arg1_renamed(true) .arg2_renamed(()) .arg3_renamed(42); } { use sut_with_self_builder::*; #[allow(type_alias_bounds)] type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3); let sut = Sut; let _ = sut.with_self().arg1_renamed(true); let _ = sut.with_self().arg2_renamed(()); let _ = sut.with_self().maybe_arg2_renamed(Some(())); let _ = sut.with_self().arg3_renamed(42); let _ = sut.with_self().maybe_arg3_renamed(Some(42)); // The name in the state must remain the same let _: SutWithSelfBuilder<'_, SetArg3>> = sut .with_self() .arg1_renamed(true) .arg2_renamed(()) .arg3_renamed(42); } } } mod option_fn_name_and_some_fn_name { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] #[builder(derive(Clone))] #[allow(dead_code)] struct Sut { #[builder(setters(some_fn = arg1_some))] arg1: Option<()>, #[builder(setters(option_fn = arg2_option))] arg2: Option<()>, #[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] arg3: Option<()>, #[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))] arg4: Option<()>, #[builder(default, setters(some_fn = arg5_some))] arg5: (), #[builder(default, setters(option_fn = arg6_option))] arg6: (), #[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] arg7: (), #[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))] arg8: (), } use sut_builder::*; let _ = Sut::builder().arg1_some(()); let _ = Sut::builder().maybe_arg1(Some(())); let _ = Sut::builder().arg2(()); let _ = Sut::builder().arg2_option(Some(())); let _ = Sut::builder().arg3_some(()); let _ = Sut::builder().arg3_option(Some(())); let _ = Sut::builder().arg4_some(()); let _ = Sut::builder().arg4_option(Some(())); let _ = Sut::builder().arg5_some(()); let _ = Sut::builder().maybe_arg5(Some(())); let _ = Sut::builder().arg6(()); let _ = Sut::builder().arg6_option(Some(())); let _ = Sut::builder().arg7_some(()); let _ = Sut::builder().arg7_option(Some(())); let _ = Sut::builder().arg8_some(()); let _ = Sut::builder().arg8_option(Some(())); #[allow(clippy::type_complexity)] let _: SutBuilder< SetArg8>>>>>>, > = Sut::builder() .arg1_some(()) .arg2(()) .arg3_some(()) .arg4_some(()) .arg5_some(()) .arg6(()) .arg7_some(()) .arg8_some(()); } #[test] fn test_function() { #[builder(derive(Clone))] fn sut( #[builder(setters(some_fn = arg1_some))] _arg1: Option<()>, #[builder(setters(option_fn = arg2_option))] _arg2: Option<()>, #[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>, #[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))] _arg4: Option<()>, #[builder(default, setters(some_fn = arg5_some))] _arg5: (), #[builder(default, setters(option_fn = arg6_option))] _arg6: (), #[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: (), #[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))] _arg8: (), ) { } use sut_builder::*; let _ = sut().arg1_some(()); let _ = sut().maybe_arg1(Some(())); let _ = sut().arg2(()); let _ = sut().arg2_option(Some(())); let _ = sut().arg3_some(()); let _ = sut().arg3_option(Some(())); let _ = sut().arg4_some(()); let _ = sut().arg4_option(Some(())); let _ = sut().arg5_some(()); let _ = sut().maybe_arg5(Some(())); let _ = sut().arg6(()); let _ = sut().arg6_option(Some(())); let _ = sut().arg7_some(()); let _ = sut().arg7_option(Some(())); let _ = sut().arg8_some(()); let _ = sut().arg8_option(Some(())); #[allow(clippy::type_complexity)] let _: SutBuilder< SetArg8>>>>>>, > = sut() .arg1_some(()) .arg2(()) .arg3_some(()) .arg4_some(()) .arg5_some(()) .arg6(()) .arg7_some(()) .arg8_some(()); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(derive(Clone))] fn sut( #[builder(setters(some_fn = arg1_some))] _arg1: Option<()>, #[builder(setters(option_fn = arg2_option))] _arg2: Option<()>, #[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>, #[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))] _arg4: Option<()>, #[builder(default, setters(some_fn = arg5_some))] _arg5: (), #[builder(default, setters(option_fn = arg6_option))] _arg6: (), #[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: ( ), #[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))] _arg8: (), ) { } #[builder(derive(Clone))] fn with_self( &self, #[builder(setters(some_fn = arg1_some))] _arg1: Option<()>, #[builder(setters(option_fn = arg2_option))] _arg2: Option<()>, #[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>, #[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))] _arg4: Option<()>, #[builder(default, setters(some_fn = arg5_some))] _arg5: (), #[builder(default, setters(option_fn = arg6_option))] _arg6: (), #[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: ( ), #[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))] _arg8: (), ) { let _ = self; } } { use sut_sut_builder::*; let _ = Sut::sut().arg1_some(()); let _ = Sut::sut().maybe_arg1(Some(())); let _ = Sut::sut().arg2(()); let _ = Sut::sut().arg2_option(Some(())); let _ = Sut::sut().arg3_some(()); let _ = Sut::sut().arg3_option(Some(())); let _ = Sut::sut().arg4_some(()); let _ = Sut::sut().arg4_option(Some(())); let _ = Sut::sut().arg5_some(()); let _ = Sut::sut().maybe_arg5(Some(())); let _ = Sut::sut().arg6(()); let _ = Sut::sut().arg6_option(Some(())); let _ = Sut::sut().arg7_some(()); let _ = Sut::sut().arg7_option(Some(())); let _ = Sut::sut().arg8_some(()); let _ = Sut::sut().arg8_option(Some(())); #[allow(clippy::type_complexity)] let _: SutSutBuilder< SetArg8>>>>>>, > = Sut::sut() .arg1_some(()) .arg2(()) .arg3_some(()) .arg4_some(()) .arg5_some(()) .arg6(()) .arg7_some(()) .arg8_some(()); } { use sut_with_self_builder::*; let _ = Sut.with_self().arg1_some(()); let _ = Sut.with_self().maybe_arg1(Some(())); let _ = Sut.with_self().arg2(()); let _ = Sut.with_self().arg2_option(Some(())); let _ = Sut.with_self().arg3_some(()); let _ = Sut.with_self().arg3_option(Some(())); let _ = Sut.with_self().arg4_some(()); let _ = Sut.with_self().arg4_option(Some(())); let _ = Sut.with_self().arg5_some(()); let _ = Sut.with_self().maybe_arg5(Some(())); let _ = Sut.with_self().arg6(()); let _ = Sut.with_self().arg6_option(Some(())); let _ = Sut.with_self().arg7_some(()); let _ = Sut.with_self().arg7_option(Some(())); let _ = Sut.with_self().arg8_some(()); let _ = Sut.with_self().arg8_option(Some(())); #[allow(clippy::type_complexity)] let _: SutWithSelfBuilder< '_, SetArg8>>>>>>, > = Sut .with_self() .arg1_some(()) .arg2(()) .arg3_some(()) .arg4_some(()) .arg5_some(()) .arg6(()) .arg7_some(()) .arg8_some(()); } } } mod self_references_in_docs { use crate::prelude::*; #[test] fn test_struct() { /// [`Self`] link #[derive(Builder)] struct Sut { /// [`Self`] link #[builder(setters(doc {}))] _arg1: u32, /// [`Self`] link #[builder(setters( option_fn(doc {}), some_fn(doc {}) ))] _arg2: Option, } let _ = Sut::builder().arg1(42); } #[test] fn test_function() { /// [`Self`] link #[builder] fn sut( /// [`Self`] link #[builder(setters(doc {}))] _arg1: u32, ) { } let _ = sut().arg1(42); } } bon-3.7.1/tests/integration/builder/attr_skip.rs000064400000000000000000000051501046102023000200740ustar 00000000000000use crate::prelude::*; use expect_test::expect; #[cfg(feature = "alloc")] #[test] fn struct_alloc() { use expect_test::expect; #[derive(Debug, Builder)] struct Sut { #[builder(skip = "skip".to_owned())] #[allow(dead_code)] arg1: String, #[builder(skip = vec![42])] #[allow(dead_code)] arg2: Vec, } assert_debug_eq( Sut::builder().build(), expect![[r#"Sut { arg1: "skip", arg2: [42] }"#]], ); } #[test] fn struct_no_std() { #[derive(Debug, Builder)] struct Sut { #[builder(skip)] #[allow(dead_code)] arg1: u32, #[builder(skip = 42)] #[allow(dead_code)] arg2: u32, } assert_debug_eq(Sut::builder().build(), expect!["Sut { arg1: 0, arg2: 42 }"]); } #[test] fn struct_with_non_skipped_arg() { #[derive(Debug, Builder)] struct Sut { #[builder(skip)] #[allow(dead_code)] arg1: u32, #[allow(dead_code)] arg2: u32, } assert_debug_eq( Sut::builder().arg2(24).build(), expect!["Sut { arg1: 0, arg2: 24 }"], ); } #[test] fn struct_generic_skipped() { #[derive(Builder)] struct Sut where A: Clone + Default, B: Clone + Default, { #[builder(skip)] #[allow(dead_code)] arg1: A, #[builder(skip = <_>::default())] #[allow(dead_code)] arg2: B, } let _: Sut<(), ()> = Sut::<(), ()>::builder().build(); } #[test] fn interaction_with_positional_members() { #[derive(Builder, Debug)] #[allow(dead_code)] struct Sut { #[builder(start_fn)] starter_1: u32, #[builder(start_fn)] starter_2: u32, #[builder(finish_fn)] finisher_1: u32, #[builder(finish_fn)] finisher_2: u32, #[builder(skip = [starter_1, starter_2, finisher_1, finisher_2])] named_1: [u32; 4], #[builder(skip = (32, named_1))] named_2: (u32, [u32; 4]), } assert_debug_eq( Sut::builder(1, 2).build(3, 4), expect![[r#" Sut { starter_1: 1, starter_2: 2, finisher_1: 3, finisher_2: 4, named_1: [ 1, 2, 3, 4, ], named_2: ( 32, [ 1, 2, 3, 4, ], ), }"#]], ); } bon-3.7.1/tests/integration/builder/attr_top_level_start_fn.rs000064400000000000000000000036571046102023000230310ustar 00000000000000use crate::prelude::*; use core::fmt; #[test] fn test_method() { { struct Sut; #[bon] impl Sut { #[builder(start_fn = builder)] fn new() -> Self { Self } #[builder(start_fn = regular_builder)] fn regular() {} } let builder: SutBuilder = Sut::builder(); let _: Sut = builder.build(); let _: Sut = Sut::new(); Sut::regular_builder().call(); Sut::regular(); } { pub(crate) struct Sut; #[bon] impl Sut { #[builder(start_fn(name = builder, vis = ""))] pub(crate) fn new() -> Self { Self } #[builder(start_fn(name = regular_builder, vis = ""))] pub(crate) fn regular() {} } let builder: SutBuilder = Sut::builder(); let _: Sut = builder.build(); let _: Sut = Sut::new(); Sut::regular_builder().call(); Sut::regular(); } } #[test] fn test_function() { { #[builder(start_fn(name = sut_builder))] fn sut(arg1: bool, arg2: u32) -> impl fmt::Debug { (arg1, arg2) } assert_debug_eq(sut(true, 42), expect!["(true, 42)"]); } { #[builder(start_fn = sut_builder)] fn sut(arg1: u32) -> u32 { arg1 } assert_debug_eq(sut(42), expect!["42"]); } { #[builder(start_fn(name = sut_builder, vis = ""))] fn sut(arg1: u32) -> u32 { arg1 } assert_debug_eq(sut(42), expect!["42"]); } { /// Docs on `sut` #[builder(start_fn(name = sut_builder, doc { /// Docs on `sut_builder` }))] fn sut(arg1: u32) -> u32 { arg1 } assert_debug_eq(sut_builder().arg1(42).call(), expect!["42"]); assert_debug_eq(sut(42), expect!["42"]); } } bon-3.7.1/tests/integration/builder/attr_with/from_iter.rs000064400000000000000000000313061046102023000220710ustar 00000000000000#![cfg(feature = "std")] #![allow(clippy::linkedlist)] use crate::prelude::*; use core::fmt; use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; type RenamedVec = Vec; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(derive(Clone))] struct Sut { #[builder(with = <_>::from_iter)] _vec: Vec, #[builder(with = FromIterator::from_iter)] _optional_vec: Option<::alloc::vec::Vec>, #[builder(with = <_>::from_iter, default)] _default_vec: Vec, #[builder(with = FromIterator::from_iter)] _renamed_vec: RenamedVec, #[builder(with = <_>::from_iter)] _hash_set: HashSet, #[builder(with = FromIterator::from_iter)] _btree_set: BTreeSet, #[builder(with = <_>::from_iter)] _vec_deque: VecDeque, #[builder(with = FromIterator::from_iter)] _binary_heap: BinaryHeap, #[builder(with = <_>::from_iter)] _linked_list: std::collections::LinkedList, #[builder(with = FromIterator::from_iter)] _hash_map: HashMap, #[builder(with = <_>::from_iter)] _btree_map: std::collections::BTreeMap, } let builder = Sut::builder(); let _ignore = builder.clone().optional_vec([1, 2, 3]); let builder = builder.maybe_optional_vec(Some([4, 5, 6])); let _ignore = builder.clone().default_vec([7, 8, 9]); let builder = builder.maybe_default_vec(Some([10, 11, 12])); // `Hash*`` collections have random order of iteration, so their debug // output is unstable. To work around this instability, we just specify // a single element for `Hash*` collections. let sut = builder .vec([13, 14, 15]) .renamed_vec([16, 17, 18]) .hash_set(std::iter::once(19)) .btree_set([20, 21, 22, 22, 21]) .vec_deque([23, 24, 25]) .binary_heap([26, 27, 28]) .linked_list([29, 30, 31]) .hash_map(std::iter::once((32, 33))) .btree_map([(34, 35), (34, 36), (37, 38)]) .build(); assert_debug_eq( &sut, expect![[r#" Sut { _vec: [ 13, 14, 15, ], _optional_vec: Some( [ 4, 5, 6, ], ), _default_vec: [ 10, 11, 12, ], _renamed_vec: [ 16, 17, 18, ], _hash_set: { 19, }, _btree_set: { 20, 21, 22, }, _vec_deque: [ 23, 24, 25, ], _binary_heap: [ 28, 27, 26, ], _linked_list: [ 29, 30, 31, ], _hash_map: { 32: 33, }, _btree_map: { 34: 36, 37: 38, }, }"#]], ); } #[test] fn test_function() { #[builder(derive(Clone))] fn sut( #[builder(with = <_>::from_iter)] vec: Vec, #[builder(with = FromIterator::from_iter)] optional_vec: Option<::alloc::vec::Vec>, #[builder(with = <_>::from_iter, default)] default_vec: Vec, #[builder(with = FromIterator::from_iter)] renamed_vec: RenamedVec, #[builder(with = <_>::from_iter)] hash_set: HashSet, #[builder(with = FromIterator::from_iter)] btree_set: BTreeSet, #[builder(with = <_>::from_iter)] vec_deque: VecDeque, #[builder(with = FromIterator::from_iter)] binary_heap: BinaryHeap, #[builder(with = <_>::from_iter)] linked_list: std::collections::LinkedList, #[builder(with = FromIterator::from_iter)] hash_map: HashMap, #[builder(with = <_>::from_iter)] btree_map: std::collections::BTreeMap, ) -> impl fmt::Debug { ( vec, optional_vec, default_vec, renamed_vec, hash_set, btree_set, vec_deque, binary_heap, linked_list, hash_map, btree_map, ) } let builder = sut(); let _ignore = builder.clone().optional_vec([1, 2, 3]); let builder = builder.maybe_optional_vec(Some([4, 5, 6])); let _ignore = builder.clone().default_vec([7, 8, 9]); let builder = builder.maybe_default_vec(Some([10, 11, 12])); // `Hash*`` collections have random order of iteration, so their debug // output is unstable. To work around this instability, we just specify // a single element for `Hash*` collections. let sut = builder .vec([13, 14, 15]) .renamed_vec([16, 17, 18]) .hash_set(std::iter::once(19)) .btree_set([20, 21, 22, 22, 21]) .vec_deque([23, 24, 25]) .binary_heap([26, 27, 28]) .linked_list([29, 30, 31]) .hash_map(std::iter::once((32, 33))) .btree_map([(34, 35), (34, 36), (37, 38)]) .call(); assert_debug_eq( &sut, expect![[r#" ( [ 13, 14, 15, ], Some( [ 4, 5, 6, ], ), [ 10, 11, 12, ], [ 16, 17, 18, ], { 19, }, { 20, 21, 22, }, [ 23, 24, 25, ], [ 28, 27, 26, ], [ 29, 30, 31, ], { 32: 33, }, { 34: 36, 37: 38, }, )"#]], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(derive(Clone))] fn sut( #[builder(with = <_>::from_iter)] vec: Vec, #[builder(with = FromIterator::from_iter)] optional_vec: Option<::alloc::vec::Vec>, #[builder(with = <_>::from_iter, default)] default_vec: Vec, #[builder(with = FromIterator::from_iter)] renamed_vec: RenamedVec, #[builder(with = <_>::from_iter)] hash_set: HashSet, #[builder(with = FromIterator::from_iter)] btree_set: BTreeSet, #[builder(with = <_>::from_iter)] vec_deque: VecDeque, #[builder(with = FromIterator::from_iter)] binary_heap: BinaryHeap, #[builder(with = <_>::from_iter)] linked_list: std::collections::LinkedList, #[builder(with = FromIterator::from_iter)] hash_map: HashMap, #[builder(with = <_>::from_iter)] btree_map: std::collections::BTreeMap, ) -> impl fmt::Debug { ( vec, optional_vec, default_vec, renamed_vec, hash_set, btree_set, vec_deque, binary_heap, linked_list, hash_map, btree_map, ) } #[builder(derive(Clone))] fn with_self( &self, #[builder(with = <_>::from_iter)] vec: Vec, #[builder(with = FromIterator::from_iter)] optional_vec: Option<::alloc::vec::Vec>, #[builder(with = <_>::from_iter, default)] default_vec: Vec, #[builder(with = FromIterator::from_iter)] renamed_vec: RenamedVec, #[builder(with = <_>::from_iter)] hash_set: HashSet, #[builder(with = FromIterator::from_iter)] btree_set: BTreeSet, #[builder(with = <_>::from_iter)] vec_deque: VecDeque, #[builder(with = FromIterator::from_iter)] binary_heap: BinaryHeap, #[builder(with = <_>::from_iter)] linked_list: std::collections::LinkedList, #[builder(with = FromIterator::from_iter)] hash_map: HashMap, #[builder(with = <_>::from_iter)] btree_map: std::collections::BTreeMap, ) -> impl fmt::Debug { let _ = self; ( vec, optional_vec, default_vec, renamed_vec, hash_set, btree_set, vec_deque, binary_heap, linked_list, hash_map, btree_map, ) } } let builder = Sut::sut(); let _ignore = builder.clone().optional_vec([1, 2, 3]); let builder = builder.maybe_optional_vec(Some([4, 5, 6])); let _ignore = builder.clone().default_vec([7, 8, 9]); let builder = builder.maybe_default_vec(Some([10, 11, 12])); // `Hash*`` collections have random order of iteration, so their debug // output is unstable. To work around this instability, we just specify // a single element for `Hash*` collections. let sut = builder .vec([13, 14, 15]) .renamed_vec([16, 17, 18]) .hash_set(std::iter::once(19)) .btree_set([20, 21, 22, 22, 21]) .vec_deque([23, 24, 25]) .binary_heap([26, 27, 28]) .linked_list([29, 30, 31]) .hash_map(std::iter::once((32, 33))) .btree_map([(34, 35), (34, 36), (37, 38)]) .call(); assert_debug_eq( &sut, expect![[r#" ( [ 13, 14, 15, ], Some( [ 4, 5, 6, ], ), [ 10, 11, 12, ], [ 16, 17, 18, ], { 19, }, { 20, 21, 22, }, [ 23, 24, 25, ], [ 28, 27, 26, ], [ 29, 30, 31, ], { 32: 33, }, { 34: 36, 37: 38, }, )"#]], ); let builder = Sut.with_self(); let _ignore = builder.clone().optional_vec([1, 2, 3]); let builder = builder.maybe_optional_vec(Some([4, 5, 6])); let _ignore = builder.clone().default_vec([7, 8, 9]); let builder = builder.maybe_default_vec(Some([10, 11, 12])); // `Hash*`` collections have random order of iteration, so their debug // output is unstable. To work around this instability, we just specify // a single element for `Hash*` collections. let sut = builder .vec([13, 14, 15]) .renamed_vec([16, 17, 18]) .hash_set(std::iter::once(19)) .btree_set([20, 21, 22, 22, 21]) .vec_deque([23, 24, 25]) .binary_heap([26, 27, 28]) .linked_list([29, 30, 31]) .hash_map(std::iter::once((32, 33))) .btree_map([(34, 35), (34, 36), (37, 38)]) .call(); assert_debug_eq( &sut, expect![[r#" ( [ 13, 14, 15, ], Some( [ 4, 5, 6, ], ), [ 10, 11, 12, ], [ 16, 17, 18, ], { 19, }, { 20, 21, 22, }, [ 23, 24, 25, ], [ 28, 27, 26, ], [ 29, 30, 31, ], { 32: 33, }, { 34: 36, 37: 38, }, )"#]], ); } bon-3.7.1/tests/integration/builder/attr_with/mod.rs000064400000000000000000000004071046102023000206600ustar 00000000000000mod from_iter; mod multi_arg; #[cfg(feature = "experimental-overwritable")] mod overwritable; mod single_arg; mod some; struct IntoStrRef<'a>(&'a str); impl<'a> From> for &'a str { fn from(val: IntoStrRef<'a>) -> Self { val.0 } } bon-3.7.1/tests/integration/builder/attr_with/multi_arg.rs000064400000000000000000000074071046102023000220730ustar 00000000000000use super::IntoStrRef; use crate::prelude::*; use core::convert::Infallible; use core::{fmt, num}; type ParseIntResult = Result; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(derive(Clone))] #[allow(dead_code)] struct Sut { #[builder(with = |x: u32, y: u32| x + y)] required: u32, #[builder(with = |x: u32, y: u32| x + y)] optional: Option, #[builder(with = |x: u32, y: u32| x + y, default)] default: u32, #[builder(with = |value: &T, _value2: &T| value.clone())] generic: T, #[builder(with = |value: &T, _value2: &T| value.clone())] optional_generic: Option, #[builder(with = |value: &T, _value2: &T| value.clone(), default)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into())] impl_trait: &'static str, #[builder(with = |value: &str, _value2: u32| -> Result<_, num::ParseIntError> { value.parse() })] try_required: u32, #[builder(with = |value: &str, _value2: u32| -> Result<_, num::ParseIntError> { value.parse() })] try_optional: Option, #[builder(with = |value: &str, _value2: u32| -> ParseIntResult<_> { value.parse() }, default)] try_default: u32, #[builder(with = |value: &T, _value2: &T| -> Result<_, Infallible> { Ok(value.clone()) })] try_optional_generic: Option, #[builder(with = |value: &T, _value2: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>, _value2: impl fmt::Debug| -> Result<_, Infallible> { Ok(value.into()) })] try_impl_trait: &'static str, } let builder = Sut::builder() .required(1, 2) .optional(3, 4) .default(5, 6) .generic(&"hello", &"world"); let _ignore = builder.clone().optional_generic(&"hello", &"you"); let builder = builder.maybe_optional_generic(Some((&"littlepip", &"blackjack"))); let _ignore = builder.clone().default_generic(&"p21", &"rampage"); let builder = builder.maybe_default_generic(Some((&"<3", &"glory"))); let builder = builder .impl_trait(IntoStrRef("p21")) .try_required("4", 99) .unwrap(); let _ignore = builder.clone().try_optional("5", 99).unwrap(); let builder = builder.maybe_try_optional(Some(("6", 99))).unwrap(); let _ignore = builder.clone().try_default("7", 99).unwrap(); let builder = builder.maybe_try_default(Some(("8", 99))).unwrap(); let _ignore = builder.clone().try_optional_generic(&"9", &"99").unwrap(); let builder = builder .maybe_try_optional_generic(Some((&"10", &"99"))) .unwrap(); let _ignore = builder.clone().try_default_generic(&"11", &"99").unwrap(); let builder = builder .maybe_try_default_generic(Some((&"12", &"99"))) .unwrap(); let builder = builder.try_impl_trait(IntoStrRef("p21"), true).unwrap(); assert_debug_eq( builder.build(), expect![[r#" Sut { required: 3, optional: Some( 7, ), default: 11, generic: "hello", optional_generic: Some( "littlepip", ), default_generic: "<3", impl_trait: "p21", try_required: 4, try_optional: Some( 6, ), try_default: 8, try_optional_generic: Some( "10", ), try_default_generic: "12", try_impl_trait: "p21", }"#]], ); } bon-3.7.1/tests/integration/builder/attr_with/overwritable.rs000064400000000000000000000071711046102023000226130ustar 00000000000000use super::IntoStrRef; use crate::prelude::*; use core::convert::Infallible; use core::num; type ParseIntResult = Result; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut { #[builder(with = |x: u32| x + 1, overwritable)] required: u32, #[builder(with = |x: u32| x + 1, overwritable)] optional: Option, #[builder(with = |x: u32| x + 1, default, overwritable)] default: u32, #[builder(with = |value: &T| value.clone(), overwritable)] generic: T, #[builder(with = |value: &T| value.clone(), overwritable)] optional_generic: Option, #[builder(with = |value: &T| value.clone(), default, overwritable)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into(), overwritable)] impl_trait: &'static str, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() }, overwritable)] try_required: u32, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() }, overwritable)] try_optional: Option, #[builder(with = |value: &str| -> ParseIntResult<_> { value.parse() }, default, overwritable)] try_default: u32, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, overwritable)] try_optional_generic: Option, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default, overwritable)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>| -> Result<_, Infallible> { Ok(value.into()) }, overwritable)] try_impl_trait: &'static str, } let builder = Sut::builder() .required(1) .required(2) .optional(3) .optional(4) .default(5) .default(6) .generic(&"hello") .generic(&"hello2") .optional_generic(&"hello you") .maybe_optional_generic(Some(&"littlepip")) .default_generic(&"blackjack") .maybe_default_generic(Some(&"<3")) .impl_trait(IntoStrRef("p21")) .impl_trait(IntoStrRef("rampage")) .try_required("7") .unwrap() .try_required("8") .unwrap() .try_optional("9") .unwrap() .maybe_try_optional(Some("10")) .unwrap() .try_default("11") .unwrap() .maybe_try_default(Some("12")) .unwrap() .try_optional_generic(&"13") .unwrap() .maybe_try_optional_generic(Some(&"14")) .unwrap() .try_default_generic(&"15") .unwrap() .maybe_try_default_generic(Some(&"16")) .unwrap() .try_impl_trait(IntoStrRef("daisy")) .unwrap() .try_impl_trait(IntoStrRef("roseluck")) .unwrap(); assert_debug_eq( builder.build(), expect![[r#" Sut { required: 3, optional: Some( 5, ), default: 7, generic: "hello2", optional_generic: Some( "littlepip", ), default_generic: "<3", impl_trait: "rampage", try_required: 8, try_optional: Some( 10, ), try_default: 12, try_optional_generic: Some( "14", ), try_default_generic: "16", try_impl_trait: "roseluck", }"#]], ); } bon-3.7.1/tests/integration/builder/attr_with/single_arg.rs000064400000000000000000000357031046102023000222220ustar 00000000000000use crate::prelude::*; use core::convert::Infallible; use core::{fmt, num}; type ParseIntResult = Result; use super::IntoStrRef; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(derive(Clone))] #[allow(dead_code)] struct Sut { #[builder(with = |x: u32| x + 1)] required: u32, #[builder(with = |x: u32| x + 1)] optional: Option, #[builder(with = |x: u32| x + 1, default)] default: u32, #[builder(with = |value: &T| value.clone())] generic: T, #[builder(with = |value: &T| value.clone())] optional_generic: Option, #[builder(with = |value: &T| value.clone(), default)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into())] impl_trait: &'static str, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_required: u32, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_optional: Option, #[builder(with = |value: &str| -> ParseIntResult<_> { value.parse() }, default)] try_default: u32, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) })] try_optional_generic: Option, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>| -> Result<_, Infallible> { Ok(value.into()) })] try_impl_trait: &'static str, } let builder = Sut::builder() .required(1) .optional(2) .default(3) .generic(&"hello"); let _ignore = builder.clone().optional_generic(&"hello you"); let builder = builder.maybe_optional_generic(Some(&"littlepip")); let _ignore = builder.clone().default_generic(&"blackjack"); let builder = builder.maybe_default_generic(Some(&"<3")); let builder = builder .impl_trait(IntoStrRef("morning glory")) .try_required("4") .unwrap(); let _ignore = builder.clone().try_optional("5").unwrap(); let builder = builder.maybe_try_optional(Some("6")).unwrap(); let _ignore = builder.clone().try_default("7").unwrap(); let builder = builder.maybe_try_default(Some("8")).unwrap(); let _ignore = builder.clone().try_optional_generic(&"9").unwrap(); let builder = builder.maybe_try_optional_generic(Some(&"10")).unwrap(); let _ignore = builder.clone().try_default_generic(&"11").unwrap(); let builder = builder.maybe_try_default_generic(Some(&"12")).unwrap(); let builder = builder.try_impl_trait(IntoStrRef("morning glory")).unwrap(); assert_debug_eq( builder.build(), expect![[r#" Sut { required: 2, optional: Some( 3, ), default: 4, generic: "hello", optional_generic: Some( "littlepip", ), default_generic: "<3", impl_trait: "morning glory", try_required: 4, try_optional: Some( 6, ), try_default: 8, try_optional_generic: Some( "10", ), try_default_generic: "12", try_impl_trait: "morning glory", }"#]], ); } #[test] fn test_function() { #[builder(derive(Clone))] fn sut( #[builder(with = |x: u32| x + 1)] required: u32, #[builder(with = |x: u32| x + 1)] optional: Option, #[builder(with = |x: u32| x + 1, default)] default: u32, #[builder(with = |value: &T| value.clone())] generic: T, #[builder(with = |value: &T| value.clone())] optional_generic: Option, #[builder(with = |value: &T| value.clone(), default)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into())] impl_trait: &'static str, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_required: u32, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_optional: Option, #[builder(with = |value: &str| -> ParseIntResult<_> { value.parse() }, default)] try_default: u32, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) })] try_optional_generic: Option, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>| -> Result<_, Infallible> { Ok(value.into()) })] try_impl_trait: &'static str, ) -> impl fmt::Debug { ( ( required, optional, default, generic, optional_generic, default_generic, impl_trait, ), ( try_required, try_optional, try_default, try_optional_generic, try_default_generic, try_impl_trait, ), ) } let builder = sut().required(1).optional(2).default(3).generic(&"hello"); let _ignore = builder.clone().optional_generic(&"hello you"); let builder = builder.maybe_optional_generic(Some(&"littlepip")); let _ignore = builder.clone().default_generic(&"blackjack"); let builder = builder.maybe_default_generic(Some(&"<3")); let builder = builder .impl_trait(IntoStrRef("morning glory")) .try_required("4") .unwrap(); let _ignore = builder.clone().try_optional("5").unwrap(); let builder = builder.maybe_try_optional(Some("6")).unwrap(); let _ignore = builder.clone().try_default("7").unwrap(); let builder = builder.maybe_try_default(Some("8")).unwrap(); let _ignore = builder.clone().try_optional_generic(&"9").unwrap(); let builder = builder.maybe_try_optional_generic(Some(&"10")).unwrap(); let _ignore = builder.clone().try_default_generic(&"11").unwrap(); let builder = builder.maybe_try_default_generic(Some(&"12")).unwrap(); let builder = builder.try_impl_trait(IntoStrRef("morning glory")).unwrap(); assert_debug_eq( builder.call(), expect![[r#" ( ( 2, Some( 3, ), 4, "hello", Some( "littlepip", ), "<3", "morning glory", ), ( 4, Some( 6, ), 8, Some( "10", ), "12", "morning glory", ), )"#]], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(derive(Clone))] fn sut( #[builder(with = |x: u32| x + 1)] required: u32, #[builder(with = |x: u32| x + 1)] optional: Option, #[builder(with = |x: u32| x + 1, default)] default: u32, #[builder(with = |value: &T| value.clone())] generic: T, #[builder(with = |value: &T| value.clone())] optional_generic: Option, #[builder(with = |value: &T| value.clone(), default)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into())] impl_trait: &'static str, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_required: u32, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_optional: Option, #[builder(with = |value: &str| -> ParseIntResult<_> { value.parse() }, default)] try_default: u32, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) })] try_optional_generic: Option, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>| -> Result<_, Infallible> { Ok(value.into()) })] try_impl_trait: &'static str, ) -> impl fmt::Debug { ( ( required, optional, default, generic, optional_generic, default_generic, impl_trait, ), ( try_required, try_optional, try_default, try_optional_generic, try_default_generic, try_impl_trait, ), ) } #[builder(derive(Clone))] fn with_self( &self, #[builder(with = |x: u32| x + 1)] required: u32, #[builder(with = |x: u32| x + 1)] optional: Option, #[builder(with = |x: u32| x + 1, default)] default: u32, #[builder(with = |value: &T| value.clone())] generic: T, #[builder(with = |value: &T| value.clone())] optional_generic: Option, #[builder(with = |value: &T| value.clone(), default)] default_generic: T, #[builder(with = |value: impl Into<&'static str>| value.into())] impl_trait: &'static str, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_required: u32, #[builder(with = |value: &str| -> Result<_, num::ParseIntError> { value.parse() })] try_optional: Option, #[builder(with = |value: &str| -> ParseIntResult<_> { value.parse() }, default)] try_default: u32, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) })] try_optional_generic: Option, #[builder(with = |value: &T| -> Result<_, Infallible> { Ok(value.clone()) }, default)] try_default_generic: T, #[builder(with = |value: impl Into<&'static str>| -> Result<_, Infallible> { Ok(value.into()) })] try_impl_trait: &'static str, ) -> impl fmt::Debug { let _ = self; ( ( required, optional, default, generic, optional_generic, default_generic, impl_trait, ), ( try_required, try_optional, try_default, try_optional_generic, try_default_generic, try_impl_trait, ), ) } } let builder = Sut::sut() .required(1) .optional(2) .default(3) .generic(&"hello"); let _ignore = builder.clone().optional_generic(&"hello you"); let builder = builder.maybe_optional_generic(Some(&"littlepip")); let _ignore = builder.clone().default_generic(&"blackjack"); let builder = builder.maybe_default_generic(Some(&"<3")); let builder = builder .impl_trait(IntoStrRef("morning glory")) .try_required("4") .unwrap(); let _ignore = builder.clone().try_optional("5").unwrap(); let builder = builder.maybe_try_optional(Some("6")).unwrap(); let _ignore = builder.clone().try_default("7").unwrap(); let builder = builder.maybe_try_default(Some("8")).unwrap(); let _ignore = builder.clone().try_optional_generic(&"9").unwrap(); let builder = builder.maybe_try_optional_generic(Some(&"10")).unwrap(); let _ignore = builder.clone().try_default_generic(&"11").unwrap(); let builder = builder.maybe_try_default_generic(Some(&"12")).unwrap(); let builder = builder.try_impl_trait(IntoStrRef("morning glory")).unwrap(); assert_debug_eq( builder.call(), expect![[r#" ( ( 2, Some( 3, ), 4, "hello", Some( "littlepip", ), "<3", "morning glory", ), ( 4, Some( 6, ), 8, Some( "10", ), "12", "morning glory", ), )"#]], ); let builder = Sut .with_self() .required(1) .optional(2) .default(3) .generic(&"hello"); let _ignore = builder.clone().optional_generic(&"hello you"); let builder = builder.maybe_optional_generic(Some(&"littlepip")); let _ignore = builder.clone().default_generic(&"blackjack"); let builder = builder.maybe_default_generic(Some(&"<3")); let builder = builder .impl_trait(IntoStrRef("morning glory")) .try_required("4") .unwrap(); let _ignore = builder.clone().try_optional("5").unwrap(); let builder = builder.maybe_try_optional(Some("6")).unwrap(); let _ignore = builder.clone().try_default("7").unwrap(); let builder = builder.maybe_try_default(Some("8")).unwrap(); let _ignore = builder.clone().try_optional_generic(&"9").unwrap(); let builder = builder.maybe_try_optional_generic(Some(&"10")).unwrap(); let _ignore = builder.clone().try_default_generic(&"11").unwrap(); let builder = builder.maybe_try_default_generic(Some(&"12")).unwrap(); let builder = builder.try_impl_trait(IntoStrRef("morning glory")).unwrap(); assert_debug_eq( builder.call(), expect![[r#" ( ( 2, Some( 3, ), 4, "hello", Some( "littlepip", ), "<3", "morning glory", ), ( 4, Some( 6, ), 8, Some( "10", ), "12", "morning glory", ), )"#]], ); } bon-3.7.1/tests/integration/builder/attr_with/some.rs000064400000000000000000000121331046102023000210430ustar 00000000000000use crate::prelude::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(derive(Clone))] struct Sut { #[builder(required, with = Some)] _required: Option, #[builder(required, with = Some, default = Some(()))] _optional: Option<()>, #[builder(required, with = Some)] _generic: Option, #[builder(required, with = Some, default = None)] _optional_generic: Option, } let builder = Sut::builder(); let builder = builder.required(99); let _ignore = builder.clone().optional(()); let builder = builder.maybe_optional(None); let builder = builder.generic(2); let _ignore = builder.clone().optional_generic(21); let builder = builder.maybe_optional_generic(Some(22)); let sut = builder.build(); assert_debug_eq( &sut, expect![[r#" Sut { _required: Some( 99, ), _optional: Some( (), ), _generic: Some( 2, ), _optional_generic: Some( 22, ), }"#]], ); } #[test] fn test_function() { { #[builder(derive(Clone))] fn sut( #[builder(required, with = Some)] required: Option, #[builder(required, with = Some, default = Some(()))] optional: Option<()>, #[builder(required, with = Some)] generic: Option, #[builder(required, with = Some, default = None)] optional_generic: Option, ) -> impl fmt::Debug { (required, optional, generic, optional_generic) } let builder = sut(); let builder = builder.required(99); let _ignore = builder.clone().optional(()); let builder = builder.maybe_optional(None); let builder = builder.generic(2); let _ignore = builder.clone().optional_generic(21); let builder = builder.maybe_optional_generic(Some(22)); let sut = builder.call(); assert_debug_eq(&sut, expect!["(Some(99), Some(()), Some(2), Some(22))"]); } { #[builder] fn sut( #[builder(required, with = Some)] impl_trait: Option, ) -> impl fmt::Debug { impl_trait } assert_debug_eq( sut().impl_trait("impl Trait").call(), expect![[r#"Some("impl Trait")"#]], ); } } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(derive(Clone))] fn sut( #[builder(required, with = Some)] required: Option, #[builder(required, with = Some, default = Some(()))] optional: Option<()>, #[builder(required, with = Some)] generic: Option, #[builder(required, with = Some, default = None)] optional_generic: Option, ) -> impl fmt::Debug { (required, optional, generic, optional_generic) } #[builder(derive(Clone))] fn with_self( &self, #[builder(required, with = Some)] required: Option, #[builder(required, with = Some, default = Some(()))] optional: Option<()>, #[builder(required, with = Some)] generic: Option, #[builder(required, with = Some, default = None)] optional_generic: Option, ) -> impl fmt::Debug { let _ = self; (required, optional, generic, optional_generic) } #[builder] fn sut_impl_trait( #[builder(required, with = Some)] impl_trait: Option, ) -> impl fmt::Debug { impl_trait } #[builder] fn with_self_impl_trait( &self, #[builder(required, with = Some)] impl_trait: Option, ) -> impl fmt::Debug { let _ = self; impl_trait } } let builder = Sut::sut(); let builder = builder.required(99); let _ignore = builder.clone().optional(()); let builder = builder.maybe_optional(None); let builder = builder.generic(2); let _ignore = builder.clone().optional_generic(21); let builder = builder.maybe_optional_generic(Some(22)); let sut = builder.call(); assert_debug_eq(&sut, expect!["(Some(99), Some(()), Some(2), Some(22))"]); let builder = Sut.with_self(); let builder = builder.required(99); let _ignore = builder.clone().optional(()); let builder = builder.maybe_optional(None); let builder = builder.generic(2); let _ignore = builder.clone().optional_generic(21); let builder = builder.maybe_optional_generic(Some(22)); let sut = builder.call(); assert_debug_eq(&sut, expect!["(Some(99), Some(()), Some(2), Some(22))"]); assert_debug_eq( Sut::sut_impl_trait().impl_trait("impl Trait").call(), expect![[r#"Some("impl Trait")"#]], ); assert_debug_eq( Sut.with_self_impl_trait().impl_trait("impl Trait").call(), expect![[r#"Some("impl Trait")"#]], ); } bon-3.7.1/tests/integration/builder/cfgs.rs000064400000000000000000000067001046102023000170200ustar 00000000000000#![allow(clippy::non_minimal_cfg)] use crate::prelude::*; #[test] fn struct_smoke() { #[derive(Debug, Builder)] struct Sut { #[cfg(all())] #[cfg_attr(all(), allow(dead_code))] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg(any())] arg1: String, } assert_debug_eq( Sut::builder().arg1(true).build(), expect!["Sut { arg1: true }"], ); } #[test] fn struct_with_params() { #[derive(Debug, Builder)] #[cfg_attr(all(), builder(builder_type = OverrideBuilder, finish_fn = finish))] #[cfg_attr(any(), builder(builder_type = Unreachable))] #[allow(dead_code)] struct Sut { #[cfg(all())] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg_attr(all(), builder(default))] arg2: [u8; 4], #[cfg_attr(any(), builder(name = renamed))] arg3: [char; 2], } let builder: OverrideBuilder = Sut::builder(); assert_debug_eq( builder .arg1(true) // arg3 is not renamed .arg3(['a', 'b']) .finish(), expect!["Sut { arg1: true, arg2: [0, 0, 0, 0], arg3: ['a', 'b'] }"], ); } #[test] fn fn_smoke() { #[builder] fn sut( #[cfg(all())] #[cfg_attr(all(), allow(dead_code))] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg(any())] arg1: String, ) -> bool { arg1 } assert!(sut().arg1(true).call()); } #[test] fn fn_with_params() { #[cfg_attr(all(), builder(builder_type = OverrideBuilder))] #[cfg_attr(any(), builder(builder_type = Unreachable))] fn sut( #[cfg(all())] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg_attr(all(), builder(default))] arg2: [u8; 4], #[cfg_attr(any(), builder(name = renamed))] arg3: [char; 2], ) -> (bool, [u8; 4], [char; 2]) { (arg1, arg2, arg3) } let builder: OverrideBuilder = sut(); assert_debug_eq( builder.arg1(true).arg3(['a', 'b']).call(), expect!["(true, [0, 0, 0, 0], ['a', 'b'])"], ); } #[test] fn fn_with_nested_cfgs() { #[builder] fn sut(#[cfg_attr(all(), cfg_attr(not(not(all())), builder(name = renamed)))] arg: u32) -> u32 { arg } assert_eq!(sut().renamed(99).call(), 99); } #[test] fn impl_block() { struct Sut; #[bon::bon] impl Sut { #[builder] fn sut_smoke( #[cfg(all())] #[cfg_attr(all(), allow(dead_code))] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg(any())] arg1: String, ) -> bool { arg1 } #[cfg_attr(all(), builder(builder_type = OverrideBuilder))] #[cfg_attr(any(), builder(builder_type = Unreachable))] fn sut_with_params( #[cfg(all())] arg1: bool, /// doc comment #[cfg(not(all()))] arg1: u32, #[cfg_attr(all(), builder(default))] arg2: [u8; 4], #[cfg_attr(any(), builder(name = renamed))] arg3: [char; 2], ) -> bool { let _ = (arg2, arg3); arg1 } } assert!(Sut::sut_smoke().arg1(true).call()); let builder: OverrideBuilder = Sut::sut_with_params(); assert!(builder.arg1(true).arg3(['a', 'b']).call()); } bon-3.7.1/tests/integration/builder/generics.rs000064400000000000000000000172331046102023000177000ustar 00000000000000use crate::prelude::*; use core::marker::PhantomData; #[test] fn generic_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut<'a, 'b, T, U> { a: &'a str, b: &'b str, c: T, d: U, e: [u8; 3], } let actual = Sut::builder().a("a").b("b").c(42).d("d").e([0; 3]).build(); assert_debug_eq( actual, expect![[r#"Sut { a: "a", b: "b", c: 42, d: "d", e: [0, 0, 0] }"#]], ); } #[test] fn return_type_only_generic_param() { #[builder] fn sut() -> T { T::default() } let _: i32 = sut().call(); } #[test] fn unsized_generics_in_params() { #[builder] fn sut(arg: &T) { let _ = arg; } sut().arg(&42).call(); } #[test] fn unsized_generics_in_return_type() { #[builder] fn sut() -> PhantomData { PhantomData } sut::().call(); } // This is based on the issue https://github.com/rust-lang/rust/issues/129701 #[test] fn assoc_types_work_in_params() { trait Trait { type Assoc; } #[builder] fn sut(_val: T::Assoc) {} impl Trait for () { type Assoc = (); } sut::<()>().val(()).call(); } // This is based on the issue https://github.com/rust-lang/rust/issues/129701 #[test] fn assoc_types_work_in_return_type() { trait Trait { type Assoc; } #[builder] fn sut() -> T::Assoc where T::Assoc: Default, { T::Assoc::default() } impl Trait for () { type Assoc = (); } sut::<()>().call(); } // This is based on the issue https://github.com/elastio/bon/issues/16 #[test] fn self_only_generic_param() { struct Sut<'a, 'b: 'a, T> { bar: Option, str: &'a str, other_ref: &'b (), } #[bon] impl Sut<'_, '_, T> { #[builder] fn new() -> Self { Self { bar: None, str: "littlepip", other_ref: &(), } } } // Make sure `new` method is hidden Sut::::__orig_new(); // Make sure the builder type name matches the type of builder when // `#[builder]` is placed on top of a struct let _: SutBuilder<'_, '_, core::convert::Infallible> = Sut::builder(); let actual = Sut::::builder().build(); assert!(actual.bar.is_none()); assert_eq!(actual.str, "littlepip"); let _: &() = actual.other_ref; } #[test] fn impl_block_with_self_in_const_generics() { #[derive(Default)] struct Sut; impl Sut { const fn val(&self) -> usize { let _ = self; 42 } } #[bon] impl Sut<{ Sut::<3>.val() }> where Self:, { #[builder] fn method(self) -> usize { self.val() } } assert_eq!(Sut::<42>.method().call(), 42); } #[test] fn generics_with_lifetimes() { #[builder] #[allow(clippy::trivially_copy_pass_by_ref)] fn sut(arg: &&&&&T) { let _ = arg; } sut().arg(&&&&&&&&&&42).call(); } // This is based on the issue https://github.com/elastio/bon/issues/106 #[test] fn default_generic_type_params() { #[derive(bon::Builder)] struct Sut { #[builder(skip)] _phantom: ::core::marker::PhantomData<(T, U)>, } let builder: SutBuilder = Sut::builder(); let _: Sut = builder.build(); } #[test] fn const_generics() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut<'a, T, const N: usize> { a: &'a str, b: T, c: [u8; N], } let actual = Sut::builder().a("a").b(42).c([0; 3]).build(); assert_debug_eq(actual, expect![[r#"Sut { a: "a", b: 42, c: [0, 0, 0] }"#]]); } #[test] fn default_generic_const_params() { #[derive(bon::Builder)] struct Sut {} let builder: SutBuilder = Sut::builder(); let _: Sut = builder.build(); } #[test] fn lifetimes_with_bounds() { #[builder] fn sut<'a, 'b: 'a, T: 'a, U: 'b>(arg: &'a T, arg2: &'b U) { let _ = arg; let _ = arg2; } sut().arg(&42).arg2(&42).call(); } // This is based on the issue https://github.com/elastio/bon/issues/206 mod lifetimes_used_only_in_type_predicates { use crate::prelude::*; trait Trait<'a> {} impl Trait<'_> for u32 {} #[test] fn function() { #[builder] fn sut<'a, T: Trait<'a>>(x1: T) -> T { x1 } assert_eq!(sut().x1(2).call(), 2); } #[test] fn generic_method() { struct Sut; #[bon] impl Sut { #[builder] fn method<'a, T: Trait<'a>>(x1: T) -> T { x1 } #[builder] fn with_self<'a, T: Trait<'a>>(&self, x1: T) -> T { let _ = self; x1 } } assert_eq!(Sut::method().x1(2).call(), 2); assert_eq!(Sut.with_self().x1(2).call(), 2); } #[test] fn generic_impl() { struct Sut(T); #[bon] impl<'a, T: Trait<'a>> Sut { #[builder] fn method(x1: T) -> T { x1 } #[builder] fn with_self(&self, x1: T) -> T { let _ = self; x1 } } assert_eq!(Sut::::method().x1(2).call(), 2); assert_eq!(Sut(1).with_self().x1(2).call(), 2); } } mod unused_lifetimes { use crate::prelude::*; #[test] fn function() { #[builder] #[allow(clippy::extra_unused_lifetimes, unused_lifetimes)] fn sut<'a, 'b>() {} sut().call(); } #[test] fn generic_method() { struct Sut; #[bon] impl Sut { #[builder] #[allow(clippy::extra_unused_lifetimes, unused_lifetimes)] fn method<'a, 'b>() {} #[builder] #[allow(clippy::extra_unused_lifetimes, unused_lifetimes)] fn with_self<'a, 'b>(&self) { let _ = self; } } Sut::method().call(); Sut.with_self().call(); } #[test] fn generic_impl() { struct Sut(T); // Interestingly, this code doesn't produce an `unused_lifetimes` warning // because the generated starting functions are inserted into this impl // block and they do use the lifetimes by storing them in the builder. // There isn't a good way to deal with this problem. // // We could generate the starting functions in a separate impl block, but // then it would break the lexical order of methods as they are declared // in this impl block in regards to how they are displayed in `rustdoc`. // // Also, rustdoc permits documentation on the impl block itself, so if // we create a separate impl block for the starting functions, that // would be rendered as separate impl blocks in `rustdoc` as well and we // would need to do something about the docs on the original impl block, // (e.g. copy them to the impl block for starting functions?). // // Anyway, the problem of unused lifetimes lint false-negative is probably // not that serious to justify the complexity of the solution to fix it. #[bon] impl<'a, 'b, T> Sut { #[builder] fn method() {} #[builder] fn with_self(&self) { let _ = self; } } Sut::::method().call(); Sut(1).with_self().call(); } } bon-3.7.1/tests/integration/builder/init_order.rs000064400000000000000000000037241046102023000202370ustar 00000000000000use crate::prelude::*; use core::fmt; // Functions don't support `skip` attributes #[test] fn fn_init_order() { #[builder] fn sut( #[builder(default = 1)] arg1: u32, #[builder(default = 2)] arg2: u32, #[builder(default = [arg1, arg2, 3])] arg3: [u32; 3], ) -> impl fmt::Debug { (arg1, arg2, arg3) } assert_debug_eq(sut().call(), expect!["(1, 2, [1, 2, 3])"]); // Make sure overriding the default works assert_debug_eq(sut().arg1(4).call(), expect!["(4, 2, [4, 2, 3])"]); assert_debug_eq(sut().arg2(5).call(), expect!["(1, 5, [1, 5, 3])"]); assert_debug_eq(sut().arg3([6, 7, 8]).call(), expect!["(1, 2, [6, 7, 8])"]); } #[test] fn struct_init_order() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut { #[builder(skip = 1)] arg1: u32, #[builder(default = 2)] arg2: u32, #[builder(skip = [arg1, arg2, 3])] arg3: [u32; 3], } assert_debug_eq( Sut::builder().build(), expect!["Sut { arg1: 1, arg2: 2, arg3: [1, 2, 3] }"], ); // Make sure overriding the default works assert_debug_eq( Sut::builder().arg2(4).build(), expect!["Sut { arg1: 1, arg2: 4, arg3: [1, 4, 3] }"], ); #[bon] #[allow(clippy::items_after_statements)] impl Sut { #[builder] fn sut( #[builder(default = 1)] arg1: u32, #[builder(default = 2)] arg2: u32, #[builder(default = [arg1, arg2, 3])] arg3: [u32; 3], ) -> (u32, u32, [u32; 3]) { (arg1, arg2, arg3) } } assert_debug_eq(Sut::sut().call(), expect!["(1, 2, [1, 2, 3])"]); // Make sure overriding the default works assert_debug_eq(Sut::sut().arg1(4).call(), expect!["(4, 2, [4, 2, 3])"]); assert_debug_eq(Sut::sut().arg2(5).call(), expect!["(1, 5, [1, 5, 3])"]); assert_debug_eq( Sut::sut().arg3([6, 7, 8]).call(), expect!["(1, 2, [6, 7, 8])"], ); } bon-3.7.1/tests/integration/builder/lints.rs000064400000000000000000000003661046102023000172310ustar 00000000000000use crate::prelude::*; // This used to trigger the `unused_parens` lint #[test] fn func_with_skipped_generic_arg() { #[builder] fn sut(arg: &(impl Clone + Default)) -> impl Clone { arg.clone() } sut().arg(&32).call(); } bon-3.7.1/tests/integration/builder/many_params.rs000064400000000000000000000030371046102023000204050ustar 00000000000000use crate::prelude::*; #[test] fn many_params_fn() { #[builder(builder_type = OverrideBuilder, finish_fn = finish)] fn sut(#[builder(default, name = renamed)] arg1: u32) -> u32 { arg1 } let builder = || -> OverrideBuilder { sut() }; assert_eq!(builder().finish(), 0); assert_eq!(builder().renamed(32).finish(), 32); } #[test] fn many_attrs_struct() { #[derive(Builder)] #[builder(builder_type = OverrideBuilder)] #[builder(finish_fn = finish)] struct Sut { #[builder(default, name = renamed)] arg1: u32, #[builder(default)] #[builder(name = renamed2)] arg2: u32, } let builder = || -> OverrideBuilder { Sut::builder() }; assert_eq!(builder().finish().arg1, 0); assert_eq!(builder().renamed(32).finish().arg1, 32); assert_eq!(builder().renamed2(32).finish().arg2, 32); } #[test] fn many_params_in_one_attr_struct() { #[derive(Builder)] #[builder(builder_type = OverrideBuilder, finish_fn = finish)] #[builder(start_fn = start)] struct Sut {} let builder: OverrideBuilder = Sut::start(); let _ = builder.finish(); } #[test] fn many_params_impl_block() { struct Sut; #[bon] impl Sut { #[builder(builder_type = OverrideBuilder, finish_fn = finish)] fn method(#[builder(default, name = renamed)] arg1: u32) -> u32 { arg1 } } let builder = || -> OverrideBuilder { Sut::method() }; assert_eq!(builder().finish(), 0); assert_eq!(builder().renamed(32).finish(), 32); } bon-3.7.1/tests/integration/builder/mod.rs000064400000000000000000000055701046102023000166610ustar 00000000000000mod attr_bon; mod attr_builder; mod attr_const; mod attr_crate; mod attr_default; mod attr_derive; mod attr_field; mod attr_getter; mod attr_into; mod attr_into_future; mod attr_on; #[cfg(feature = "experimental-overwritable")] mod attr_overwritable; mod attr_required; mod attr_setters; mod attr_skip; mod attr_top_level_start_fn; mod attr_with; mod cfgs; mod generics; mod init_order; mod lints; mod many_params; mod name_conflicts; mod native_fields; mod orig_fn_naming; mod positional_members; mod raw_idents; mod smoke; mod target_feature; mod track_caller; use crate::prelude::*; #[test] fn leading_underscore_is_stripped() { #[builder] fn sut(#[builder(default)] _arg1: bool, _arg2: Option<()>) {} sut().arg1(true).call(); sut().arg2(()).call(); sut().maybe_arg2(Some(())).call(); } #[test] fn lifetime_elision() { #[builder] fn sut(arg: &str, _arg2: usize) -> (&str, &str, [&str; 1]) { (arg, arg, [arg]) } let actual = sut().arg("blackjack").arg2(32).call(); assert_eq!(actual, ("blackjack", "blackjack", ["blackjack"])); } #[cfg(feature = "std")] #[tokio::test] async fn async_fn() { #[builder] async fn sut(arg: u32) -> u32 { std::future::ready(arg).await } let actual = sut().arg(42).call().await; assert_eq!(actual, 42); } #[cfg(feature = "std")] #[tokio::test] async fn async_fn_with_future_arg() { #[builder] async fn sut(fut: Fut) -> Fut::Output { fut.await } fn is_send(_val: impl Send + Sync) {} let fut = sut().fut(std::future::ready(42)).call(); is_send(fut); let actual = sut().fut(async { 42 }).call().await; assert_eq!(actual, 42); } #[test] #[allow(unsafe_code)] fn unsafe_fn() { #[builder] unsafe fn sut(arg: bool) { let _ = arg; } let builder = sut().arg(true); // Only the call method should be unsafe unsafe { builder.call() }; } #[test] fn impl_traits() { #[builder] fn sut( /// Some documentation iterable: impl IntoIterator>, multi_bounds: impl Send + Copy, ) { drop(iterable.into_iter().map(Into::into)); let _ = multi_bounds; let _ = multi_bounds; } sut().iterable([1_u16, 2, 3]).multi_bounds("multi").call(); } #[test] fn const_function() { #[builder] const fn foo(_arg: u32) {} foo().arg(42).call(); } #[test] fn mut_fn_params() { #[builder] fn sut(mut arg1: u32, mut arg2: u32) -> (u32, u32) { arg1 += 1; arg2 += 2; (arg1, arg2) } let actual = sut().arg1(1).arg2(2).call(); assert_eq!(actual, (2, 4)); } // This is based on the issue https://github.com/elastio/bon/issues/12 #[test] fn types_not_implementing_default() { struct DoesNotImplementDefault; #[builder] fn test(_value: Option) {} test().call(); } bon-3.7.1/tests/integration/builder/name_conflicts/builder_state.rs000064400000000000000000000160551046102023000237140ustar 00000000000000mod conflicts_in_bodies { use crate::prelude::*; #[test] #[allow(clippy::items_after_statements)] fn test_struct() { #[derive(Builder, Clone, Copy)] #[allow(dead_code)] struct S { field: u32, } let s = S::builder().field(1).build(); #[derive(Builder, Clone, Copy)] #[allow(dead_code)] struct State { field: S, } let state = State::builder().field(s).build(); #[derive(Builder, Clone, Copy)] #[allow(dead_code)] struct BuilderState { field1: S, field2: State, } let builder_state = BuilderState::builder().field1(s).field2(state).build(); #[derive(Builder, Clone, Copy)] #[allow(dead_code)] #[allow(non_snake_case)] struct S_ { field1: S, field2: State, field3: BuilderState, } let s_ = S_::builder() .field1(s) .field2(state) .field3(builder_state) .build(); #[derive(Builder, Clone, Copy)] #[allow(dead_code)] #[allow(non_snake_case)] struct S__ { field1: S, field2: State, field3: BuilderState, field4: S_, } let _ = S__::builder() .field1(s) .field2(state) .field3(builder_state) .field4(s_) .build(); } #[test] #[allow(clippy::items_after_statements)] fn test_function() { struct S; struct State; struct BuilderState; { #[builder] fn sut(_field: S) {} sut().field(S).call(); } { #[builder] fn sut(_field: S) { let _ = State; } sut().field(S).call(); } { #[builder] fn sut(_field1: S, _field2: State) { let _ = { { ((), BuilderState) } }; } sut().field1(S).field2(State).call(); } { #[builder] fn sut(_field1: S, _field2: State, _field3: BuilderState) {} sut::<()>() .field1(S) .field2(State) .field3(BuilderState) .call(); } { #[builder] fn sut(_field1: S, _field2: State, _field3: BuilderState) {} sut::<(), ()>() .field1(S) .field2(State) .field3(BuilderState) .call(); } } #[test] #[allow(clippy::items_after_statements)] fn test_method() { struct State; struct BuilderState; { struct S; #[bon] impl S { #[builder] fn sut() {} } S::sut().call(); } { struct S; #[bon] impl S { #[builder] fn sut() { let _ = State; } #[builder] fn with_self(&self) { let _ = self; } } S::sut().call(); S.with_self().call(); } { struct S; #[bon] impl S { #[builder] fn sut(_field2: State) {} #[builder] fn with_self(&self) { let _ = self; let _ = { { ((), BuilderState) } }; } } S::sut().field2(State).call(); S.with_self().call(); } { struct S; #[bon] impl S { #[builder] fn sut(_field2: State, _field3: BuilderState) {} } S::sut::<()>().field2(State).field3(BuilderState).call(); } { struct S; #[bon] impl S { #[builder] fn sut(_field2: State, _field3: BuilderState) {} } S::sut::<(), ()>().field2(State).field3(BuilderState).call(); } } } mod conflicts_in_attrs { use crate::prelude::*; struct S; impl S { fn s(&self) -> u32 { let _ = self; 2 } } struct State; impl State { fn state(&self) -> u32 { let _ = self; 2 } } struct BuilderState; impl BuilderState { fn builder_state(&self) -> u32 { let _ = self; 2 } } #[test] fn test_struct() { { #[derive(Builder)] #[allow(dead_code)] struct Sut { #[builder(with = |s: S| s.s())] field: u32, } let _ = Sut::builder().field(S).build(); } { #[derive(Builder)] #[allow(dead_code)] struct Sut { #[builder(with = |s: S| s.s())] field1: u32, #[builder(default = State.state())] field2: u32, } let _ = Sut::builder().field1(S).maybe_field2(Some(43)).build(); } { #[derive(Builder)] #[allow(dead_code)] struct Sut { #[builder(with = |s: S| s.s())] field1: u32, #[builder(default = State.state())] field2: u32, #[builder(skip = BuilderState.builder_state())] field3: u32, } let _ = Sut::builder().field1(S).maybe_field2(Some(43)).build(); } } #[test] fn test_function() { { #[builder] fn sut(#[builder(with = |s: S| s.s())] _field: u32) {} sut().field(S).call(); } { #[builder] fn sut( #[builder(with = |s: S| s.s())] _field1: u32, #[builder(default = State.state())] _field2: u32, ) { } sut().field1(S).maybe_field2(Some(43)).call(); } } #[test] fn test_method() { { struct Sut; #[bon] impl Sut { #[builder] fn sut(#[builder(with = |s: S| s.s())] _field: u32) {} } Sut::sut().field(S).call(); } { struct Sut; #[bon] impl Sut { #[builder] fn sut( #[builder(with = |s: S| s.s())] _field1: u32, #[builder(default = State.state())] _field2: u32, ) { } } Sut::sut().field1(S).maybe_field2(Some(43)).call(); } } } bon-3.7.1/tests/integration/builder/name_conflicts/generics.rs000064400000000000000000000046161046102023000226650ustar 00000000000000mod lifetimes { use crate::prelude::*; #[test] fn test_function() { #[builder] #[allow( single_use_lifetimes, clippy::needless_lifetimes, clippy::trivially_copy_pass_by_ref )] fn sut<'f1, 'f1_, 'f2>( _x1: &u32, _x2: &'f1 u32, _x3: &'f1_ u32, _x4: &'f2 u32, _x5: &u32, ) -> u32 { 32 } sut().x1(&32).x2(&32).x3(&32).x4(&32).x5(&32).call(); } #[test] fn test_method() { #[derive(Default)] #[allow(dead_code)] struct Sut<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>( &'a str, &'b str, &'c str, &'d str, &'e str, &'f str, &'g str, &'h str, ); #[bon] impl<'i1, 'i1_, 'i2, 'f1, 'f1_, 'f2> Sut<'_, '_, 'i1, 'i1_, 'i2, 'f1, 'f1_, 'f2> { #[builder] #[allow(clippy::trivially_copy_pass_by_ref)] fn sut(_val: &u32, _val2: &u32) {} } Sut::sut().val(&32).val2(&32).call(); } } mod impl_trait { use crate::prelude::*; #[test] fn test_function() { struct I1; type I2 = I1; impl I1 { fn get_val(&self) -> u32 { let _ = self; 32 } } { #[builder] fn sut(_arg1: impl Copy) -> u32 { I1.get_val() } sut().arg1(()).call(); } { #[builder] fn sut(_arg1: impl Copy, _arg2: impl Sized) -> u32 { I2 {}.get_val() } sut().arg1(()).arg2(()).call(); } } #[test] fn test_method() { struct I1; type I2 = I1; impl I1 { fn get_val(&self) -> u32 { let _ = self; 32 } } #[bon] impl I1 { #[builder] #[allow(clippy::use_self)] fn sut(_arg1: impl Copy) -> u32 { I1.get_val() } #[builder] fn with_self(&self, _arg1: impl Copy, _arg2: impl Sized) -> u32 { let _ = self; I2 {}.get_val() } } I1::sut().arg1(()).call(); I1.with_self().arg1(()).arg2(()).call(); } } bon-3.7.1/tests/integration/builder/name_conflicts/member_and_type_named_the_same.rs000064400000000000000000000014421046102023000272230ustar 00000000000000//! @Veetaha encountered a bug when working on big changes to `bon` where //! the generic params generated by the macro were named the same as the //! type of the member, and thus leading to a name conflict. This test is //! here to catch any such simple regression. use crate::prelude::*; struct User; #[test] fn member_and_type_named_the_same_fn() { #[builder] fn sut(user: User) { let _ = user; } sut().user(User).call(); } #[test] fn member_and_type_named_the_same_struct() { #[derive(Builder)] struct Sut { #[allow(dead_code)] user: User, } #[bon] impl Sut { #[builder] fn sut(user: User) { let _ = user; } } let _ = Sut::builder().user(User).build(); Sut::sut().user(User).call(); } bon-3.7.1/tests/integration/builder/name_conflicts/member_names_state.rs000064400000000000000000000015531046102023000247150ustar 00000000000000use crate::prelude::*; #[test] fn test_function() { #[builder] fn sut(state: u32, member_state: u32, unset: u32, empty: u32) { let _ = (state, member_state, unset, empty); } sut().state(1).member_state(2).unset(3).empty(4).call(); } #[test] fn test_struct() { #[derive(Builder)] #[allow(dead_code)] struct Sut { state: u32, member_state: u32, unset: u32, empty: u32, } let _ = Sut::builder() .state(1) .member_state(2) .unset(3) .empty(4) .build(); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn sut(state: u32, member_state: u32, unset: u32, empty: u32) { let _ = (state, member_state, unset, empty); } } Sut::sut().state(1).member_state(2).unset(3).empty(4).call(); } bon-3.7.1/tests/integration/builder/name_conflicts/mod.rs000064400000000000000000000001351046102023000216350ustar 00000000000000mod builder_state; mod generics; mod member_and_type_named_the_same; mod member_names_state; bon-3.7.1/tests/integration/builder/native_fields.rs000064400000000000000000000066171046102023000207210ustar 00000000000000// Members marked with `#[builder(start_fn)]` should be available as a private fields in the builder. mod native_start_fn_fields { use crate::prelude::*; #[test] fn test_struct() { #[derive(Builder)] struct Sut { #[builder(start_fn)] #[allow(dead_code)] x1: u32, #[builder(start_fn)] #[allow(dead_code)] x2: bool, } let builder = Sut::builder(1, true); let x1: &u32 = &builder.x1; let x2: &bool = &builder.x2; assert_eq!(*x1, 1); assert!(*x2); } #[test] fn test_function() { #[builder] fn sut(#[builder(start_fn)] x1: u32, #[builder(start_fn)] x2: bool) { let _ = x1; let _ = x2; } let builder = sut(1, true); let x1: &u32 = &builder.x1; let x2: &bool = &builder.x2; assert_eq!(*x1, 1); assert!(*x2); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn method(#[builder(start_fn)] x1: u32, #[builder(start_fn)] x2: bool) { let _ = x1; let _ = x2; } } let builder = Sut::method(1, true); let x1: &u32 = &builder.x1; let x2: &bool = &builder.x2; assert_eq!(*x1, 1); assert!(*x2); } } mod native_receiver_field { use crate::prelude::*; // The `self_receiver` field in the builder should be available as a private field in the builder. #[test] fn native_receiver_field_smoke() { struct Sut { x1: u32, } #[bon] impl Sut { #[builder] fn method(self) { let _ = self; } #[builder] fn method_ref(&self) { let _ = self; } #[builder] fn method_mut(&mut self) { self.x1 += 1; let _ = self; } } { let builder = Sut { x1: 99 }.method(); let receiver: Sut = builder.self_receiver; assert_eq!(receiver.x1, 99); } { let builder = Sut { x1: 99 }.method_ref(); let receiver: &Sut = builder.self_receiver; assert_eq!(receiver.x1, 99); } { let mut sut = Sut { x1: 99 }; let builder = sut.method_mut(); let receiver: &mut Sut = builder.self_receiver; assert_eq!(receiver.x1, 99); } } #[test] fn name_conflict_resolution_for_receiver_field() { struct Sut { x1: u32, } #[bon] impl Sut { #[builder] fn method( &self, #[builder(start_fn)] self_receiver: u32, #[builder(start_fn)] self_receiver_: bool, ) { let _ = self_receiver; let _ = self_receiver_; let _ = self; } } let builder = Sut { x1: 99 }.method(2, true); let self_receiver: &u32 = &builder.self_receiver; let self_receiver_: &bool = &builder.self_receiver_; let self_receiver__: &Sut = builder.self_receiver__; assert_eq!(*self_receiver, 2); assert!(*self_receiver_); assert_eq!(self_receiver__.x1, 99); } } bon-3.7.1/tests/integration/builder/orig_fn_naming.rs000064400000000000000000000025041046102023000210500ustar 00000000000000use crate::prelude::*; use macro_rules_attribute::apply; #[test] fn attributes_see_orig_fn_name() { macro_rules! return_fn_name { ( $(#[$attr:meta])* fn $fn_name:ident() -> $ret:ty {} ) => { $(#[$attr])* fn $fn_name() -> $ret { stringify!($fn_name) } }; } #[builder] #[apply(return_fn_name!)] fn attr_after_builder() -> &'static str {} #[apply(return_fn_name!)] #[builder] fn attr_before_builder() -> &'static str {} struct Sut; #[bon] impl Sut { #[builder] #[apply(return_fn_name!)] fn attr_after_builder() -> &'static str {} #[apply(return_fn_name!)] #[builder] fn attr_before_builder() -> &'static str {} } let actual = attr_after_builder().call(); let expected = expect!["attr_after_builder"]; expected.assert_eq(actual); let actual = attr_before_builder().call(); let expected = expect!["attr_before_builder"]; expected.assert_eq(actual); let actual = Sut::attr_after_builder().call(); let expected = expect!["attr_after_builder"]; expected.assert_eq(actual); let actual = Sut::attr_before_builder().call(); let expected = expect!["attr_before_builder"]; expected.assert_eq(actual); } bon-3.7.1/tests/integration/builder/positional_members.rs000064400000000000000000000254111046102023000217710ustar 00000000000000use crate::prelude::*; struct IntoStrRef<'a>(&'a str); impl<'a> From> for &'a str { fn from(val: IntoStrRef<'a>) -> Self { val.0 } } struct IntoChar(char); impl From for char { fn from(val: IntoChar) -> Self { val.0 } } mod smoke { use super::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] struct Sut { #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_2: char, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, #[builder(finish_fn, into)] finisher_2: &'static str, named: u32, } assert_debug_eq( Sut::builder(true, IntoChar('c'), None) .named(99) .build("1", IntoStrRef("2")), expect![[r#" Sut { starter_1: true, starter_2: 'c', starter_3: None, finisher_1: "1", finisher_2: "2", named: 99, }"#]], ); let _actual = Sut::builder(true, 'c', "str"); } #[test] fn test_function() { #[builder] fn sut( #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_2: char, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, #[builder(finish_fn, into)] finisher_2: &'static str, named: u32, ) -> impl fmt::Debug { ( starter_1, starter_2, starter_3, named, finisher_1, finisher_2, ) } assert_debug_eq( sut(true, IntoChar('c'), None) .named(99) .call("1", IntoStrRef("2")), expect![[r#"(true, 'c', None, 99, "1", "2")"#]], ); let _actual = sut(true, 'c', "str"); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] fn sut( #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_2: char, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, #[builder(finish_fn, into)] finisher_2: &'static str, named: u32, ) -> impl fmt::Debug { ( starter_1, starter_2, starter_3, named, finisher_1, finisher_2, ) } #[builder] fn with_self( &self, #[builder(start_fn)] starter_1: bool, #[builder(finish_fn)] finisher_1: &'static str, named: u32, ) -> impl fmt::Debug { let _ = self; (starter_1, named, finisher_1) } } assert_debug_eq( Sut::sut(true, IntoChar('c'), None) .named(99) .call("1", IntoStrRef("2")), expect![[r#"(true, 'c', None, 99, "1", "2")"#]], ); let _actual = Sut::sut(true, 'c', "str"); assert_debug_eq( Sut.with_self(true).named(99).call("1"), expect![[r#"(true, 99, "1")"#]], ); } } mod attr_on { use super::*; use core::fmt; #[test] fn test_struct() { #[derive(Debug, Builder)] #[builder(on(&str, into))] #[allow(dead_code)] struct Sut { #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, named: u32, } assert_debug_eq( Sut::builder(true, "Roseluck") .named(99) .build(IntoStrRef("Daisy")), expect![[r#" Sut { starter_1: true, starter_3: Some( "Roseluck", ), finisher_1: "Daisy", named: 99, }"#]], ); } #[test] fn test_function() { #[builder(on(&str, into))] fn sut( #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, named: u32, ) -> impl fmt::Debug { (starter_1, starter_3, finisher_1, named) } assert_debug_eq( sut(true, "Roseluck").named(99).call(IntoStrRef("Daisy")), expect![[r#"(true, Some("Roseluck"), "Daisy", 99)"#]], ); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder(on(&str, into))] fn sut( #[builder(start_fn)] starter_1: bool, #[builder(start_fn, into)] starter_3: Option<&'static str>, #[builder(finish_fn)] finisher_1: &'static str, named: u32, ) -> impl fmt::Debug { (starter_1, starter_3, finisher_1, named) } #[builder(on(&str, into))] fn with_self( &self, #[builder(start_fn)] starter_1: bool, #[builder(finish_fn)] finisher_1: &'static str, named: u32, ) -> impl fmt::Debug { let _ = self; (starter_1, finisher_1, named) } } assert_debug_eq( Sut::sut(true, "Roseluck") .named(99) .call(IntoStrRef("Daisy")), expect![[r#"(true, Some("Roseluck"), "Daisy", 99)"#]], ); assert_debug_eq( Sut.with_self(true).named(99).call("Daisy"), expect![[r#"(true, "Daisy", 99)"#]], ); } } mod generics { use super::*; use core::fmt::Debug; #[test] fn test_struct() { #[derive(Debug, Builder)] #[allow(dead_code)] #[builder(derive(Debug, Clone))] struct Sut<'a, 'b, T, U, A, const N1: usize, const N2: usize> where T: PartialEq + Debug + Clone, Self: Sized + 'b, U: Debug + Clone, A: Debug + Clone, { #[builder(start_fn)] starter: &'a [T; N1], #[builder(finish_fn, into)] finisher: [&'b U; N2], named: A, } let builder = Sut::builder(&[1_u32, 2, 3]); assert_debug_eq( builder.clone(), expect!["SutBuilder { starter: [1, 2, 3] }"], ); assert_debug_eq( builder.named(99).build([&false]), expect!["Sut { starter: [1, 2, 3], finisher: [false], named: 99 }"], ); } #[test] fn test_function() { #[builder(derive(Debug, Clone))] fn sut<'a, 'b, T, U, A, const N1: usize, const N2: usize>( #[builder(start_fn)] starter: &'a [T; N1], #[builder(finish_fn, into)] finisher: [&'b U; N2], named: A, ) -> (&'a [T; N1], [&'b U; N2], A) where T: PartialEq + Debug + Clone, U: Debug + Clone, A: Debug + Clone, { (starter, finisher, named) } let builder = sut(&[1_u32, 2, 3]); assert_debug_eq( builder.clone(), expect!["SutBuilder { starter: [1, 2, 3] }"], ); assert_debug_eq( builder.named(99).call([&false]), expect!["([1, 2, 3], [false], 99)"], ); } #[test] fn test_impl_trait_free_fn() { #[builder(derive(Clone, Debug))] fn sut( #[builder(start_fn)] starter: impl IntoIterator + Clone + Debug, #[builder(finish_fn)] _finisher: impl Debug + Clone + 'static, ) -> u32 { starter.into_iter().sum() } let builder = sut([1, 2, 3]); assert_debug_eq( builder.clone(), expect!["SutBuilder { starter: [1, 2, 3] }"], ); assert_eq!(builder.call(()), 6); } #[test] fn test_method() { #[derive(Debug, Clone)] struct Sut; #[bon] impl Sut { #[builder(derive(Debug, Clone))] fn sut<'a, 'b, T, U, A, const N1: usize, const N2: usize>( #[builder(start_fn)] starter_1: &'a [T; N1], #[builder(finish_fn, into)] starter_2: [&'b U; N2], named: A, ) -> (&'a [T; N1], [&'b U; N2], A) where T: PartialEq + Debug + Clone, U: Debug + Clone, A: Debug + Clone, { (starter_1, starter_2, named) } #[builder(derive(Debug, Clone))] fn with_self<'a, 'b, T, U, A, const N1: usize, const N2: usize>( &self, #[builder(start_fn)] starter_1: &'a [T; N1], #[builder(finish_fn, into)] starter_2: [&'b U; N2], named: A, ) -> (&'a [T; N1], [&'b U; N2], A) where T: PartialEq + Debug + Clone, U: Debug + Clone, A: Debug + Clone, { let _ = self; (starter_1, starter_2, named) } } let builder = Sut::sut(&[1_u32, 2, 3]); assert_debug_eq( builder.clone(), expect!["SutSutBuilder { starter_1: [1, 2, 3] }"], ); assert_debug_eq( builder.named(99).call([&false]), expect!["([1, 2, 3], [false], 99)"], ); assert_debug_eq( Sut.with_self(&[1_u32, 2, 3]).named(99).call([&false]), expect!["([1, 2, 3], [false], 99)"], ); } } mod mut_params { use crate::prelude::*; #[test] fn test_function() { #[builder] fn sut(#[builder(start_fn)] mut x1: u32, #[builder(finish_fn)] mut x2: u32) { x1 += 1; x2 += 1; let _ = (x1, x2); } sut(1).call(2); } #[test] fn test_method() { struct Sut; #[bon] impl Sut { #[builder] #[allow(clippy::needless_pass_by_ref_mut)] fn sut(&mut self, #[builder(start_fn)] mut x1: u32, #[builder(finish_fn)] mut x2: u32) { let _ = self; x1 += 1; x2 += 1; let _ = (x1, x2); } } Sut.sut(1).call(2); } } bon-3.7.1/tests/integration/builder/raw_idents.rs000064400000000000000000000051251046102023000202350ustar 00000000000000//! This is based on the issue use crate::prelude::*; #[test] #[allow(non_camel_case_types)] fn test_struct() { { #[derive(Builder)] struct r#Type { r#type: u32, #[builder(name = r#while)] other: u32, } let actual = r#Type::builder().r#type(42).r#while(100).build(); assert_eq!(actual.r#type, 42); assert_eq!(actual.other, 100); #[derive(Builder)] #[builder(builder_type = r#type, state_mod = r#mod)] #[allow(clippy::items_after_statements, dead_code)] struct Sut { r#while: u32, } let _actual: r#type = Sut::builder(); let _actual: r#type = Sut::builder().r#while(32); } // This is based on the issue https://github.com/elastio/bon/issues/174 { { #[derive(Builder)] struct Sut { r#type: Option, } let value = Sut::builder().maybe_type(Some(2)).build(); assert_eq!(value.r#type, Some(2)); } { #[derive(Builder)] struct Sut { #[builder(default)] r#type: u32, } let value = Sut::builder().maybe_type(Some(2)).build(); assert_eq!(value.r#type, 2); } } } #[test] #[allow(non_camel_case_types)] fn test_fn() { { #[builder] fn r#type(r#type: u32, #[builder(name = r#while)] other: u32) { let _ = (r#type, other); } r#type().r#type(42).r#while(100).call(); } { #[builder(builder_type = r#type, state_mod = r#mod)] fn sut() {} let _: r#type = sut(); } // This is based on the issue https://github.com/elastio/bon/issues/174 { { #[builder] fn sut(r#type: Option) -> Option { r#type } let value = sut().maybe_type(Some(2)).call(); assert_eq!(value, Some(2)); } { #[builder] fn sut(#[builder(default)] r#type: u32) -> u32 { r#type } let value = sut().maybe_type(Some(2)).call(); assert_eq!(value, 2); } } } // This is based on the issue https://github.com/elastio/bon/issues/237 #[test] fn test_self_underscore_bug_237() { #[derive(Builder)] struct Sut { self_: u32, } let builder: SutBuilder = Sut::builder().self_(42); assert_eq!(builder.build().self_, 42); } bon-3.7.1/tests/integration/builder/smoke.rs000064400000000000000000000044051046102023000172140ustar 00000000000000use crate::prelude::*; #[cfg(feature = "alloc")] #[test] fn smoke_fn() { /// Function-level docs /// multiline. #[builder] fn sut( /// ### Documentation /// **Docs** for arg1. /// /// Multiline with `code` *examples* __even__! /// /// ``` /// let wow_such_code = true; /// println!("Code is so lovely! {wow_such_code}"); /// ``` /// /// - List item 1 /// - List item 2 arg1: bool, /// Docs for arg2 arg2: &'_ str, arg3: String, arg4: u32, /// Docs on optional parameter arg5: Option, arg6: Option<&str>, arg7: Vec, arg8: (u32, &[bool]), ) -> String { drop((arg1, arg2, arg4, arg5, arg6, arg7, arg8)); arg3 } let actual = sut() .arg1(true) .arg2("arg2") .arg3("arg3".to_owned()) .arg4(1) .arg7(vec!["arg7".to_owned()]) .arg8((1, &[true])) .call(); assert_eq!(actual, "arg3"); } #[test] fn smoke_struct() { /// Docs on struct itself. /// Multiline. #[allow(dead_code)] #[derive(Debug, Builder)] pub(crate) struct Sut<'a> { /// Docs on bool field. /// Multiline. bool: bool, str_ref: &'a str, #[builder(default)] u32: u32, /// Docs on option field. /// Multiline. option_u32: Option, option_str_ref: Option<&'a str>, tuple: (u32, &'a [bool]), #[builder(skip)] skipped: u32, } let actual = Sut::builder() .bool(true) .str_ref("str_ref") .maybe_option_u32(Some(42)) .option_str_ref("value") .tuple((42, &[true, false])) .build(); let expected = expect![[r#" Sut { bool: true, str_ref: "str_ref", u32: 0, option_u32: Some( 42, ), option_str_ref: Some( "value", ), tuple: ( 42, [ true, false, ], ), skipped: 0, } "#]]; expected.assert_debug_eq(&actual); } bon-3.7.1/tests/integration/builder/target_feature.rs000064400000000000000000000020701046102023000210730ustar 00000000000000#[cfg(target_arch = "x86_64")] #[rustversion::since(1.86.0)] mod msrv_1_86 { #![allow(dead_code)] use crate::prelude::*; #[test] fn target_feature_function() { #[builder] #[target_feature(enable = "avx2")] fn building_but_wider(_x: [u8; 32], _y: [u32; 8]) {} #[target_feature(enable = "avx2")] #[allow(unsafe_code)] unsafe fn wider() { building_but_wider().x([0; 32]).y([1; 8]).call(); } } #[test] fn target_feature_method() { #[repr(C, align(32))] struct Brick([u8; 32]); struct Senti; #[bon] impl Senti { #[builder(finish_fn = yatta_but_wide)] #[target_feature(enable = "avx2")] fn new(brick: Brick) -> Self { let Brick(_) = brick; Self } #[target_feature(enable = "avx2")] #[allow(unsafe_code)] unsafe fn briiick() { Self::builder().brick(Brick([0; 32])).yatta_but_wide(); } } } } bon-3.7.1/tests/integration/builder/track_caller.rs000064400000000000000000000023471046102023000205270ustar 00000000000000use crate::prelude::*; use core::panic::Location; #[derive(Debug)] #[allow(dead_code)] struct LineCol { line: u32, col: u32, } impl From<&'_ Location<'_>> for LineCol { fn from(value: &'_ Location<'_>) -> Self { Self { line: value.line(), col: value.column(), } } } #[test] fn track_caller_function() { #[builder] #[track_caller] fn dont_brick(_x: u32) -> LineCol { Location::caller().into() } let location = dont_brick().x(10).call(); assert_debug_eq(location, expect!["LineCol { line: 28, col: 39 }"]); #[track_caller] #[builder] fn dont_brick_2(_x: u32) -> LineCol { Location::caller().into() } let location = dont_brick_2().x(10).call(); assert_debug_eq(location, expect!["LineCol { line: 37, col: 41 }"]); } #[test] fn track_caller_method() { struct Brick; struct Senti; #[bon] impl Senti { #[builder(finish_fn = yatta)] #[track_caller] fn new(brick: Brick) -> LineCol { let Brick = brick; Location::caller().into() } } let yatta = Senti::builder().brick(Brick).yatta(); assert_debug_eq(yatta, expect!["LineCol { line: 54, col: 47 }"]); } bon-3.7.1/tests/integration/main.rs000064400000000000000000000031461046102023000153750ustar 00000000000000#![cfg_attr(not(feature = "std"), no_std)] #![allow( clippy::redundant_pub_crate, clippy::missing_const_for_fn, clippy::needless_pass_by_value, clippy::too_many_lines, // `expect_test` sometimes adds redundant hashes, we just have to live with that clippy::needless_raw_string_hashes, non_local_definitions, missing_docs, impl_trait_overcaptures, )] // This catches the problem of `clippy::empty_enum` lint triggering. // This lint is enabled only when `feature(never_type)` is enabled. #![cfg_attr(nightly, allow(unstable_features), feature(never_type))] #[cfg(feature = "alloc")] extern crate alloc; mod prelude { #[cfg(feature = "alloc")] pub(crate) use alloc::{ borrow::ToOwned, boxed::Box, collections::BTreeSet, format, rc::Rc, string::String, sync::Arc, vec, vec::Vec, }; pub(crate) use super::assert_debug_eq; pub(crate) use bon::{bon, builder, Builder}; pub(crate) use expect_test::expect; } mod builder; mod ui; use expect_test::Expect; /// Approximate number of characters that can fit on a single screen const COMMON_SCREEN_CHARS_WIDTH: usize = 60; #[track_caller] fn assert_debug_eq(actual: impl core::fmt::Debug, expected: Expect) { extern crate alloc; let snapshot = || { let terse = alloc::format!("{actual:?}"); let width = match terse.lines().map(str::len).max() { Some(width) => width, _ => return terse, }; if width < COMMON_SCREEN_CHARS_WIDTH { return terse; } alloc::format!("{actual:#?}") }; expected.assert_eq(&snapshot()); } bon-3.7.1/tests/integration/ui/compile_fail/attr_bon.rs000064400000000000000000000021421046102023000213140ustar 00000000000000use bon::bon; struct InvalidAttrsForBonMacro; #[bon(attrs)] impl InvalidAttrsForBonMacro { #[builder] fn sut() {} } struct BuilderAttrOnReceiver; #[bon] impl BuilderAttrOnReceiver { #[builder] fn sut(#[builder] &self) {} } struct NoBuilderMethods; #[bon] impl NoBuilderMethods { fn not_builder1() {} fn not_builder2(&self) {} const NOT_BUILDER: () = (); } struct BuilderLikeMethodAttribute; #[bon] impl BuilderLikeMethodAttribute { fn not_builder() {} #[::foo::builder] fn builder_like() {} } struct ActiveBuilderInsideImplWithSelf; #[bon] impl ActiveBuilderInsideImplWithSelf { #[bon::builder] fn active_bon_with_self(&self) {} } struct ActiveBuilderInsideImplClueless; #[bon] impl ActiveBuilderInsideImplClueless { // The `builder` attribute is "clueless" here because nothing tells it that // it is inside of an impl block, so it silently "succeeds" to generate // a builder method, but it produces a bunch of errors that items can't // be defined inside of an impl block. #[bon::builder] fn active_bon_clueless() {} } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_bon.stderr000064400000000000000000000124731046102023000222030ustar 00000000000000error: Unknown field: `attrs` --> tests/integration/ui/compile_fail/attr_bon.rs:5:7 | 5 | #[bon(attrs)] | ^^^^^ error: #[builder] attributes on the receiver are not supported --> tests/integration/ui/compile_fail/attr_bon.rs:16:12 | 16 | fn sut(#[builder] &self) {} | ^ error: there are no #[builder] functions in the impl block, so there is no need for a #[bon] attribute here --> tests/integration/ui/compile_fail/attr_bon.rs:21:1 | 21 | #[bon] | ^^^^^^ | = note: this error originates in the attribute macro `bon` (in Nightly builds, run with -Z macro-backtrace for more info) error: #[bon] macro found no #[builder] attributes in the impl block, but it looks like this attribute was meant for #[bon]; note that #[bon] expects a bare #[builder] attribute without the `foo::` prefix; #[builder] acts as a simple config attribute for the active #[bon] attribute in impl blocks; more info on inert vs active attributes: https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes --> tests/integration/ui/compile_fail/attr_bon.rs:35:7 | 35 | #[::foo::builder] | ^ error: #[bon] macro found no #[builder] attributes in the impl block, but it looks like this attribute was meant for #[bon]; note that #[bon] expects a bare #[builder] attribute without the `bon::` prefix; #[builder] acts as a simple config attribute for the active #[bon] attribute in impl blocks; more info on inert vs active attributes: https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes --> tests/integration/ui/compile_fail/attr_bon.rs:43:7 | 43 | #[bon::builder] | ^^^ error: this function contains a `self` parameter which likely means the builder attribute was used inside of an impl block; the impl block needs to be annotated with the #[bon] attribute and the builder attribute must be spelled as #[builder] without any additional path prefix, since it's used as a simple inert config attribute for #[bon] in impl blocks; more info on inert vs active attributes: https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes --> tests/integration/ui/compile_fail/attr_bon.rs:44:30 | 44 | fn active_bon_with_self(&self) {} | ^^^^ error: #[bon] macro found no #[builder] attributes in the impl block, but it looks like this attribute was meant for #[bon]; note that #[bon] expects a bare #[builder] attribute without the `bon::` prefix; #[builder] acts as a simple config attribute for the active #[bon] attribute in impl blocks; more info on inert vs active attributes: https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes --> tests/integration/ui/compile_fail/attr_bon.rs:55:7 | 55 | #[bon::builder] | ^^^ error: struct is not supported in `trait`s or `impl`s --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ | = help: consider moving the struct out to a nearby module scope = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: implementation is not supported in `trait`s or `impl`s --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ | = help: consider moving the implementation out to a nearby module scope = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: module is not supported in `trait`s or `impl`s --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ | = help: consider moving the module out to a nearby module scope = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: `const` items in this context need a name --> tests/integration/ui/compile_fail/attr_bon.rs:41:1 | 41 | #[bon] | ^^^^^^ `_` is not a valid name for this `const` item | = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: `const` items in this context need a name --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ `_` is not a valid name for this `const` item | = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: could not find `foo` in the list of imported crates --> tests/integration/ui/compile_fail/attr_bon.rs:35:9 | 35 | #[::foo::builder] | ^^^ could not find `foo` in the list of imported crates error[E0412]: cannot find type `ActiveBonCluelessBuilder` in this scope --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ not found in this scope | = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0422]: cannot find struct, variant or union type `ActiveBonCluelessBuilder` in this scope --> tests/integration/ui/compile_fail/attr_bon.rs:49:1 | 49 | #[bon] | ^^^^^^ not found in this scope | = note: this error originates in the attribute macro `bon::builder` (in Nightly builds, run with -Z macro-backtrace for more info) bon-3.7.1/tests/integration/ui/compile_fail/attr_builder.rs000064400000000000000000000025431046102023000221710ustar 00000000000000use bon::{bon, builder, Builder}; #[derive(Builder)] #[builder] struct EmptyTopLevelBuilderAttr {} #[derive(Builder)] #[builder()] struct EmptyTopLevelBuilderAttrWithParens {} #[derive(Builder)] struct EmptyMemberLevelBuilderAttr { #[builder] x: u32, } #[derive(Builder)] struct EmptyMemberLevelBuilderAttrWithParens { #[builder()] x: u32, } #[builder] fn fn_empty_member_level_builder_attr(#[builder] _x: u32) {} #[builder] fn fn_empty_member_level_builder_attr_with_parens(#[builder()] _x: u32) {} struct EmptyBuilderAttr; #[bon] impl EmptyBuilderAttr { #[builder] fn empty_member_level_builder_attr(#[builder] _x: u32) {} } #[bon] impl EmptyBuilderAttr { #[builder] fn empty_member_level_builder_attr_with_parens(#[builder()] _x: u32) {} } #[bon] impl EmptyBuilderAttr { #[builder()] fn empty_top_level_builder_attr_with_parens() {} } #[builder] struct LegacyBuilderProcMacroAttrOnStruct {} #[builder] enum EnumsAreUnsupported {} fn main() {} #[builder] #[must_use] #[must_use] fn double_must_use() {} #[builder] fn destructuring1((x, y): (u32, u32)) { let _ = x; let _ = y; } #[builder] fn destructuring2((_, _): (u32, u32)) {} #[builder] #[track_caller] #[track_caller] fn double_track_caller() {} #[builder] #[target_feature(enable = "")] #[target_feature(enable = "")] fn double_invalid_target_feature() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_builder.stderr000064400000000000000000000100211046102023000230360ustar 00000000000000error: this empty `#[builder]` attribute is redundant; remove it --> tests/integration/ui/compile_fail/attr_builder.rs:4:3 | 4 | #[builder] | ^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_builder.rs:8:10 | 8 | #[builder()] | ^^ error: this empty `builder` attribute is unexpected; remove it or pass parameters in parentheses: `builder(...)` --> tests/integration/ui/compile_fail/attr_builder.rs:13:7 | 13 | #[builder] | ^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_builder.rs:19:14 | 19 | #[builder()] | ^^ error: this empty `builder` attribute is unexpected; remove it or pass parameters in parentheses: `builder(...)` --> tests/integration/ui/compile_fail/attr_builder.rs:24:41 | 24 | fn fn_empty_member_level_builder_attr(#[builder] _x: u32) {} | ^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_builder.rs:27:60 | 27 | fn fn_empty_member_level_builder_attr_with_parens(#[builder()] _x: u32) {} | ^^ error: this empty `builder` attribute is unexpected; remove it or pass parameters in parentheses: `builder(...)` --> tests/integration/ui/compile_fail/attr_builder.rs:34:42 | 34 | fn empty_member_level_builder_attr(#[builder] _x: u32) {} | ^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_builder.rs:40:61 | 40 | fn empty_member_level_builder_attr_with_parens(#[builder()] _x: u32) {} | ^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_builder.rs:45:14 | 45 | #[builder()] | ^^ error: to generate a builder for a struct, use `#[derive(bon::Builder)]` instead; `#[bon::builder]` syntax is supported only for functions starting with bon v3 --> tests/integration/ui/compile_fail/attr_builder.rs:50:1 | 50 | struct LegacyBuilderProcMacroAttrOnStruct {} | ^^^^^^ error: only `fn` items are supported by the `#[bon::builder]` attribute --> tests/integration/ui/compile_fail/attr_builder.rs:52:1 | 52 | #[builder] | ^^^^^^^^^^ | = note: this error originates in the attribute macro `builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: found multiple #[must_use], but bon only works with exactly one or zero. --> tests/integration/ui/compile_fail/attr_builder.rs:59:1 | 59 | #[must_use] | ^ error: use a simple `identifier: type` syntax for the function argument; destructuring patterns in arguments aren't supported by the `#[builder]` --> tests/integration/ui/compile_fail/attr_builder.rs:63:19 | 63 | fn destructuring1((x, y): (u32, u32)) { | ^^^^^^ error: use a simple `identifier: type` syntax for the function argument; destructuring patterns in arguments aren't supported by the `#[builder]` --> tests/integration/ui/compile_fail/attr_builder.rs:69:19 | 69 | fn destructuring2((_, _): (u32, u32)) {} | ^^^^^^ error: found multiple #[track_caller], but bon only works with exactly one or zero. --> tests/integration/ui/compile_fail/attr_builder.rs:73:1 | 73 | #[track_caller] | ^ error: found multiple #[target_feature], but bon only works with exactly one or zero. --> tests/integration/ui/compile_fail/attr_builder.rs:77:1 | 77 | #[target_feature(enable = "")] | ^ error: the feature named `` is not valid for this target --> tests/integration/ui/compile_fail/attr_builder.rs:76:18 | 76 | #[target_feature(enable = "")] | ^^^^^^^^^^^ `` is not valid for this target error: the feature named `` is not valid for this target --> tests/integration/ui/compile_fail/attr_builder.rs:77:18 | 77 | #[target_feature(enable = "")] | ^^^^^^^^^^^ `` is not valid for this target bon-3.7.1/tests/integration/ui/compile_fail/attr_const.rs000064400000000000000000000017311046102023000216670ustar 00000000000000use bon::{bon, builder, Builder}; #[builder(const)] fn const_on_non_const_fn() {} struct Sut; #[bon] impl Sut { #[builder(const)] fn const_on_non_const_fn() {} } #[derive(Builder)] #[builder(const)] struct IncompatibleDefault { #[builder(default)] x1: u32, } #[derive(Builder)] #[builder(const)] struct IncompatibleSkip { #[builder(skip)] x1: u32, } #[derive(Builder)] #[builder(const)] struct IncompatibleField { #[builder(field)] x1: u32, } #[derive(Builder)] #[builder(const)] struct IncompatibleInto { #[builder(into)] x1: u32, } #[derive(Builder)] #[builder(const)] struct IncompatibleFromIter1 { #[builder(with = FromIterator::from_iter)] x1: Vec, } #[derive(Builder)] #[builder(const)] struct IncompatibleFromIter2 { #[builder(with = <_>::from_iter)] x1: Vec, } #[derive(Builder)] #[builder(const)] struct IncompatibleDefaultExpression { #[builder(default = return 1)] x1: u32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_const.stderr000064400000000000000000000046161046102023000225530ustar 00000000000000error: #[builder(const)] requires the underlying function to be marked as `const fn` --> tests/integration/ui/compile_fail/attr_const.rs:3:11 | 3 | #[builder(const)] | ^^^^^ error: #[builder(const)] requires the underlying function to be marked as `const fn` --> tests/integration/ui/compile_fail/attr_const.rs:10:15 | 10 | #[builder(const)] | ^^^^^ error: bare #[builder(default)] is incompatible with #[builder(const)] because Default::default() can not be called in const context; provide an explicit value via #[builder(default = ...)] instead --> tests/integration/ui/compile_fail/attr_const.rs:17:15 | 17 | #[builder(default)] | ^^^^^^^ error: bare #[builder(skip)] is incompatible with #[builder(const)] because Default::default() can not be called in const context; provide an explicit value via #[builder(skip = ...)] instead --> tests/integration/ui/compile_fail/attr_const.rs:24:15 | 24 | #[builder(skip)] | ^^^^ error: bare #[builder(field)] is incompatible with #[builder(const)] because Default::default() can not be called in const context; provide an explicit value via #[builder(field = ...)] instead --> tests/integration/ui/compile_fail/attr_const.rs:31:15 | 31 | #[builder(field)] | ^^^^^ error: #[builder(into)] is incompatible with #[builder(const)] because Into::into() can not be called in const context --> tests/integration/ui/compile_fail/attr_const.rs:38:15 | 38 | #[builder(into)] | ^^^^ error: from_iter is incompatible with #[builder(const)] because FromIterator::from_iter() can not be called in const context --> tests/integration/ui/compile_fail/attr_const.rs:45:22 | 45 | #[builder(with = FromIterator::from_iter)] | ^^^^^^^^^^^^ error: from_iter is incompatible with #[builder(const)] because FromIterator::from_iter() can not be called in const context --> tests/integration/ui/compile_fail/attr_const.rs:52:22 | 52 | #[builder(with = <_>::from_iter)] | ^ error: this kind of expression is not allowed in this position; if you need to use a complex expression such as this then move it into a separate `const fn` and call that function here instead --> tests/integration/ui/compile_fail/attr_const.rs:59:25 | 59 | #[builder(default = return 1)] | ^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_crate.rs000064400000000000000000000013721046102023000216400ustar 00000000000000use bon::{bon, builder, Builder}; #[derive(Builder)] #[builder(crate = self::bon)] struct Relative1 {} #[derive(Builder)] #[builder(crate = super::bon)] struct Relative2 {} #[derive(Builder)] #[builder(crate = bon)] struct Relative3 {} #[builder(crate = self::bon)] fn relative_1() {} #[builder(crate = super::bon)] fn relative_2() {} #[builder(crate = bon)] fn relative_3() {} struct CrateAttrInMethod; #[bon] impl CrateAttrInMethod { #[builder(crate = ::bon)] fn method() {} } struct Relative; #[bon(crate = self::bon)] impl Relative { #[builder] fn method1() {} } #[bon(crate = super::bon)] impl Relative { #[builder] fn method2() {} } #[bon(crate = bon)] impl Relative { #[builder] fn method3() {} } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_crate.stderr000064400000000000000000000070221046102023000225150ustar 00000000000000error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:4:19 | 4 | #[builder(crate = self::bon)] | ^^^^ error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:8:19 | 8 | #[builder(crate = super::bon)] | ^^^^^ error: path must be absolute; if you want to refer to a reexport from an external crate then add leading colons like `::bon`; if the path leads to a module in the current crate, then specify the absolute path with `crate` like `crate::reexport::path::bon` or `$crate::reexport::path::bon` (if within a macro) --> tests/integration/ui/compile_fail/attr_crate.rs:12:19 | 12 | #[builder(crate = bon)] | ^^^ error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:15:19 | 15 | #[builder(crate = self::bon)] | ^^^^ error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:18:19 | 18 | #[builder(crate = super::bon)] | ^^^^^ error: path must be absolute; if you want to refer to a reexport from an external crate then add leading colons like `::bon`; if the path leads to a module in the current crate, then specify the absolute path with `crate` like `crate::reexport::path::bon` or `$crate::reexport::path::bon` (if within a macro) --> tests/integration/ui/compile_fail/attr_crate.rs:21:19 | 21 | #[builder(crate = bon)] | ^^^ error: `crate` parameter should be specified via `#[bon(crate = path::to::bon)]` when impl block syntax is used; no need to specify it in the method's `#[builder]` attribute --> tests/integration/ui/compile_fail/attr_crate.rs:28:23 | 28 | #[builder(crate = ::bon)] | ^ error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:34:15 | 34 | #[bon(crate = self::bon)] | ^^^^ error: path must not be relative; specify the path that starts with `crate::` instead; if you want to refer to a reexport from an external crate then use leading colons like `::crate_name::reexport::path::bon` --> tests/integration/ui/compile_fail/attr_crate.rs:40:15 | 40 | #[bon(crate = super::bon)] | ^^^^^ error: path must be absolute; if you want to refer to a reexport from an external crate then add leading colons like `::bon`; if the path leads to a module in the current crate, then specify the absolute path with `crate` like `crate::reexport::path::bon` or `$crate::reexport::path::bon` (if within a macro) --> tests/integration/ui/compile_fail/attr_crate.rs:46:15 | 46 | #[bon(crate = bon)] | ^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_derive.rs000064400000000000000000000051161046102023000220200ustar 00000000000000use bon::{bon, builder, Builder}; struct NoTraitImpls; #[derive(Builder)] #[builder(derive(Clone, Debug))] struct StructContainsNonTrait { #[builder(start_fn)] no_impl_start_fn: NoTraitImpls, no_impls_required: NoTraitImpls, no_impl_optional: Option, #[builder(default = NoTraitImpls)] no_impl_optional_2: NoTraitImpls, x: u32, } #[builder(derive(Clone, Debug))] fn fn_contains_non_trait( #[builder(start_fn)] // _no_impl_start_fn: NoTraitImpls, _no_impls_required: NoTraitImpls, _no_impl_optional: Option, #[builder(default = NoTraitImpls)] // _no_impl_optional_2: NoTraitImpls, _x: u32, ) { } #[bon] impl StructContainsNonTrait { #[builder(derive(Clone, Debug))] fn method_contains_non_trait( self, #[builder(start_fn)] _no_impl_start_fn: NoTraitImpls, _no_impls_required: NoTraitImpls, _no_impl_optional: Option, #[builder(default = NoTraitImpls)] // _no_impl_optional_2: NoTraitImpls, _x: u32, ) { } } #[derive(Builder)] #[builder(derive())] struct EmptyDerives {} #[derive(Builder)] #[builder(derive(Clone()))] struct EmptyParamsForDerive {} #[derive(Builder)] #[builder(derive(Clone(bounds {})))] struct WrongDelimInBounds {} #[builder(derive(Into))] fn derive_into_with_finish_fn_member(#[builder(finish_fn)] _finish_fn: fn() -> u32) -> u32 { 99 } #[builder(derive(Into))] fn function_with_unit_return_type() {} #[builder(derive(Into))] async fn async_function() -> u32 { 99 } #[builder(derive(Into))] unsafe fn unsafe_function() -> u32 { 99 } #[builder(derive(Into))] async unsafe fn unsafe_async_function() -> u32 { 99 } struct MethodWithUnsupportedIntoDerive; #[bon] impl MethodWithUnsupportedIntoDerive { #[builder(derive(Into))] fn derive_into_with_finish_fn_member(#[builder(finish_fn)] _finish_fn: fn() -> u32) -> u32 { 99 } } #[bon] impl MethodWithUnsupportedIntoDerive { #[builder(derive(Into))] fn function_with_unit_return_type() {} } #[bon] impl MethodWithUnsupportedIntoDerive { #[builder(derive(Into))] async fn async_function() -> Self { Self } } #[bon] impl MethodWithUnsupportedIntoDerive { #[builder(derive(Into))] unsafe fn unsafe_function() -> Self { Self } } #[bon] impl MethodWithUnsupportedIntoDerive { #[builder(derive(Into))] async unsafe fn unsafe_async_function() -> Self { Self } } #[builder(derive(Into(bounds(u32: Copy))))] fn unsupported_bounds_on_derive_into() -> u32 { 99 } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_derive.stderr000064400000000000000000000510301046102023000226730ustar 00000000000000error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_derive.rs:58:17 | 58 | #[builder(derive())] | ^^ error: Missing field `bounds` --> tests/integration/ui/compile_fail/attr_derive.rs:62:18 | 62 | #[builder(derive(Clone()))] | ^^^^^ error: wrong delimiter, expected parentheses e.g. `bounds(...)`, but got curly braces: `bounds{...}` --> tests/integration/ui/compile_fail/attr_derive.rs:66:24 | 66 | #[builder(derive(Clone(bounds {})))] | ^^^^^^ error: `#[builder(derive(Into))` is incompatible with `#[builder(finish_fn)]` members because `From::from()` method accepts zero parameters --> tests/integration/ui/compile_fail/attr_derive.rs:70:48 | 70 | fn derive_into_with_finish_fn_member(#[builder(finish_fn)] _finish_fn: fn() -> u32) -> u32 { | ^^^^^^^^^ error: `#[builder(derive(Into))` is not supported for functions with the implicit unit return type; if you have a use case where it makes sense to implement `From for ()`, please open an issue, and in the meantime annotate the function return type explicitly with `-> ()` --> tests/integration/ui/compile_fail/attr_derive.rs:75:4 | 75 | fn function_with_unit_return_type() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[builder(derive(Into))` is not supported for async functions because `From::from()` method is a synchronous method --> tests/integration/ui/compile_fail/attr_derive.rs:78:1 | 78 | async fn async_function() -> u32 { | ^^^^^ error: `#[builder(derive(Into))` is not supported for unsafe functions because `From::from()` method is a safe method --> tests/integration/ui/compile_fail/attr_derive.rs:83:1 | 83 | unsafe fn unsafe_function() -> u32 { | ^^^^^^ error: `#[builder(derive(Into))` is not supported for async functions because `From::from()` method is a synchronous method --> tests/integration/ui/compile_fail/attr_derive.rs:88:1 | 88 | async unsafe fn unsafe_async_function() -> u32 { | ^^^^^ error: `#[builder(derive(Into))` is incompatible with `#[builder(finish_fn)]` members because `From::from()` method accepts zero parameters --> tests/integration/ui/compile_fail/attr_derive.rs:97:52 | 97 | fn derive_into_with_finish_fn_member(#[builder(finish_fn)] _finish_fn: fn() -> u32) -> u32 { | ^^^^^^^^^ error: `#[builder(derive(Into))` is not supported for functions with the implicit unit return type; if you have a use case where it makes sense to implement `From for ()`, please open an issue, and in the meantime annotate the function return type explicitly with `-> ()` --> tests/integration/ui/compile_fail/attr_derive.rs:105:8 | 105 | fn function_with_unit_return_type() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[builder(derive(Into))` is not supported for async functions because `From::from()` method is a synchronous method --> tests/integration/ui/compile_fail/attr_derive.rs:111:5 | 111 | async fn async_function() -> Self { | ^^^^^ error: `#[builder(derive(Into))` is not supported for unsafe functions because `From::from()` method is a safe method --> tests/integration/ui/compile_fail/attr_derive.rs:119:5 | 119 | unsafe fn unsafe_function() -> Self { | ^^^^^^ error: `#[builder(derive(Into))` is not supported for async functions because `From::from()` method is a synchronous method --> tests/integration/ui/compile_fail/attr_derive.rs:127:5 | 127 | async unsafe fn unsafe_async_function() -> Self { | ^^^^^ error: Unknown field: `bounds` --> tests/integration/ui/compile_fail/attr_derive.rs:132:23 | 132 | #[builder(derive(Into(bounds(u32: Copy))))] | ^^^^^^ error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:9:23 | 9 | no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:11:24 | 11 | no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:13:30 | 13 | no_impl_optional: Option, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:16:25 | 16 | no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:9:23 | 9 | no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:11:24 | 11 | no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:13:30 | 13 | no_impl_optional: Option, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:16:25 | 16 | no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:24:24 | 24 | _no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:26:25 | 26 | _no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:28:31 | 28 | _no_impl_optional: Option, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:31:26 | 31 | _no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:24:24 | 24 | _no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:26:25 | 26 | _no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:28:31 | 28 | _no_impl_optional: Option, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:31:26 | 31 | _no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `StructContainsNonTrait: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:38:6 | 38 | impl StructContainsNonTrait { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `StructContainsNonTrait` error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:43:49 | 43 | #[builder(start_fn)] _no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:45:29 | 45 | _no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:47:35 | 47 | _no_impl_optional: Option, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: the trait bound `NoTraitImpls: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_derive.rs:50:30 | 50 | _no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoTraitImpls` | note: required by a bound in `clone_member` --> src/__/better_errors.rs | | pub fn clone_member(member: &Option) -> Option { | ^^^^^ required by this bound in `clone_member` help: consider annotating `NoTraitImpls` with `#[derive(Clone)]` | 3 + #[derive(Clone)] 4 | struct NoTraitImpls; | error[E0277]: `StructContainsNonTrait` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:38:6 | 38 | impl StructContainsNonTrait { | ^^^^^^^^^^^^^^^^^^^^^^ `StructContainsNonTrait` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `StructContainsNonTrait` = note: add `#[derive(Debug)]` to `StructContainsNonTrait` or manually `impl Debug for StructContainsNonTrait` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:43:49 | 43 | #[builder(start_fn)] _no_impl_start_fn: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:45:29 | 45 | _no_impls_required: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:47:35 | 47 | _no_impl_optional: Option, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | error[E0277]: `NoTraitImpls` doesn't implement `Debug` --> tests/integration/ui/compile_fail/attr_derive.rs:50:30 | 50 | _no_impl_optional_2: NoTraitImpls, | ^^^^^^^^^^^^ `NoTraitImpls` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NoTraitImpls` = note: add `#[derive(Debug)]` to `NoTraitImpls` or manually `impl Debug for NoTraitImpls` note: required by a bound in `as_dyn_debug` --> src/__/better_errors.rs | | pub fn as_dyn_debug(member: &T) -> &dyn Debug { | ^^^^^ required by this bound in `as_dyn_debug` help: consider annotating `NoTraitImpls` with `#[derive(Debug)]` | 3 + #[derive(Debug)] 4 | struct NoTraitImpls; | bon-3.7.1/tests/integration/ui/compile_fail/attr_field.rs000064400000000000000000000005461046102023000216270ustar 00000000000000use bon::Builder; #[derive(Builder)] struct WrongName { #[builder(field)] __x1: i32, } mod privacy { #[derive(bon::Builder)] pub struct MustBePrivate { #[builder(field)] x1: i32, } } fn main() { let builder = privacy::MustBePrivate::builder(); // Should be inaccessible in this scope let _ = builder.x1; } bon-3.7.1/tests/integration/ui/compile_fail/attr_field.stderr000064400000000000000000000006301046102023000225000ustar 00000000000000error: field names starting with `__` are reserved for `bon`'s internal use; please, select a different name --> tests/integration/ui/compile_fail/attr_field.rs:6:5 | 6 | __x1: i32, | ^^^^ error[E0616]: field `x1` of struct `MustBePrivateBuilder` is private --> tests/integration/ui/compile_fail/attr_field.rs:21:21 | 21 | let _ = builder.x1; | ^^ private field bon-3.7.1/tests/integration/ui/compile_fail/attr_getter.rs000064400000000000000000000031251046102023000220320ustar 00000000000000use bon::Builder; #[derive(Builder)] struct StartFnCompat { #[builder(getter, start_fn)] x: u32, } #[derive(Builder)] struct FinishFnCompat { #[builder(getter, finish_fn)] x: u32, } #[derive(Builder)] struct SkipCompat { #[builder(getter, skip)] x: u32, } #[derive(Builder)] struct NegativeTest { #[builder(getter)] x1: u32, #[builder(getter)] x2: Option, #[builder(getter, default)] x3: u32, } #[derive(Builder)] struct NonCopy { #[builder(getter(copy))] x1: String, #[builder(getter(copy))] x2: Option, #[builder(getter(copy), default)] x3: String, } #[derive(Default)] struct NonClone; #[derive(Builder)] struct NonCloneTest { #[builder(getter(clone))] x1: NonClone, #[builder(getter(clone))] x2: Option, #[builder(getter(clone), default)] x3: NonClone, } #[derive(Builder)] struct NoDeref { #[builder(getter(deref(u64)))] x1: String, #[builder(getter(deref(u64)))] x2: Option, #[builder(getter(deref(u64)), default)] x3: String, } #[derive(Builder)] struct CantInferDerefTarget { #[builder(getter(deref))] x1: u32, } #[derive(Builder)] struct CopyCloneExclusion { #[builder(getter(copy, clone))] x1: u32, } #[derive(Builder)] struct CopyDerefExclusion { #[builder(getter(copy, deref))] x1: u32, } #[derive(Builder)] struct CloneDerefExclusion { #[builder(getter(clone, deref))] x1: u32, } fn main() { let builder = NegativeTest::builder(); builder.get_x1(); builder.get_x2(); builder.get_x3(); } bon-3.7.1/tests/integration/ui/compile_fail/attr_getter.stderr000064400000000000000000000227021046102023000227130ustar 00000000000000error: `start_fn` attribute can't be specified together with `getter` --> tests/integration/ui/compile_fail/attr_getter.rs:5:23 | 5 | #[builder(getter, start_fn)] | ^^^^^^^^ error: `finish_fn` attribute can't be specified together with `getter` --> tests/integration/ui/compile_fail/attr_getter.rs:11:23 | 11 | #[builder(getter, finish_fn)] | ^^^^^^^^^ error: `skip` attribute can't be specified together with `getter` --> tests/integration/ui/compile_fail/attr_getter.rs:17:23 | 17 | #[builder(getter, skip)] | ^^^^ error: can't infer the `Deref::Target` for the getter from the member's type; please specify the return type (target of the deref coercion) explicitly in parentheses without the leading `&`; example: `#[builder(getter(deref(TargetTypeHere))]` automatic deref target detection is supported only for the following types: - Vec - Box - Rc - Arc - String - CString - OsString - PathBuf - Cow --> tests/integration/ui/compile_fail/attr_getter.rs:74:22 | 74 | #[builder(getter(deref))] | ^^^^^ error: `copy` can't be specified together with `clone` --> tests/integration/ui/compile_fail/attr_getter.rs:80:22 | 80 | #[builder(getter(copy, clone))] | ^^^^ error: `copy` can't be specified together with `deref` --> tests/integration/ui/compile_fail/attr_getter.rs:86:22 | 86 | #[builder(getter(copy, deref))] | ^^^^ error: `clone` can't be specified together with `deref` --> tests/integration/ui/compile_fail/attr_getter.rs:92:22 | 92 | #[builder(getter(clone, deref))] | ^^^^^ error[E0277]: the trait bound `String: std::marker::Copy` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:36:9 | 36 | x1: String, | ^^^^^^ the trait `std::marker::Copy` is not implemented for `String` | note: required by a bound in `copy_member` --> src/__/better_errors.rs | | pub fn copy_member(member: &Option) -> Option { | ^^^^ required by this bound in `copy_member` error[E0277]: the trait bound `String: std::marker::Copy` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:39:16 | 39 | x2: Option, | ^^^^^^ the trait `std::marker::Copy` is not implemented for `String` | note: required by a bound in `copy_member` --> src/__/better_errors.rs | | pub fn copy_member(member: &Option) -> Option { | ^^^^ required by this bound in `copy_member` error[E0277]: the trait bound `String: std::marker::Copy` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:42:9 | 42 | x3: String, | ^^^^^^ the trait `std::marker::Copy` is not implemented for `String` | note: required by a bound in `copy_member` --> src/__/better_errors.rs | | pub fn copy_member(member: &Option) -> Option { | ^^^^ required by this bound in `copy_member` error[E0277]: the trait bound `NonClone: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:51:9 | 51 | x1: NonClone, | ^^^^^^^^ the trait `Clone` is not implemented for `NonClone` | help: consider annotating `NonClone` with `#[derive(Clone)]` | 46 + #[derive(Clone)] 47 | struct NonClone; | error[E0277]: the trait bound `NonClone: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:54:16 | 54 | x2: Option, | ^^^^^^^^ the trait `Clone` is not implemented for `NonClone` | = note: required for `Option` to implement `Clone` help: consider annotating `NonClone` with `#[derive(Clone)]` | 46 + #[derive(Clone)] 47 | struct NonClone; | error[E0277]: the trait bound `NonClone: Clone` is not satisfied --> tests/integration/ui/compile_fail/attr_getter.rs:57:9 | 57 | x3: NonClone, | ^^^^^^^^ the trait `Clone` is not implemented for `NonClone` | = note: required for `Option` to implement `Clone` help: consider annotating `NonClone` with `#[derive(Clone)]` | 46 + #[derive(Clone)] 47 | struct NonClone; | error[E0308]: mismatched types --> tests/integration/ui/compile_fail/attr_getter.rs:62:28 | 60 | #[derive(Builder)] | ------- expected `&u64` because of return type 61 | struct NoDeref { 62 | #[builder(getter(deref(u64)))] | ^^^ expected `&u64`, found `&String` | = note: expected reference `&u64` found reference `&String` error[E0308]: mismatched types --> tests/integration/ui/compile_fail/attr_getter.rs:65:28 | 60 | #[derive(Builder)] | ------- arguments to this enum variant are incorrect ... 65 | #[builder(getter(deref(u64)))] | ^^^ expected `&u64`, found `&String` | = note: expected reference `&u64` found reference `&String` help: the type constructed contains `&String` due to the type of the argument passed --> tests/integration/ui/compile_fail/attr_getter.rs:60:10 | 60 | #[derive(Builder)] | ^^^^^^^ ... 65 | #[builder(getter(deref(u64)))] | --- this argument influences the type of `Some` note: tuple variant defined here --> $RUST/core/src/option.rs | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), | ^^^^ = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> tests/integration/ui/compile_fail/attr_getter.rs:68:28 | 60 | #[derive(Builder)] | ------- arguments to this enum variant are incorrect ... 68 | #[builder(getter(deref(u64)), default)] | ^^^ expected `&u64`, found `&String` | = note: expected reference `&u64` found reference `&String` help: the type constructed contains `&String` due to the type of the argument passed --> tests/integration/ui/compile_fail/attr_getter.rs:60:10 | 60 | #[derive(Builder)] | ^^^^^^^ ... 68 | #[builder(getter(deref(u64)), default)] | --- this argument influences the type of `Some` note: tuple variant defined here --> $RUST/core/src/option.rs | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), | ^^^^ = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/attr_getter.rs:99:13 | 99 | builder.get_x1(); | ^^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required by a bound in `NegativeTestBuilder::::get_x1` --> tests/integration/ui/compile_fail/attr_getter.rs:21:10 | 21 | #[derive(Builder)] | ^^^^^^^ required by this bound in `NegativeTestBuilder::::get_x1` ... 24 | x1: u32, | -- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/attr_getter.rs:100:13 | 100 | builder.get_x2(); | ^^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required by a bound in `NegativeTestBuilder::::get_x2` --> tests/integration/ui/compile_fail/attr_getter.rs:21:10 | 21 | #[derive(Builder)] | ^^^^^^^ required by this bound in `NegativeTestBuilder::::get_x2` ... 27 | x2: Option, | -- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/attr_getter.rs:101:13 | 101 | builder.get_x3(); | ^^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required by a bound in `NegativeTestBuilder::::get_x3` --> tests/integration/ui/compile_fail/attr_getter.rs:21:10 | 21 | #[derive(Builder)] | ^^^^^^^ required by this bound in `NegativeTestBuilder::::get_x3` ... 30 | x3: u32, | -- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) bon-3.7.1/tests/integration/ui/compile_fail/attr_into.rs000064400000000000000000000001471046102023000215120ustar 00000000000000use bon::builder; #[builder] fn invalid_into_false(#[builder(into = false)] _x: u32) {} fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_into.stderr000064400000000000000000000003131046102023000223640ustar 00000000000000error: Unexpected type `bool` --> tests/integration/ui/compile_fail/attr_into.rs:4:40 | 4 | fn invalid_into_false(#[builder(into = false)] _x: u32) {} | ^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_into_future.rs000064400000000000000000000017051046102023000231050ustar 00000000000000use bon::{builder, Builder}; // IntoFuture can only be used with async functions #[builder(derive(IntoFuture(Box)))] fn sync_function() -> u32 { 42 } // IntoFuture is not supported for unsafe functions #[builder(derive(IntoFuture(Box)))] async unsafe fn unsafe_async_function() -> u32 { 42 } // IntoFuture is incompatible with finish_fn members #[builder(derive(IntoFuture(Box)))] async fn with_finish_fn(#[builder(finish_fn)] value: u32) -> u32 { value } // IntoFuture requires Box argument #[builder(derive(IntoFuture))] async fn missing_box_arg() -> u32 { 42 } // Only Box is supported as future container #[builder(derive(IntoFuture(Arc)))] async fn wrong_container() -> u32 { 42 } // Wrong syntax for ?Send #[builder(derive(IntoFuture(Box, Send)))] async fn wrong_send_syntax() -> u32 { 42 } // Cannot be used on structs #[derive(Builder)] #[builder(derive(IntoFuture(Box)))] struct AsyncConfig { value: u32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_into_future.stderr000064400000000000000000000036501046102023000237650ustar 00000000000000error: `#[builder(derive(IntoFuture(...)))` can only be used with async functions; using it with a synchronous function is likely a mistake --> tests/integration/ui/compile_fail/attr_into_future.rs:4:1 | 4 | #[builder(derive(IntoFuture(Box)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the attribute macro `builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[builder(derive(IntoFuture(...)))` is not supported for unsafe functions because `IntoFuture::into_future()` method is a safe method --> tests/integration/ui/compile_fail/attr_into_future.rs:11:7 | 11 | async unsafe fn unsafe_async_function() -> u32 { | ^^^^^^ error: `#[builder(derive(IntoFuture(...)))` is incompatible with `#[builder(finish_fn)]` members because `IntoFuture::into_future()` method accepts zero parameters --> tests/integration/ui/compile_fail/attr_into_future.rs:17:35 | 17 | async fn with_finish_fn(#[builder(finish_fn)] value: u32) -> u32 { | ^^^^^^^^^ error: expected an attribute of form `IntoFuture(Box, ...)` --> tests/integration/ui/compile_fail/attr_into_future.rs:22:18 | 22 | #[builder(derive(IntoFuture))] | ^^^^^^^^^^ error: expected `Box` as the first argument, only boxed futures are supported --> tests/integration/ui/compile_fail/attr_into_future.rs:28:29 | 28 | #[builder(derive(IntoFuture(Arc)))] | ^^^ error: expected `?Send` as the second argument --> tests/integration/ui/compile_fail/attr_into_future.rs:34:34 | 34 | #[builder(derive(IntoFuture(Box, Send)))] | ^^^^ error: `#[builder(derive(IntoFuture(...)))` can only be used with async functions; using it with a synchronous function is likely a mistake --> tests/integration/ui/compile_fail/attr_into_future.rs:42:8 | 42 | struct AsyncConfig { | ^^^^^^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_on.rs000064400000000000000000000016751046102023000211640ustar 00000000000000use bon::builder; #[builder(on(String, into))] fn unnecessary_into(#[builder(into)] _x: String) {} #[builder(on(&dyn std::fmt::Debug, into))] fn invalid_type_pattern() {} #[builder(on(fn(#[attr] a: u32), into))] fn attrs_in_on_type_pattern() {} #[builder(on)] fn incomplete_on() {} #[builder(on())] fn incomplete_on2() {} #[builder(on(_))] fn incomplete_on3() {} #[builder(on(_,))] fn incomplete_on4() {} #[builder( on(_, required), finish_fn = finish, on(String, into), )] fn non_consecutive_on1() {} #[builder( start_fn = start, on(_, required), finish_fn = finish, on(String, into), )] fn non_consecutive_on2() {} #[builder( start_fn = start, on(_, required), finish_fn = finish, on(String, into), builder_type = Builder, )] fn non_consecutive_on3() {} #[builder(on(_, into), on(_, required))] fn non_first_required() {} #[builder(on(u8, required))] fn non_wildcard_required() {} fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_on.stderr000064400000000000000000000054751046102023000220450ustar 00000000000000error: this `#[builder(into)]` attribute is redundant, because `into` is already implied for this member via the `#[builder(on(...))]` at the top of the function --> tests/integration/ui/compile_fail/attr_on.rs:4:31 | 4 | fn unnecessary_into(#[builder(into)] _x: String) {} | ^^^^ error: this syntax is not supported in type patterns yet. If you have a use case for this, please open an issue at https://github.com/elastio/bon/issues. --> tests/integration/ui/compile_fail/attr_on.rs:6:15 | 6 | #[builder(on(&dyn std::fmt::Debug, into))] | ^^^ error: nested attributes are not allowed in the type pattern of #[builder(on(type_pattern, ...))] --> tests/integration/ui/compile_fail/attr_on.rs:9:17 | 9 | #[builder(on(fn(#[attr] a: u32), into))] | ^ error: this empty `on` attribute is unexpected; remove it or pass parameters in parentheses: `on(...)` --> tests/integration/ui/compile_fail/attr_on.rs:12:11 | 12 | #[builder(on)] | ^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_on.rs:15:13 | 15 | #[builder(on())] | ^^ error: expected `,` --> tests/integration/ui/compile_fail/attr_on.rs:18:1 | 18 | #[builder(on(_))] | ^^^^^^^^^^^^^^^^^ | = note: this error originates in the attribute macro `builder` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected at least one parameter after the comma in `on(type_pattern, ...)` --> tests/integration/ui/compile_fail/attr_on.rs:21:15 | 21 | #[builder(on(_,))] | ^ error: this `on(...)` clause is out of order; all `on(...)` clauses must be consecutive; there shouldn't be any other parameters between them --> tests/integration/ui/compile_fail/attr_on.rs:27:5 | 27 | on(String, into), | ^^ error: this `on(...)` clause is out of order; all `on(...)` clauses must be consecutive; there shouldn't be any other parameters between them --> tests/integration/ui/compile_fail/attr_on.rs:35:5 | 35 | on(String, into), | ^^ error: this `on(...)` clause is out of order; all `on(...)` clauses must be consecutive; there shouldn't be any other parameters between them --> tests/integration/ui/compile_fail/attr_on.rs:43:5 | 43 | on(String, into), | ^^ error: `required` can only be specified in the first `on(...)` clause; this restriction may be lifted in the future --> tests/integration/ui/compile_fail/attr_on.rs:48:30 | 48 | #[builder(on(_, into), on(_, required))] | ^^^^^^^^ error: `required` can only be used with the wildcard type pattern i.e. `on(_, required)`; this restriction may be lifted in the future --> tests/integration/ui/compile_fail/attr_on.rs:51:14 | 51 | #[builder(on(u8, required))] | ^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_required.rs000064400000000000000000000020641046102023000223610ustar 00000000000000use bon::Builder; #[derive(Builder)] struct InvalidOnRequiredMember { #[builder(required)] member: i32, } #[derive(Builder)] struct InvalidOnStartFnMember { #[builder(start_fn, required)] member: Option, } #[derive(Builder)] struct InvalidOnFnMember { #[builder(finish_fn, required)] member: Option, } #[derive(Builder)] struct InvalidOnSkippedMember { #[builder(skip, required)] member: Option, } #[derive(Builder)] struct Valid { #[builder(required)] member: Option, #[builder(required, with = Some)] some_member: Option<()>, } fn main() { // Make sure there is no `maybe_` setter generated let _ = Valid::builder().maybe_member(Some(42)); let _ = Valid::builder().maybe_some_member(Some(())); // Another way to get transparency { type OpaqueOption = Option; #[derive(Builder)] struct Sut { arg1: OpaqueOption, } // Should not be allowed `OpaqueOption` is required let _ = Sut::builder().build(); } } bon-3.7.1/tests/integration/ui/compile_fail/attr_required.stderr000064400000000000000000000061341046102023000232420ustar 00000000000000error: `#[builder(required)]` can only be applied to members of type `Option` to disable their special handling --> tests/integration/ui/compile_fail/attr_required.rs:5:15 | 5 | #[builder(required)] | ^^^^^^^^ error: `start_fn` attribute can't be specified together with `required` --> tests/integration/ui/compile_fail/attr_required.rs:11:15 | 11 | #[builder(start_fn, required)] | ^^^^^^^^ error: `finish_fn` attribute can't be specified together with `required` --> tests/integration/ui/compile_fail/attr_required.rs:17:15 | 17 | #[builder(finish_fn, required)] | ^^^^^^^^^ error: `skip` attribute can't be specified together with `required` --> tests/integration/ui/compile_fail/attr_required.rs:23:15 | 23 | #[builder(skip, required)] | ^^^^ error[E0599]: no method named `maybe_member` found for struct `ValidBuilder` in the current scope --> tests/integration/ui/compile_fail/attr_required.rs:38:30 | 27 | #[derive(Builder)] | ------- method `maybe_member` not found for this struct ... 38 | let _ = Valid::builder().maybe_member(Some(42)); | ^^^^^^^^^^^^ | help: there is a method `member` with a similar name | 38 - let _ = Valid::builder().maybe_member(Some(42)); 38 + let _ = Valid::builder().member(Some(42)); | error[E0599]: no method named `maybe_some_member` found for struct `ValidBuilder` in the current scope --> tests/integration/ui/compile_fail/attr_required.rs:39:30 | 27 | #[derive(Builder)] | ------- method `maybe_some_member` not found for this struct ... 39 | let _ = Valid::builder().maybe_some_member(Some(())); | ^^^^^^^^^^^^^^^^^ | help: there is a method `some_member` with a similar name | 39 - let _ = Valid::builder().maybe_some_member(Some(())); 39 + let _ = Valid::builder().some_member(Some(())); | error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/attr_required.rs:51:32 | 51 | let _ = Sut::builder().build(); | ^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required for `sut_builder::Empty` to implement `sut_builder::IsComplete` --> tests/integration/ui/compile_fail/attr_required.rs:45:18 | 45 | #[derive(Builder)] | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `SutBuilder::::build` --> tests/integration/ui/compile_fail/attr_required.rs:45:18 | 45 | #[derive(Builder)] | ^^^^^^^ required by this bound in `SutBuilder::::build` 46 | struct Sut { | --- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) bon-3.7.1/tests/integration/ui/compile_fail/attr_setters.rs000064400000000000000000000040541046102023000222330ustar 00000000000000use bon::Builder; #[derive(Builder)] struct UnusedNameConfig { #[builder(setters( name = littlepip, some_fn = blackjack, option_fn = roseluck, ))] value: Option, } #[derive(Builder)] struct UnusedNameConfigVerbose { #[builder(setters( name = littlepip, some_fn(name = blackjack), option_fn(name = roseluck), ))] value: Option, } #[derive(Builder)] struct UnusedVisConfig { #[builder(setters(vis = "pub(crate)", some_fn(vis = ""), option_fn(vis = ""),))] value: Option, } #[derive(Builder)] struct UnusedDocsConfig { #[builder(setters( doc { /// Unused }, some_fn(doc { /// some_fn docs }), option_fn(doc { /// option_fn docs }), ))] value: Option, } #[derive(Builder)] struct SomeFnSetterRequiredMember { #[builder(setters(some_fn = foo))] member: i32, } #[derive(Builder)] struct OptionFnSetterOnRequiredMember { #[builder(setters(option_fn = bar))] member: i32, } #[derive(Builder)] struct SomeFnSetterWithrequired { #[builder(required, setters(some_fn = foo))] member: Option, } #[derive(Builder)] struct OptionFnSetterWithrequired { #[builder(required, setters(option_fn = bar))] member: Option, } #[derive(Builder)] struct EmptySettersConfig { #[builder(setters())] member: i32, } #[derive(Builder)] struct RepeatedSettersDocContent { #[builder(setters( doc { /// Doc 1 }, doc { /// Doc 2 } ))] member: i32, } #[derive(Builder)] struct RepeatedSettersDocConfig { #[builder(setters( doc { /// Doc 1 }, doc(default(skip)), doc(default(skip)), ))] member: i32, } #[derive(Builder)] struct InvalidSettersDocSyntax { #[builder(setters(doc["Doc 2"]))] member: i32, } #[derive(Builder)] struct SettersDocDefaultOnNonDefault { #[builder(setters(doc(default(skip))))] member: i32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_setters.stderr000064400000000000000000000062101046102023000231060ustar 00000000000000error: this `name` configuration is unused because all of the `some_fn`, `option_fn` setters contain a `name` override --> tests/integration/ui/compile_fail/attr_setters.rs:6:9 | 6 | name = littlepip, | ^^^^ error: this `name` configuration is unused because all of the `some_fn`, `option_fn` setters contain a `name` override --> tests/integration/ui/compile_fail/attr_setters.rs:16:9 | 16 | name = littlepip, | ^^^^ error: this `vis` configuration is unused because all of the `some_fn`, `option_fn` setters contain a `vis` override --> tests/integration/ui/compile_fail/attr_setters.rs:25:23 | 25 | #[builder(setters(vis = "pub(crate)", some_fn(vis = ""), option_fn(vis = ""),))] | ^^^ error: this `doc` configuration is unused because all of the `some_fn`, `option_fn` setters contain a `doc` override --> tests/integration/ui/compile_fail/attr_setters.rs:32:9 | 32 | doc { | ^^^ error: `some_fn` setter function applies only to members with `#[builder(default)]` or members of `Option` type (if #[builder(required)] is not set) --> tests/integration/ui/compile_fail/attr_setters.rs:47:23 | 47 | #[builder(setters(some_fn = foo))] | ^^^^^^^ error: `option_fn` setter function applies only to members with `#[builder(default)]` or members of `Option` type (if #[builder(required)] is not set) --> tests/integration/ui/compile_fail/attr_setters.rs:53:23 | 53 | #[builder(setters(option_fn = bar))] | ^^^^^^^^^ error: `some_fn` setter function applies only to members with `#[builder(default)]` or members of `Option` type (if #[builder(required)] is not set) --> tests/integration/ui/compile_fail/attr_setters.rs:59:33 | 59 | #[builder(required, setters(some_fn = foo))] | ^^^^^^^ error: `option_fn` setter function applies only to members with `#[builder(default)]` or members of `Option` type (if #[builder(required)] is not set) --> tests/integration/ui/compile_fail/attr_setters.rs:65:33 | 65 | #[builder(required, setters(option_fn = bar))] | ^^^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_setters.rs:71:22 | 71 | #[builder(setters())] | ^^ error: repeated `doc {...}` attribute is not allowed --> tests/integration/ui/compile_fail/attr_setters.rs:81:9 | 81 | doc { | ^^^ error: repeated `doc(...)` attribute is not allowed --> tests/integration/ui/compile_fail/attr_setters.rs:95:9 | 95 | doc(default(skip)), | ^^^ error: wrong delimiter, expected doc(...) or doc {...} --> tests/integration/ui/compile_fail/attr_setters.rs:102:23 | 102 | #[builder(setters(doc["Doc 2"]))] | ^^^ error: `#[builder(setters(doc(default(...)))]` may only be specified when #[builder(default)] is also specified --> tests/integration/ui/compile_fail/attr_setters.rs:108:27 | 108 | #[builder(setters(doc(default(skip))))] | ^^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_skip.rs000064400000000000000000000014731046102023000215120ustar 00000000000000use bon::{builder, Builder}; #[derive(Builder)] struct ConflictingAttrs { #[builder(skip, into)] x: u32, } #[derive(Builder)] struct ConflictingAttrs2 { #[builder(skip, name = bar)] x: u32, } #[derive(Builder)] struct ConflictingAttrs3 { #[builder(skip, default = 42)] z: u32, } #[builder] fn skip_on_fn_is_unsupporetd1(#[builder(skip)] _x: u32) {} #[builder] fn skip_on_fn_is_unsupporetd2(#[builder(skip = "skip".to_owned())] _y: String) {} #[builder] fn skip_on_fn_is_unsupporetd3(#[builder(skip = vec![42])] _z: Vec) {} fn main() { #[derive(Builder)] struct SkipGeneratesNoSetter { #[builder(skip)] x: u32, #[builder(skip = 4)] y: u32, } SkipGeneratesNoSetter::builder().x(42).build(); SkipGeneratesNoSetter::builder().y(42).build(); } bon-3.7.1/tests/integration/ui/compile_fail/attr_skip.stderr000064400000000000000000000045061046102023000223710ustar 00000000000000error: `skip` attribute can't be specified together with `into` --> tests/integration/ui/compile_fail/attr_skip.rs:5:15 | 5 | #[builder(skip, into)] | ^^^^ error: `skip` attribute can't be specified together with `name` --> tests/integration/ui/compile_fail/attr_skip.rs:11:15 | 11 | #[builder(skip, name = bar)] | ^^^^ error: `skip` attribute can't be specified with the `default` attribute; if you wanted to specify a value for the member, then use the following syntax instead `#[builder(skip = value)]` --> tests/integration/ui/compile_fail/attr_skip.rs:17:15 | 17 | #[builder(skip, default = 42)] | ^^^^ error: `skip` attribute is not supported on function arguments; use a local variable instead. --> tests/integration/ui/compile_fail/attr_skip.rs:22:41 | 22 | fn skip_on_fn_is_unsupporetd1(#[builder(skip)] _x: u32) {} | ^^^^ error: `skip` attribute is not supported on function arguments; use a local variable instead. --> tests/integration/ui/compile_fail/attr_skip.rs:24:41 | 24 | fn skip_on_fn_is_unsupporetd2(#[builder(skip = "skip".to_owned())] _y: String) {} | ^^^^ error: `skip` attribute is not supported on function arguments; use a local variable instead. --> tests/integration/ui/compile_fail/attr_skip.rs:26:41 | 26 | fn skip_on_fn_is_unsupporetd3(#[builder(skip = vec![42])] _z: Vec) {} | ^^^^ error[E0599]: no method named `x` found for struct `SkipGeneratesNoSetterBuilder` in the current scope --> tests/integration/ui/compile_fail/attr_skip.rs:38:38 | 29 | #[derive(Builder)] | ------- method `x` not found for this struct ... 38 | SkipGeneratesNoSetter::builder().x(42).build(); | ^ method not found in `SkipGeneratesNoSetterBuilder` error[E0599]: no method named `y` found for struct `SkipGeneratesNoSetterBuilder` in the current scope --> tests/integration/ui/compile_fail/attr_skip.rs:39:38 | 29 | #[derive(Builder)] | ------- method `y` not found for this struct ... 39 | SkipGeneratesNoSetter::builder().y(42).build(); | ^ method not found in `SkipGeneratesNoSetterBuilder` bon-3.7.1/tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs000064400000000000000000000023051046102023000257700ustar 00000000000000use bon::{bon, builder, Builder}; #[derive(Builder)] #[builder(start_fn())] struct EmptyStartFn {} #[derive(Builder)] #[builder(finish_fn())] struct EmptyFinisFn {} #[derive(Builder)] #[builder(start_fn)] struct BareStartFnAttrOnStruct {} #[builder(start_fn)] fn bare_start_fn_on_free_function() {} #[builder(start_fn())] fn empty_paren_start_fn_on_free_function() {} #[builder(start_fn(vis = ""))] fn missing_name_for_start_fn_on_free_function1() {} #[builder(start_fn(doc {}))] fn missing_name_for_start_fn_on_free_function2() {} struct AssocCtx; struct AssocCtx2; struct AssocCtx3; struct AssocCtx4; #[bon] impl AssocCtx { #[builder(start_fn)] fn new() {} } #[bon] impl AssocCtx2 { #[builder(start_fn())] fn new() {} } #[bon] impl AssocCtx3 { #[builder(start_fn(vis = ""))] fn new() {} } #[bon] impl AssocCtx4 { #[builder(start_fn(doc {}))] fn new() {} } #[bon] impl AssocCtx { #[builder(start_fn)] fn bare_start_fn_on_method() {} } #[bon] impl AssocCtx { #[builder(start_fn(vis = ""))] fn missing_name_for_start_fn_on_method1() {} } #[bon] impl AssocCtx { #[builder(start_fn(doc {}))] fn missing_name_for_start_fn_on_method2() {} } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.stderr000064400000000000000000000137371046102023000266620ustar 00000000000000error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:4:19 | 4 | #[builder(start_fn())] | ^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:8:20 | 8 | #[builder(finish_fn())] | ^^ error: this empty `start_fn` attribute is unexpected; remove it or pass parameters in parentheses: `start_fn(...)` --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:12:11 | 12 | #[builder(start_fn)] | ^^^^^^^^ error: this empty `start_fn` attribute is unexpected; remove it or pass parameters in parentheses: `start_fn(...)` --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:15:11 | 15 | #[builder(start_fn)] | ^^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:18:19 | 18 | #[builder(start_fn())] | ^^ error: #[builder(start_fn(vis))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:21:20 | 21 | #[builder(start_fn(vis = ""))] | ^^^ error: #[builder(start_fn(doc))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:24:20 | 24 | #[builder(start_fn(doc {}))] | ^^^ error: this empty `start_fn` attribute is unexpected; remove it or pass parameters in parentheses: `start_fn(...)` --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:34:15 | 34 | #[builder(start_fn)] | ^^^^^^^^ error: expected parameters in parentheses --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:40:23 | 40 | #[builder(start_fn())] | ^^ error: #[builder(start_fn(vis))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:46:24 | 46 | #[builder(start_fn(vis = ""))] | ^^^ error: #[builder(start_fn(doc))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:52:24 | 52 | #[builder(start_fn(doc {}))] | ^^^ error: this empty `start_fn` attribute is unexpected; remove it or pass parameters in parentheses: `start_fn(...)` --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:58:15 | 58 | #[builder(start_fn)] | ^^^^^^^^ error: #[builder(start_fn(vis))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:64:24 | 64 | #[builder(start_fn(vis = ""))] | ^^^ error: #[builder(start_fn(doc))] requires that you also specify #[builder(start_fn(name))] which makes the starting function not to replace the positional function under the #[builder] attribute; by default (without the explicit #[builder(start_fn(name))]) the name, visibility and documentation of the positional function are all copied to the starting function, and the positional function under the #[builder] attribute becomes private with #[doc(hidden)] and it's renamed (the name is not guaranteed to be stable) to make it inaccessible even within the current module --> tests/integration/ui/compile_fail/attr_top_level_start_finish_fn.rs:70:24 | 70 | #[builder(start_fn(doc {}))] | ^^^ bon-3.7.1/tests/integration/ui/compile_fail/attr_with.rs000064400000000000000000000045671046102023000215260ustar 00000000000000use bon::Builder; #[derive(Builder)] struct InvalidWithExpr { #[builder(with = 42)] x: u32, } #[derive(Builder)] struct ConflictingInto { #[builder(into, with = |x: u32| x + 1)] value: u32, } #[derive(Builder)] struct RejectForSyntax { #[builder(with = for<'a> |x: &'a u32| -> u32 { x + 1 })] value: u32, } #[derive(Builder)] struct RejectConstSyntax { #[builder(with = const || 1)] value: u32, } #[derive(Builder)] struct RejectStaticSyntax { #[builder(with = static || 1)] value: u32, } #[derive(Builder)] struct RejectAsyncSyntax { #[builder(with = async || 1)] value: u32, } #[derive(Builder)] struct RejectMoveSyntax { #[builder(with = move || 1)] value: u32, } #[derive(Builder)] struct UnexpectedReturnTypeShape { #[builder(with = |x: u32| -> u32 { x + 1 })] value: u32, } #[derive(Builder)] struct InvalidReturnTypeInResultClosure { #[builder(with = |value: &str| -> ::core::result::Result<_, core::num::ParseIntError> { Ok(value) })] value: u32, } #[derive(Builder)] struct InvalidReturnTypeInImplTraitClosure { #[builder(with = |value: impl Into<::core::net::IpAddr>| value)] value: u32, } #[derive(Builder)] struct NoGenericArgsResultReturnType1 { #[builder(with = |value: u32| -> Result {})] value: u32, } #[derive(Builder)] struct NoGenericArgsResultReturnType2 { #[builder(with = |value: u32| -> Result<> {})] value: u32, } #[derive(Builder)] struct ThreeGenericArgsResultReturnType { #[builder(with = |value: u32| -> ::core::result::Result {})] value: u32, } #[derive(Builder)] struct NonOptionWithSome1 { #[builder(with = Some)] value: u32, } #[derive(Builder)] struct NonOptionWithSome2 { #[builder(with = Some)] value: Option, } #[derive(Builder)] struct NonCollectionWithFromIter1 { #[builder(with = FromIterator::from_iter)] value: Option, } #[derive(Builder)] struct NonCollectionWithFromIter2 { #[builder(with = <_>::from_iter)] value: Option, } #[derive(Builder)] struct IncompatibleWithStartFn { #[builder(with = |x: u32| x + 1, start_fn)] value: u32, } #[derive(Builder)] struct IncompatibleWithFinishFn { #[builder(with = |x: u32| x + 1, finish_fn)] value: u32, } #[derive(Builder)] struct IncompatibleWithInto { #[builder(with = |x: u32| x + 1, into)] value: u32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/attr_with.stderr000064400000000000000000000242361046102023000224000ustar 00000000000000error: expected a closure e.g. `#[builder(with = |param: T| expression)]` or a well-known function path which could be one of: - #[builder(with = Some)] - #[builder(with = FromIterator::from_iter)] - #[builder(with = <_>::from_iter)] (same as above, but shorter) --> tests/integration/ui/compile_fail/attr_with.rs:5:15 | 5 | #[builder(with = 42)] | ^^^^ error: `with` attribute can't be specified together with `into` --> tests/integration/ui/compile_fail/attr_with.rs:11:21 | 11 | #[builder(into, with = |x: u32| x + 1)] | ^^^^ error: `for<...>` syntax is not allowed here --> tests/integration/ui/compile_fail/attr_with.rs:17:22 | 17 | #[builder(with = for<'a> |x: &'a u32| -> u32 { x + 1 })] | ^^^ error: `const` keyword is not allowed here --> tests/integration/ui/compile_fail/attr_with.rs:23:22 | 23 | #[builder(with = const || 1)] | ^^^^^ error: `static` keyword is not allowed here --> tests/integration/ui/compile_fail/attr_with.rs:29:22 | 29 | #[builder(with = static || 1)] | ^^^^^^ error: `async` keyword is not allowed here --> tests/integration/ui/compile_fail/attr_with.rs:35:22 | 35 | #[builder(with = async || 1)] | ^^^^^ error: `move` keyword is not allowed here --> tests/integration/ui/compile_fail/attr_with.rs:41:22 | 41 | #[builder(with = move || 1)] | ^^^^ error: expected one of the following: (1) no return type annotation; this means the closure is expected to return a value of the same type as the member's underlying type(*); (2) `-> *Result<_, {{ErrorType}}>` or `-> *Result<_>` return type annotation; this means the closure is expected to return a `Result` where the `Ok` variant is of the same type as the member's underlying type(*); this syntax allows you to define a fallbile setter (one that returns a `Result`); the `_` placeholder must be spelled literally to mark the underlying type(*) of the member; an optional second generic parameter for the error type is allowed; the return type doesn't have to be named `Result` exactly, the only requirement is that it must have the `Result` suffix; for example if you have a type alias `ApiResult<_>`, then it'll work fine; (*) underlying type is the type of the member stripped from the `Option` wrapper if this member is of `Option` type and no `#[builder(required)]` annotation is present --> tests/integration/ui/compile_fail/attr_with.rs:47:34 | 47 | #[builder(with = |x: u32| -> u32 { x + 1 })] | ^^^ error: expected one of the following: (1) no return type annotation; this means the closure is expected to return a value of the same type as the member's underlying type(*); (2) `-> *Result<_, {{ErrorType}}>` or `-> *Result<_>` return type annotation; this means the closure is expected to return a `Result` where the `Ok` variant is of the same type as the member's underlying type(*); this syntax allows you to define a fallbile setter (one that returns a `Result`); the `_` placeholder must be spelled literally to mark the underlying type(*) of the member; an optional second generic parameter for the error type is allowed; the return type doesn't have to be named `Result` exactly, the only requirement is that it must have the `Result` suffix; for example if you have a type alias `ApiResult<_>`, then it'll work fine; (*) underlying type is the type of the member stripped from the `Option` wrapper if this member is of `Option` type and no `#[builder(required)]` annotation is present --> tests/integration/ui/compile_fail/attr_with.rs:67:38 | 67 | #[builder(with = |value: u32| -> Result {})] | ^^^^^^ error: expected one of the following: (1) no return type annotation; this means the closure is expected to return a value of the same type as the member's underlying type(*); (2) `-> *Result<_, {{ErrorType}}>` or `-> *Result<_>` return type annotation; this means the closure is expected to return a `Result` where the `Ok` variant is of the same type as the member's underlying type(*); this syntax allows you to define a fallbile setter (one that returns a `Result`); the `_` placeholder must be spelled literally to mark the underlying type(*) of the member; an optional second generic parameter for the error type is allowed; the return type doesn't have to be named `Result` exactly, the only requirement is that it must have the `Result` suffix; for example if you have a type alias `ApiResult<_>`, then it'll work fine; (*) underlying type is the type of the member stripped from the `Option` wrapper if this member is of `Option` type and no `#[builder(required)]` annotation is present --> tests/integration/ui/compile_fail/attr_with.rs:73:38 | 73 | #[builder(with = |value: u32| -> Result<> {})] | ^^^^^^ error: expected one of the following: (1) no return type annotation; this means the closure is expected to return a value of the same type as the member's underlying type(*); (2) `-> *Result<_, {{ErrorType}}>` or `-> *Result<_>` return type annotation; this means the closure is expected to return a `Result` where the `Ok` variant is of the same type as the member's underlying type(*); this syntax allows you to define a fallbile setter (one that returns a `Result`); the `_` placeholder must be spelled literally to mark the underlying type(*) of the member; an optional second generic parameter for the error type is allowed; the return type doesn't have to be named `Result` exactly, the only requirement is that it must have the `Result` suffix; for example if you have a type alias `ApiResult<_>`, then it'll work fine; (*) underlying type is the type of the member stripped from the `Option` wrapper if this member is of `Option` type and no `#[builder(required)]` annotation is present --> tests/integration/ui/compile_fail/attr_with.rs:79:38 | 79 | #[builder(with = |value: u32| -> ::core::result::Result {})] | ^ error: `with = Some` only works for members with the underlying type of `Option`; --> tests/integration/ui/compile_fail/attr_with.rs:86:12 | 86 | value: u32, | ^^^ error: the underlying type of this member is not `Option`; by default, members of type `Option` are optional and their 'underlying type' is the type under the `Option`; you might be missing #[builder(required)]` annotation for this member --> tests/integration/ui/compile_fail/attr_with.rs:91:22 | 91 | #[builder(with = Some)] | ^^^^ error: the underlying type of this member is not a known collection type; only a collection type that matches the following patterns will be accepted by `#[builder(with = FromIterator::from_iter)], where * at the beginning means the collection type may start with any prefix: - *Map - *Vec - *Set - *Deque - *Heap - *List --> tests/integration/ui/compile_fail/attr_with.rs:98:19 | 98 | value: Option, | ^^^ error: the underlying type of this member is not a known collection type; only a collection type that matches the following patterns will be accepted by `#[builder(with = <_>::from_iter)], where * at the beginning means the collection type may start with any prefix: - *Map - *Vec - *Set - *Deque - *Heap - *List --> tests/integration/ui/compile_fail/attr_with.rs:104:19 | 104 | value: Option, | ^^^ error: `start_fn` attribute can't be specified together with `with` --> tests/integration/ui/compile_fail/attr_with.rs:109:38 | 109 | #[builder(with = |x: u32| x + 1, start_fn)] | ^^^^^^^^ error: `finish_fn` attribute can't be specified together with `with` --> tests/integration/ui/compile_fail/attr_with.rs:115:38 | 115 | #[builder(with = |x: u32| x + 1, finish_fn)] | ^^^^^^^^^ error: `with` attribute can't be specified together with `into` --> tests/integration/ui/compile_fail/attr_with.rs:121:15 | 121 | #[builder(with = |x: u32| x + 1, into)] | ^^^^ error[E0308]: mismatched types --> tests/integration/ui/compile_fail/attr_with.rs:54:12 | 54 | Ok(value) | -- ^^^^^ expected `u32`, found `&str` | | | arguments to this enum variant are incorrect | help: the type constructed contains `&str` due to the type of the argument passed --> tests/integration/ui/compile_fail/attr_with.rs:54:9 | 54 | Ok(value) | ^^^-----^ | | | this argument influences the type of `Ok` note: tuple variant defined here --> $RUST/core/src/result.rs | | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), | ^^ error[E0308]: mismatched types --> tests/integration/ui/compile_fail/attr_with.rs:61:62 | 61 | #[builder(with = |value: impl Into<::core::net::IpAddr>| value)] | ------------------------------ ^^^^^ expected `u32`, found type parameter `impl Into<::core::net::IpAddr>` | | | found this type parameter 62 | value: u32, | --- expected `u32` because of return type | = note: expected type `u32` found type parameter `impl Into<::core::net::IpAddr>` bon-3.7.1/tests/integration/ui/compile_fail/broken_intra_doc_links.rs000064400000000000000000000022541046102023000242120ustar 00000000000000use bon::{bon, builder, Builder}; #[builder] fn broken_link_in_arg_docs( /// [Self] link _arg: u32, ) { } struct BrokenLinkInArgDocs; #[bon] impl BrokenLinkInArgDocs { #[builder] fn broken_link_in_arg_docs( /// [Self] link _arg: u32, ) { } } #[derive(Builder)] struct BrokenLinkInFieldDocs { /// [`Self`] link field: u32, } #[derive(Builder)] struct BrokenLinkInSettersDocs { #[builder(setters(doc { /// [`Self`] link }))] field: u32, } #[derive(Builder)] struct BrokenLinkInSomeFnDocs { #[builder(setters( some_fn(doc { /// [`Self`] link }) ))] field: Option, } #[derive(Builder)] struct BrokenLinkInOptionFnDocs { #[builder(setters( option_fn(doc { /// [`Self`] link }) ))] field: Option, } #[derive(Builder)] #[builder(builder_type(doc { /// [Self] link }))] struct BrokenLinkInBuilderTypeDocs {} #[derive(Builder)] #[builder(finish_fn(doc { /// [Self] link }))] struct BrokenLinkInFinishFnDocs {} #[derive(Builder)] #[builder(state_mod(doc { /// [Self] link }))] struct BrokenLinkInStateModDocs {} fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/broken_intra_doc_links.stderr000064400000000000000000000061241046102023000250710ustar 00000000000000error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:5:5 | 5 | /// [Self] link | ^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:16:9 | 16 | /// [Self] link | ^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:24:5 | 24 | /// [`Self`] link | ^^^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:31:9 | 31 | /// [`Self`] link | ^^^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:40:13 | 40 | /// [`Self`] link | ^^^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:50:13 | 50 | /// [`Self`] link | ^^^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:58:5 | 58 | /// [Self] link | ^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder struct's impl block where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:64:5 | 64 | /// [Self] link | ^^^^^^^^^^^^^^^ error: the documentation should not reference `Self` because it will be moved to the builder's state module where `Self` changes meaning, which may confuse the reader of this code; use explicit type names instead. --> tests/integration/ui/compile_fail/broken_intra_doc_links.rs:70:5 | 70 | /// [Self] link | ^^^^^^^^^^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/collections.rs000064400000000000000000000004301046102023000220200ustar 00000000000000use std::collections::{BTreeMap, BTreeSet}; fn main() { let _repeated_keys_in_map: BTreeMap = bon::map! { "Hello": "Blackjack", "Hello": "Littlepip", }; let _set: BTreeSet = bon::set!["mintals", "guns", "mintals", "roses"]; } bon-3.7.1/tests/integration/ui/compile_fail/collections.stderr000064400000000000000000000014401046102023000227010ustar 00000000000000error: duplicate key in the map --> tests/integration/ui/compile_fail/collections.rs:5:9 | 5 | "Hello": "Blackjack", | ^^^^^^^ error: duplicate key in the map --> tests/integration/ui/compile_fail/collections.rs:6:9 | 6 | "Hello": "Littlepip", | ^^^^^^^ error: duplicate value in the set --> tests/integration/ui/compile_fail/collections.rs:9:44 | 9 | let _set: BTreeSet = bon::set!["mintals", "guns", "mintals", "roses"]; | ^^^^^^^^^ error: duplicate value in the set --> tests/integration/ui/compile_fail/collections.rs:9:63 | 9 | let _set: BTreeSet = bon::set!["mintals", "guns", "mintals", "roses"]; | ^^^^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/derive_builder.rs000064400000000000000000000003151046102023000224700ustar 00000000000000use bon::Builder; #[derive(Builder)] struct TupleStruct(u32, u32); #[derive(Builder)] struct TupleStructsAreUnsupported(u32, u32); #[derive(Builder)] enum EnumsAreUnsupportedWithDerive {} fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/derive_builder.stderr000064400000000000000000000012301046102023000233440ustar 00000000000000error: Only structs with named fields are supported --> tests/integration/ui/compile_fail/derive_builder.rs:4:1 | 4 | struct TupleStruct(u32, u32); | ^^^^^^ error: Only structs with named fields are supported --> tests/integration/ui/compile_fail/derive_builder.rs:7:1 | 7 | struct TupleStructsAreUnsupported(u32, u32); | ^^^^^^ error: only `struct` items are supported by the `#[derive(bon::Builder)]` attribute --> tests/integration/ui/compile_fail/derive_builder.rs:9:10 | 9 | #[derive(Builder)] | ^^^^^^^ | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) bon-3.7.1/tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs000064400000000000000000000005461046102023000252600ustar 00000000000000use bon::Builder; fn main() { #[derive(Builder)] struct Example { x: u32, y: u32, #[builder(name = renamed)] z: u32, } // Test error message about missing members let _ = Example::builder().x(1).build(); // Test error message about repeated setter calls let _ = Example::builder().y(1).y(2); } bon-3.7.1/tests/integration/ui/compile_fail/diagnostic_on_unimplemented.stderr000064400000000000000000000063621046102023000261410ustar 00000000000000error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:14:37 | 14 | let _ = Example::builder().x(1).build(); | ^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required for `SetX` to implement `IsComplete` --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:4:14 | 4 | #[derive(Builder)] | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `ExampleBuilder::::build` --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:4:14 | 4 | #[derive(Builder)] | ^^^^^^^ required by this bound in `ExampleBuilder::::build` 5 | struct Example { | ------- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the member `Unset` was not set, but this method requires it to be set --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:14:37 | 14 | let _ = Example::builder().x(1).build(); | ^^^^^ the member `Unset` was not set, but this method requires it to be set | = help: the trait `IsSet` is not implemented for `Unset` = help: the trait `IsSet` is implemented for `Set` note: required for `SetX` to implement `IsComplete` --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:4:14 | 4 | #[derive(Builder)] | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `ExampleBuilder::::build` --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:4:14 | 4 | #[derive(Builder)] | ^^^^^^^ required by this bound in `ExampleBuilder::::build` 5 | struct Example { | ------- required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the member `Set` was already set, but this method requires it to be unset --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:17:37 | 17 | let _ = Example::builder().y(1).y(2); | ^ the member `Set` was already set, but this method requires it to be unset | = help: the trait `IsUnset` is not implemented for `Set` = help: the trait `IsUnset` is implemented for `Unset` note: required by a bound in `ExampleBuilder::::y` --> tests/integration/ui/compile_fail/diagnostic_on_unimplemented.rs:4:14 | 4 | #[derive(Builder)] | ^^^^^^^ required by this bound in `ExampleBuilder::::y` ... 7 | y: u32, | - required by a bound in this associated function = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) bon-3.7.1/tests/integration/ui/compile_fail/members_order.rs000064400000000000000000000031031046102023000223270ustar 00000000000000use bon::Builder; #[derive(Builder)] struct IncorrectOrder1 { #[builder(start_fn)] _a: (), _b: (), #[builder(start_fn)] _c: (), } #[derive(Builder)] struct IncorrectOrder2 { #[builder(finish_fn)] _a: (), _b: (), #[builder(start_fn)] _c: (), } #[derive(Builder)] struct IncorrectOrder3 { _a: (), #[builder(start_fn)] _b: (), } #[derive(Builder)] struct IncorrectOrder4 { _a: (), #[builder(finish_fn)] _b: (), } #[derive(Builder)] struct IncorrectOrder5 { #[builder(skip)] _a: (), #[builder(start_fn)] _b: (), } #[derive(Builder)] struct IncorrectOrder6 { #[builder(skip)] _a: (), #[builder(finish_fn)] _b: (), } #[derive(Builder)] struct IncorrectOrder7 { #[builder(finish_fn)] _a: (), #[builder(start_fn)] _b: (), } #[derive(Builder)] struct IncorrectOrder8 { #[builder(start_fn)] _a: (), #[builder(finish_fn)] _b: (), #[builder(start_fn)] _c: (), } #[derive(Builder)] struct IncorrectOrder9 { _a: (), #[builder(field)] _b: (), } #[derive(Builder)] struct IncorrectOrder10 { #[builder(start_fn)] _a: (), _b: (), #[builder(field)] _c: (), } #[derive(Builder)] struct IncorrectOrder11 { #[builder(finish_fn)] _a: (), #[builder(field)] _b: (), } #[derive(Builder)] struct IncorrectOrder12 { #[builder(skip)] _a: (), #[builder(field)] _b: (), } #[derive(Builder)] struct IncorrectOrder13 { #[builder(field)] _a: (), _b: (), #[builder(field)] _c: (), } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/members_order.stderr000064400000000000000000000116041046102023000232130ustar 00000000000000error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:8:15 | 8 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:17:15 | 17 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:24:15 | 24 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:31:15 | 31 | #[builder(finish_fn)] | ^^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:39:15 | 39 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:47:15 | 47 | #[builder(finish_fn)] | ^^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:55:15 | 55 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:65:15 | 65 | #[builder(start_fn)] | ^^^^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:72:15 | 72 | #[builder(field)] | ^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:83:15 | 83 | #[builder(field)] | ^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:92:15 | 92 | #[builder(field)] | ^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:102:15 | 102 | #[builder(field)] | ^^^^^ error: incorrect members ordering; expected ordering: (1) members annotated with #[builder(start_fn)] (2) members annotated with #[builder(field)] (3) members annotated with #[builder(finish_fn)] (4) all other members in any order --> tests/integration/ui/compile_fail/members_order.rs:112:15 | 112 | #[builder(field)] | ^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/name_conflicts.rs000064400000000000000000000004621046102023000224730ustar 00000000000000use bon::builder; #[builder] fn body(val: &u32) { let _: &'fn1 u32 = val; } #[builder] fn attr_with(#[builder(with = |val: &'fn1 u32| val)] _val: &u32) {} #[builder] fn attr_default( #[builder(default = { let val: &'fn1 u32 = &32; val })] _val: &u32, ) { } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/name_conflicts.stderr000064400000000000000000000023611046102023000233520ustar 00000000000000error[E0261]: use of undeclared lifetime name `'fn1` --> tests/integration/ui/compile_fail/name_conflicts.rs:5:13 | 3 | #[builder] | - lifetime `'fn1` is missing in item created through this procedural macro 4 | fn body(val: &u32) { 5 | let _: &'fn1 u32 = val; | ^^^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'fn1` --> tests/integration/ui/compile_fail/name_conflicts.rs:9:38 | 8 | #[builder] | ---------- lifetime `'fn1` is missing in item created through this procedural macro 9 | fn attr_with(#[builder(with = |val: &'fn1 u32| val)] _val: &u32) {} | ^^^^ - help: consider introducing lifetime `'fn1` here: `<'fn1>` | | | undeclared lifetime error[E0261]: use of undeclared lifetime name `'fn1` --> tests/integration/ui/compile_fail/name_conflicts.rs:14:19 | 11 | #[builder] | - | | | lifetime `'fn1` is missing in item created through this procedural macro | help: consider introducing lifetime `'fn1` here: `'fn1,` ... 14 | let val: &'fn1 u32 = &32; | ^^^^ undeclared lifetime bon-3.7.1/tests/integration/ui/compile_fail/overwritable/attr_getter.rs000064400000000000000000000002031046102023000245310ustar 00000000000000use bon::Builder; #[derive(Builder)] struct OverwritableCompat { #[builder(getter, overwritable)] x: u32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/overwritable/attr_getter.stderr000064400000000000000000000003301046102023000254110ustar 00000000000000error: `getter` attribute can't be specified together with `overwritable` --> tests/integration/ui/compile_fail/overwritable/attr_getter.rs:5:15 | 5 | #[builder(getter, overwritable)] | ^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/overwritable/attr_on.rs000064400000000000000000000002121046102023000236530ustar 00000000000000use bon::builder; #[builder(on(String, overwritable))] fn unnecessary_overwritable(#[builder(overwritable)] _x: String) {} fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/overwritable/attr_on.stderr000064400000000000000000000005711046102023000245420ustar 00000000000000error: this `#[builder(overwritable)]` attribute is redundant, because `overwritable` is already implied for this member via the `#[builder(on(...))]` at the top of the function --> tests/integration/ui/compile_fail/overwritable/attr_on.rs:4:39 | 4 | fn unnecessary_overwritable(#[builder(overwritable)] _x: String) {} | ^^^^^^^^^^^^ bon-3.7.1/tests/integration/ui/compile_fail/positional_members.rs000064400000000000000000000010441046102023000233770ustar 00000000000000use bon::Builder; struct IntoUnit; impl From for () { fn from(_: IntoUnit) -> Self { () } } pub fn test_type_pattern_matching() { #[derive(Builder)] #[builder(on((), into))] struct TypePatternMatching { #[builder(start_fn)] _a: (), #[builder(start_fn)] _b: Option<()>, #[builder(finish_fn)] _c: (), #[builder(finish_fn)] _d: Option<()>, } TypePatternMatching::builder(IntoUnit, IntoUnit).build(IntoUnit, IntoUnit); } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/positional_members.stderr000064400000000000000000000026601046102023000242630ustar 00000000000000error[E0308]: mismatched types --> tests/integration/ui/compile_fail/positional_members.rs:28:44 | 28 | TypePatternMatching::builder(IntoUnit, IntoUnit).build(IntoUnit, IntoUnit); | ---------------------------- ^^^^^^^^ expected `Option<()>`, found `IntoUnit` | | | arguments to this function are incorrect | = note: expected enum `Option<()>` found struct `IntoUnit` note: associated function defined here --> tests/integration/ui/compile_fail/positional_members.rs:14:12 | 14 | struct TypePatternMatching { | ^^^^^^^^^^^^^^^^^^^ ... 19 | _b: Option<()>, | -------------- error[E0308]: mismatched types --> tests/integration/ui/compile_fail/positional_members.rs:28:70 | 28 | TypePatternMatching::builder(IntoUnit, IntoUnit).build(IntoUnit, IntoUnit); | ----- ^^^^^^^^ expected `Option<()>`, found `IntoUnit` | | | arguments to this method are incorrect | = note: expected enum `Option<()>` found struct `IntoUnit` note: method defined here --> tests/integration/ui/compile_fail/positional_members.rs:14:12 | 14 | struct TypePatternMatching { | ^^^^^^^^^^^^^^^^^^^ ... 25 | _d: Option<()>, | -------------- bon-3.7.1/tests/integration/ui/compile_fail/private_fields_access.rs000064400000000000000000000021761046102023000240340ustar 00000000000000#![deny(warnings)] mod unsafe_fields_are_private { struct Sut; #[bon::bon] impl Sut { #[builder] fn sut(self, #[builder(start_fn)] _x1: u32, _x2: u32) {} } fn _test() { let sut = Sut.sut(99); // Previously, there was an attempt to generate names for private fields // with randomness to ensure users don't try to access them. This however, // conflicts with caching in some build systems. See the following issue // for details: https://github.com/elastio/bon/issues/218 let SutSutBuilder { __unsafe_private_phantom: _, __unsafe_private_named: _, // These are public _x1: _, self_receiver: _, } = sut; } } mod self_receiver_and_start_fn_args_must_be_private { pub struct MustBePrivate; #[bon::bon] impl MustBePrivate { #[builder] pub fn method(self, #[builder(start_fn)] _x1: u32) {} } } fn main() { let builder = self_receiver_and_start_fn_args_must_be_private::MustBePrivate.method(99); let _ = builder.self_receiver; let _ = builder._x1; } bon-3.7.1/tests/integration/ui/compile_fail/private_fields_access.stderr000064400000000000000000000037451046102023000247160ustar 00000000000000error: use of deprecated field `unsafe_fields_are_private::SutSutBuilder::__unsafe_private_phantom`: this field should not be used directly; it's an implementation detail, and if you access it directly, you may break some internal unsafe invariants; if you found yourself needing it, then you are probably doing something wrong; feel free to open an issue/discussion in our GitHub repository (https://github.com/elastio/bon) or ask for help in our Discord server (https://bon-rs.com/discord) --> tests/integration/ui/compile_fail/private_fields_access.rs:20:13 | 20 | __unsafe_private_phantom: _, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/integration/ui/compile_fail/private_fields_access.rs:1:9 | 1 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(deprecated)]` implied by `#[deny(warnings)]` error: use of deprecated field `unsafe_fields_are_private::SutSutBuilder::__unsafe_private_named`: this field should not be used directly; it's an implementation detail, and if you access it directly, you may break some internal unsafe invariants; if you found yourself needing it, then you are probably doing something wrong; feel free to open an issue/discussion in our GitHub repository (https://github.com/elastio/bon) or ask for help in our Discord server (https://bon-rs.com/discord) --> tests/integration/ui/compile_fail/private_fields_access.rs:21:13 | 21 | __unsafe_private_named: _, | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0616]: field `self_receiver` of struct `MustBePrivateMethodBuilder` is private --> tests/integration/ui/compile_fail/private_fields_access.rs:41:21 | 41 | let _ = builder.self_receiver; | ^^^^^^^^^^^^^ private field error[E0616]: field `_x1` of struct `MustBePrivateMethodBuilder` is private --> tests/integration/ui/compile_fail/private_fields_access.rs:42:21 | 42 | let _ = builder._x1; | ^^^ private field bon-3.7.1/tests/integration/ui/compile_fail/std_or_alloc/attr_into_future.rs000064400000000000000000000010111046102023000255370ustar 00000000000000use bon::{bon, builder}; use core::future::IntoFuture; fn _non_send() { struct Sut; fn assert_send(_: &dyn Send) {} #[bon] impl Sut { #[builder(derive(IntoFuture(Box, ?Send)))] async fn sut(&self, value: u32) -> u32 { value * 2 } } assert_send(&Sut.sut().value(21).into_future()); #[builder(derive(IntoFuture(Box, ?Send)))] async fn sut(value: u32) -> u32 { value * 2 } assert_send(&sut().value(21).into_future()); } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/std_or_alloc/attr_into_future.stderr000064400000000000000000000035771046102023000264410ustar 00000000000000error[E0277]: `dyn Future` cannot be sent between threads safely --> tests/integration/ui/compile_fail/std_or_alloc/attr_into_future.rs:17:17 | 17 | assert_send(&Sut.sut().value(21).into_future()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Future` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `dyn Future` = note: required for `Unique>` to implement `Send` note: required because it appears within the type `Box>` --> $RUST/alloc/src/boxed.rs | | pub struct Box< | ^^^ note: required because it appears within the type `Pin>>` --> $RUST/core/src/pin.rs | | pub struct Pin { | ^^^ = note: required for the cast from `&Pin>>` to `&dyn Send` error[E0277]: `(dyn Future + 'static)` cannot be sent between threads safely --> tests/integration/ui/compile_fail/std_or_alloc/attr_into_future.rs:24:17 | 24 | assert_send(&sut().value(21).into_future()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Future + 'static)` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `(dyn Future + 'static)` = note: required for `Unique<(dyn Future + 'static)>` to implement `Send` note: required because it appears within the type `Box<(dyn Future + 'static)>` --> $RUST/alloc/src/boxed.rs | | pub struct Box< | ^^^ note: required because it appears within the type `Pin + 'static)>>` --> $RUST/core/src/pin.rs | | pub struct Pin { | ^^^ = note: required for the cast from `&Pin + 'static)>>` to `&dyn Send` bon-3.7.1/tests/integration/ui/compile_fail/warnings.rs000064400000000000000000000031021046102023000213310ustar 00000000000000#![deny(warnings)] use bon::{bon, builder, Builder}; fn main() { // Test #[must_use] for setters { #[allow(dead_code)] #[derive(Builder)] struct Example { x: u32, y: u32, } #[bon] impl Example { #[builder] #[must_use] fn must_use() -> u32 { 99 } } #[builder] #[must_use] fn must_use() -> u32 { 99 } Example::builder(); Example::must_use(); must_use(); Example::builder().x(1); Example::builder().x(1).y(2).build(); Example::must_use().call(); must_use().call(); __orig_must_use(); #[builder] #[cfg_attr(all(), must_use = "must use message")] fn must_use_under_cfg() -> u32 { 99 } must_use_under_cfg().call(); #[builder] #[cfg_attr(any(), must_use = "unreachable must use")] fn must_use_compiled_out() -> u32 { 99 } must_use_compiled_out().call(); } // Test #[must_use] for getters { #[derive(Builder)] struct Sut { #[builder(getter)] x1: u32, #[builder(getter, default)] x2: u32, #[builder(getter)] x3: Option, } let builder = Sut::builder().x1(1).x2(2).x3(3); // Make sure there are `#[must_use]` warnings builder.get_x1(); builder.get_x2(); builder.get_x3(); } } bon-3.7.1/tests/integration/ui/compile_fail/warnings.stderr000064400000000000000000000112561046102023000222210ustar 00000000000000error: unused `ExampleBuilder` that must be used --> tests/integration/ui/compile_fail/warnings.rs:29:9 | 29 | Example::builder(); | ^^^^^^^^^^^^^^^^^^ | = note: the builder does nothing until you call `build()` on it to finish building note: the lint level is defined here --> tests/integration/ui/compile_fail/warnings.rs:1:9 | 1 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_must_use)]` implied by `#[deny(warnings)]` help: use `let _ = ...` to ignore the resulting value | 29 | let _ = Example::builder(); | +++++++ error: unused `ExampleMustUseBuilder` that must be used --> tests/integration/ui/compile_fail/warnings.rs:30:9 | 30 | Example::must_use(); | ^^^^^^^^^^^^^^^^^^^ | = note: the builder does nothing until you call `call()` on it to finish building help: use `let _ = ...` to ignore the resulting value | 30 | let _ = Example::must_use(); | +++++++ error: unused `MustUseBuilder` that must be used --> tests/integration/ui/compile_fail/warnings.rs:31:9 | 31 | must_use(); | ^^^^^^^^^^ | = note: the builder does nothing until you call `call()` on it to finish building help: use `let _ = ...` to ignore the resulting value | 31 | let _ = must_use(); | +++++++ error: unused `ExampleBuilder` that must be used --> tests/integration/ui/compile_fail/warnings.rs:33:9 | 33 | Example::builder().x(1); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: the builder does nothing until you call `build()` on it to finish building help: use `let _ = ...` to ignore the resulting value | 33 | let _ = Example::builder().x(1); | +++++++ error: unused return value of `ExampleBuilder::::build` that must be used --> tests/integration/ui/compile_fail/warnings.rs:34:9 | 34 | Example::builder().x(1).y(2).build(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: building a struct without using it is likely a bug help: use `let _ = ...` to ignore the resulting value | 34 | let _ = Example::builder().x(1).y(2).build(); | +++++++ error: unused return value of `ExampleMustUseBuilder::::call` that must be used --> tests/integration/ui/compile_fail/warnings.rs:36:9 | 36 | Example::must_use().call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: use `let _ = ...` to ignore the resulting value | 36 | let _ = Example::must_use().call(); | +++++++ error: unused return value of `MustUseBuilder::::call` that must be used --> tests/integration/ui/compile_fail/warnings.rs:38:9 | 38 | must_use().call(); | ^^^^^^^^^^^^^^^^^ | help: use `let _ = ...` to ignore the resulting value | 38 | let _ = must_use().call(); | +++++++ error: unused return value of `__orig_must_use` that must be used --> tests/integration/ui/compile_fail/warnings.rs:39:9 | 39 | __orig_must_use(); | ^^^^^^^^^^^^^^^^^ | help: use `let _ = ...` to ignore the resulting value | 39 | let _ = __orig_must_use(); | +++++++ error: unused return value of `MustUseUnderCfgBuilder::::call` that must be used --> tests/integration/ui/compile_fail/warnings.rs:47:9 | 47 | must_use_under_cfg().call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: must use message help: use `let _ = ...` to ignore the resulting value | 47 | let _ = must_use_under_cfg().call(); | +++++++ error: unused return value of `SutBuilder::::get_x1` that must be used --> tests/integration/ui/compile_fail/warnings.rs:75:9 | 75 | builder.get_x1(); | ^^^^^^^^^^^^^^^^ | = note: this method has no side effects; it only returns a value help: use `let _ = ...` to ignore the resulting value | 75 | let _ = builder.get_x1(); | +++++++ error: unused return value of `SutBuilder::::get_x2` that must be used --> tests/integration/ui/compile_fail/warnings.rs:76:9 | 76 | builder.get_x2(); | ^^^^^^^^^^^^^^^^ | = note: this method has no side effects; it only returns a value help: use `let _ = ...` to ignore the resulting value | 76 | let _ = builder.get_x2(); | +++++++ error: unused return value of `SutBuilder::::get_x3` that must be used --> tests/integration/ui/compile_fail/warnings.rs:77:9 | 77 | builder.get_x3(); | ^^^^^^^^^^^^^^^^ | = note: this method has no side effects; it only returns a value help: use `let _ = ...` to ignore the resulting value | 77 | let _ = builder.get_x3(); | +++++++ bon-3.7.1/tests/integration/ui/compile_fail/wrong_delimiters.rs000064400000000000000000000016471046102023000230720ustar 00000000000000#[derive(bon::Builder)] #[builder( builder_type{}, state_mod{}, start_fn{}, finish_fn{}, )] struct CurlyBraces {} #[derive(bon::Builder)] struct CurlyBracesInField { #[builder(setters{})] x: u32, } #[derive(bon::Builder)] #[builder( builder_type[doc[]], state_mod[doc[]], start_fn[doc[]], finish_fn[doc[]], )] struct SquareBrackets { #[builder(setters[])] x: u32, } #[derive(bon::Builder)] struct SquareBracketsInFieldSetters { #[builder(setters[])] x: u32, } #[derive(bon::Builder)] #[builder( builder_type(doc[]), state_mod(doc[]), start_fn(doc[]), finish_fn(doc[]), )] struct SquareBracketsInFieldDoc { #[builder(setters(doc[]))] x: u32, } #[derive(bon::Builder)] #[builder( builder_type(doc()), state_mod(doc()), start_fn(doc()), finish_fn(doc()) )] struct Parentheses { #[builder(setters(doc()))] x: u32, } fn main() {} bon-3.7.1/tests/integration/ui/compile_fail/wrong_delimiters.stderr000064400000000000000000000076471046102023000237570ustar 00000000000000error: wrong delimiter, expected parentheses e.g. `builder_type(...)`, but got curly braces: `builder_type{...}` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:3:5 | 3 | builder_type{}, | ^^^^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `state_mod(...)`, but got curly braces: `state_mod{...}` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:4:5 | 4 | state_mod{}, | ^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `start_fn(...)`, but got curly braces: `start_fn{...}` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:5:5 | 5 | start_fn{}, | ^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `finish_fn(...)`, but got curly braces: `finish_fn{...}` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:6:5 | 6 | finish_fn{}, | ^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `setters(...)`, but got curly braces: `setters{...}` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:12:15 | 12 | #[builder(setters{})] | ^^^^^^^ error: wrong delimiter, expected parentheses e.g. `builder_type(...)`, but got square brackets: `builder_type[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:18:5 | 18 | builder_type[doc[]], | ^^^^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `state_mod(...)`, but got square brackets: `state_mod[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:19:5 | 19 | state_mod[doc[]], | ^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `start_fn(...)`, but got square brackets: `start_fn[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:20:5 | 20 | start_fn[doc[]], | ^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `finish_fn(...)`, but got square brackets: `finish_fn[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:21:5 | 21 | finish_fn[doc[]], | ^^^^^^^^^ error: wrong delimiter, expected parentheses e.g. `setters(...)`, but got square brackets: `setters[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:30:15 | 30 | #[builder(setters[])] | ^^^^^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got square brackets: `doc[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:36:18 | 36 | builder_type(doc[]), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got square brackets: `doc[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:37:15 | 37 | state_mod(doc[]), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got square brackets: `doc[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:38:14 | 38 | start_fn(doc[]), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got square brackets: `doc[...]` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:39:15 | 39 | finish_fn(doc[]), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got parentheses: `doc(...)` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:48:18 | 48 | builder_type(doc()), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got parentheses: `doc(...)` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:49:15 | 49 | state_mod(doc()), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got parentheses: `doc(...)` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:50:14 | 50 | start_fn(doc()), | ^^^ error: wrong delimiter, expected curly braces e.g. `doc{...}`, but got parentheses: `doc(...)` --> tests/integration/ui/compile_fail/wrong_delimiters.rs:51:15 | 51 | finish_fn(doc()) | ^^^ bon-3.7.1/tests/integration/ui/mod.rs000064400000000000000000000007201046102023000156400ustar 00000000000000#[cfg(not(miri))] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/integration/ui/compile_fail/*.rs"); if cfg!(any(feature = "std", feature = "alloc")) { let t = trybuild::TestCases::new(); t.compile_fail("tests/integration/ui/compile_fail/std_or_alloc/*.rs"); } if cfg!(feature = "experimental-overwritable") { t.compile_fail("tests/integration/ui/compile_fail/overwritable/*.rs"); } }