diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f9d4b93a..1b0557fb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ env: # If the compilation fails, then the version specified here needs to be bumped up to reality. # Be sure to also update the rust-version property in the workspace Cargo.toml file, # plus all the README.md files of the affected packages. - RUST_MIN_VER: "1.79" + RUST_MIN_VER: "1.81" # List of packages that will be checked with the minimum supported Rust version. # This should be limited to packages that are intended for publishing. RUST_MIN_VER_PKGS: "-p xilem -p xilem_core -p masonry" diff --git a/Cargo.toml b/Cargo.toml index 7ac58af30..d03900522 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,86 +20,85 @@ members = [ [workspace.package] edition = "2021" # Keep in sync with RUST_MIN_VER in .github/workflows/ci.yml, with the relevant README.md files. -rust-version = "1.79" +rust-version = "1.81" license = "Apache-2.0" repository = "https://github.com/linebender/xilem" homepage = "https://xilem.dev/" [workspace.lints] -rust.unexpected_cfgs = { level = "warn", check-cfg = [ - 'cfg(FALSE)', - 'cfg(tarpaulin_include)', -] } # unsafe code is not allowed in Xilem or Masonry # We would like to set this to `forbid`, but we have to use `deny` because `android_activity` # requires us to use the unsafe `#[no_mangle]` attribute # (And cargo doesn't let us have platform specific lints here) rust.unsafe_code = "deny" +# Intentional break from the lint set. Intended to be temporary +rust.unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(FALSE)', + 'cfg(tarpaulin_include)', +] } + +# LINEBENDER LINT SET - v1 +# See https://linebender.org/wiki/canonical-lints/ rust.keyword_idents_2024 = "forbid" rust.non_ascii_idents = "forbid" -rust.unsafe_op_in_unsafe_fn = "forbid" rust.non_local_definitions = "forbid" +rust.unsafe_op_in_unsafe_fn = "forbid" -rust.unused_lifetimes = "warn" +rust.elided_lifetimes_in_paths = "warn" +rust.let_underscore_drop = "warn" +rust.missing_debug_implementations = "warn" +rust.missing_docs = "warn" +rust.single_use_lifetimes = "warn" +rust.trivial_numeric_casts = "warn" +# rust.unexpected_cfgs = "warn" rust.unit_bindings = "warn" +rust.unnameable_types = "warn" +rust.unreachable_pub = "warn" rust.unused_import_braces = "warn" -rust.trivial_numeric_casts = "warn" +rust.unused_lifetimes = "warn" rust.unused_macro_rules = "warn" +rust.unused_qualifications = "warn" rust.variant_size_differences = "warn" +clippy.allow_attributes = "warn" clippy.allow_attributes_without_reason = "warn" +clippy.cast_possible_truncation = "warn" clippy.collection_is_never_read = "warn" +clippy.dbg_macro = "warn" clippy.debug_assert_with_mut_call = "warn" clippy.doc_markdown = "warn" +clippy.exhaustive_enums = "warn" clippy.fn_to_numeric_cast_any = "forbid" clippy.infinite_loop = "warn" clippy.large_include_file = "warn" clippy.large_stack_arrays = "warn" +clippy.match_same_arms = "warn" clippy.mismatching_type_param_order = "warn" +clippy.missing_assert_message = "warn" +clippy.missing_errors_doc = "warn" clippy.missing_fields_in_debug = "warn" +clippy.missing_panics_doc = "warn" +clippy.partial_pub_fields = "warn" +clippy.return_self_not_must_use = "warn" clippy.same_functions_in_if_condition = "warn" clippy.semicolon_if_nothing_returned = "warn" +clippy.shadow_unrelated = "warn" clippy.should_panic_without_expect = "warn" +clippy.todo = "warn" clippy.unseparated_literal_suffix = "warn" +clippy.use_self = "warn" +clippy.wildcard_imports = "warn" -# Follow-ups for their own PRs, too noisy to go in lint group PR - -# rust.let_underscore_drop = "warn" -# rust.missing_debug_implementations = "warn" -# rust.unused_qualifications = "warn" -# rust.single_use_lifetimes = "warn" -# clippy.exhaustive_enums = "warn" -# clippy.dbg_macro = "warn" -# clippy.match_same_arms = "warn" -# clippy.cast_possible_truncation = "warn" -# clippy.missing_assert_message = "warn" -# clippy.return_self_not_must_use = "warn" -# clippy.wildcard_imports = "warn" -# rust.elided_lifetimes_in_paths = "warn" -# clippy.use_self = "warn" - -# Aspirational lints, not enabled for one reason or another - -# rust.missing_docs = "warn" # We have many as-yet undocumented items -# rust.unreachable_pub = "warn" # Potentially controversial code style -# rust.unnameable_types = "warn" # Requires lint_reasons rustc feature for exceptions -# clippy.todo = "warn" # We have a lot of "real" todos -# clippy.missing_errors_doc = "warn" # Can be quite noisy? -# clippy.missing_panics_doc = "warn" # Can be quite noisy? -# clippy.partial_pub_fields = "warn" # Potentially controversial code style -# clippy.shadow_unrelated = "warn" # Potentially controversial code style - -# This catches duplicated dependencies in the tree, which we don't have much control over -# We should use cargo deny for this, anyway -# clippy.cargo = "warn" +clippy.cargo_common_metadata = "warn" +clippy.negative_feature_names = "warn" +clippy.redundant_feature_names = "warn" +clippy.wildcard_dependencies = "warn" +# END LINEBENDER LINT SET -# Lints which we still set in individual crates lib.rs -# False positives with example targets - https://github.com/rust-lang/rust/issues/57274 -# rust.unused_crate_dependencies = "warn" -# Examples often do want to print -# clippy.print_stdout = "warn" -# clippy.print_stderr = "warn" +# "https://github.com/rust-lang/rust-clippy/issues/13355" +# Please remove once 1.83 is stable +clippy.duplicated_attributes = "allow" [workspace.dependencies] masonry = { version = "0.2.0", path = "masonry" } diff --git a/README.md b/README.md index df495b7fa..337b7a7ce 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ sudo apt-get install clang libwayland-dev libxkbcommon-x11-dev libvulkan-dev ## Minimum supported Rust Version (MSRV) -This version of Xilem has been verified to compile with **Rust 1.79** and later. +This version of Xilem has been verified to compile with **Rust 1.81** and later. Future versions of Xilem might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases. diff --git a/masonry/README.md b/masonry/README.md index c1d2f8737..a27f5febb 100644 --- a/masonry/README.md +++ b/masonry/README.md @@ -108,7 +108,7 @@ The following feature flags are available: ## Minimum supported Rust Version (MSRV) -This version of Masonry has been verified to compile with **Rust 1.79** and later. +This version of Masonry has been verified to compile with **Rust 1.81** and later. Future versions of Masonry might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases. diff --git a/masonry/examples/calc_masonry.rs b/masonry/examples/calc_masonry.rs index d9a4376a0..543903d74 100644 --- a/masonry/examples/calc_masonry.rs +++ b/masonry/examples/calc_masonry.rs @@ -5,7 +5,12 @@ // On Windows platform, don't show a console when opening the app. #![windows_subsystem = "windows"] -#![allow(variant_size_differences, clippy::single_match)] +#![allow( + variant_size_differences, + clippy::single_match, + reason = "Don't matter for example code" +)] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] use accesskit::{DefaultActionVerb, NodeBuilder, Role}; use masonry::dpi::LogicalSize; @@ -373,7 +378,7 @@ fn build_calc() -> impl Widget { ) } -pub fn main() { +fn main() { let window_size = LogicalSize::new(223., 300.); let window_attributes = Window::default_attributes() diff --git a/masonry/examples/custom_widget.rs b/masonry/examples/custom_widget.rs index 14596cdda..7d3508b57 100644 --- a/masonry/examples/custom_widget.rs +++ b/masonry/examples/custom_widget.rs @@ -6,6 +6,9 @@ // On Windows platform, don't show a console when opening the app. #![windows_subsystem = "windows"] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::shadow_unrelated, reason = "Deferred: Noisy")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] use accesskit::{NodeBuilder, Role}; use masonry::kurbo::{BezPath, Stroke}; @@ -141,7 +144,7 @@ impl Widget for CustomWidget { } } -pub fn main() { +fn main() { let my_string = "Masonry + Vello".to_string(); let window_attributes = Window::default_attributes().with_title("Fancy colors"); diff --git a/masonry/examples/grid_masonry.rs b/masonry/examples/grid_masonry.rs index 7e5a2d8c3..85a2b0fc5 100644 --- a/masonry/examples/grid_masonry.rs +++ b/masonry/examples/grid_masonry.rs @@ -41,7 +41,7 @@ fn grid_button(params: GridParams) -> Button { )) } -pub fn main() { +fn main() { let label = SizedBox::new( Prose::new("Change spacing by right and left clicking on the buttons") .with_text_size(14.0) diff --git a/masonry/examples/hello_masonry.rs b/masonry/examples/hello_masonry.rs index 89aadd34b..832d65de7 100644 --- a/masonry/examples/hello_masonry.rs +++ b/masonry/examples/hello_masonry.rs @@ -30,7 +30,7 @@ impl AppDriver for Driver { } } -pub fn main() { +fn main() { let label = Label::new("Hello") .with_text_size(32.0) .with_weight(Weight::BOLD); diff --git a/masonry/examples/simple_image.rs b/masonry/examples/simple_image.rs index 1d0e14281..46ac1ee04 100644 --- a/masonry/examples/simple_image.rs +++ b/masonry/examples/simple_image.rs @@ -20,7 +20,7 @@ impl AppDriver for Driver { fn on_action(&mut self, _ctx: &mut DriverCtx<'_>, _widget_id: WidgetId, _action: Action) {} } -pub fn main() { +fn main() { let image_bytes = include_bytes!("./assets/PicWithAlpha.png"); let image_data = image::load_from_memory(image_bytes).unwrap().to_rgba8(); let (width, height) = image_data.dimensions(); diff --git a/masonry/examples/to_do_list.rs b/masonry/examples/to_do_list.rs index 7cec9cd84..57a9c294f 100644 --- a/masonry/examples/to_do_list.rs +++ b/masonry/examples/to_do_list.rs @@ -6,6 +6,7 @@ // On Windows platform, don't show a console when opening the app. #![windows_subsystem = "windows"] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] use masonry::dpi::LogicalSize; use masonry::widget::{Button, Flex, Label, Portal, RootWidget, Textbox, WidgetMut}; @@ -41,7 +42,7 @@ impl AppDriver for Driver { } } -pub fn main() { +fn main() { let main_widget = Portal::new( Flex::column() .with_child( diff --git a/masonry/examples/two_textboxes.rs b/masonry/examples/two_textboxes.rs index ab510205f..f06366cc7 100644 --- a/masonry/examples/two_textboxes.rs +++ b/masonry/examples/two_textboxes.rs @@ -20,7 +20,7 @@ impl AppDriver for Driver { fn on_action(&mut self, _ctx: &mut DriverCtx<'_>, _widget_id: WidgetId, _action: Action) {} } -pub fn main() { +fn main() { let main_widget = Flex::column() .with_child(Textbox::new("")) .with_child(Textbox::new("")) diff --git a/masonry/src/debug_logger.rs b/masonry/src/debug_logger.rs index d69582148..212b568b5 100644 --- a/masonry/src/debug_logger.rs +++ b/masonry/src/debug_logger.rs @@ -1,8 +1,7 @@ // Copyright 2022 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -#![allow(missing_docs)] - +#![expect(unused, reason = "Vestigial functionality")] use std::collections::HashMap; use std::sync::Arc; diff --git a/masonry/src/lib.rs b/masonry/src/lib.rs index 9c577b6aa..56072dad6 100644 --- a/masonry/src/lib.rs +++ b/masonry/src/lib.rs @@ -88,28 +88,67 @@ //! [Druid]: https://crates.io/crates/druid //! [Xilem]: https://crates.io/crates/xilem -// TODO: Remove this once the issues within masonry are fixed. Tracked in https://github.com/linebender/xilem/issues/449 -#![allow(rustdoc::broken_intra_doc_links)] -#![deny(clippy::trivially_copy_pass_by_ref)] -// #![deny(rustdoc::broken_intra_doc_links)] -// #![warn(missing_docs)] -#![warn(unused_imports)] -#![warn(clippy::print_stdout, clippy::print_stderr, clippy::dbg_macro)] -#![allow(clippy::needless_doctest_main)] -#![allow(clippy::should_implement_trait)] -#![allow(clippy::single_match)] #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![cfg_attr(not(debug_assertions), allow(unused))] -// False-positive with dev-dependencies only used in examples -#![cfg_attr(not(test), warn(unused_crate_dependencies))] +// LINEBENDER LINT SET - v1 +// See https://linebender.org/wiki/canonical-lints/ +// These lints aren't included in Cargo.toml because they +// shouldn't apply to examples and tests +#![warn(unused_crate_dependencies)] +#![warn(clippy::print_stdout, clippy::print_stderr)] +#![cfg_attr( + test, + expect( + unused_crate_dependencies, + reason = "False-positive with dev-dependencies only used in examples" + ) +)] +#![expect(clippy::allow_attributes, reason = "Deferred: Noisy")] +#![expect(clippy::allow_attributes_without_reason, reason = "Deferred: Noisy")] +// TODO: Remove any items listed as "Deferred" +#![expect( + rustdoc::broken_intra_doc_links, + reason = "Deferred: Noisy. Tracked in https://github.com/linebender/xilem/issues/449" +)] +#![expect(clippy::needless_doctest_main, reason = "Deferred: Noisy")] +#![expect(clippy::should_implement_trait, reason = "Deferred: Noisy")] +#![cfg_attr(not(debug_assertions), expect(unused, reason = "Deferred: Noisy"))] +#![expect(let_underscore_drop, reason = "Deferred: Noisy")] +#![expect(missing_debug_implementations, reason = "Deferred: Noisy")] +#![expect(unused_qualifications, reason = "Deferred: Noisy")] +#![expect(single_use_lifetimes, reason = "Deferred: Noisy")] +#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] +#![expect(clippy::return_self_not_must_use, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +// https://github.com/rust-lang/rust/pull/130025 +#![allow(missing_docs, reason = "We have many as-yet undocumented items")] +#![expect(unreachable_pub, reason = "Potentially controversial code style")] +#![expect( + unnameable_types, + reason = "Requires lint_reasons rustc feature for exceptions" +)] +#![expect(clippy::todo, reason = "We have a lot of 'real' todos")] +#![expect(clippy::missing_errors_doc, reason = "Can be quite noisy?")] +#![expect(clippy::missing_panics_doc, reason = "Can be quite noisy?")] +#![expect( + clippy::partial_pub_fields, + reason = "Potentially controversial code style" +)] +#![expect( + clippy::shadow_unrelated, + reason = "Potentially controversial code style" +)] +#![expect(clippy::single_match, reason = "General policy not decided")] // TODO - Add logo #[macro_use] mod util; -#[allow(unused)] mod debug_logger; #[allow(unused)] mod debug_values; diff --git a/masonry/src/testing/helper_widgets.rs b/masonry/src/testing/helper_widgets.rs index a2cf4745c..dbaba17ee 100644 --- a/masonry/src/testing/helper_widgets.rs +++ b/masonry/src/testing/helper_widgets.rs @@ -21,6 +21,9 @@ use widget::WidgetRef; use crate::event::{PointerEvent, TextEvent}; use crate::widget::SizedBox; + +// TODO: Expect doesn't work here +#[allow(clippy::wildcard_imports, reason = "Deferred: Noisy")] use crate::*; pub type PointerEventFn = dyn FnMut(&mut S, &mut EventCtx, &PointerEvent); diff --git a/masonry/src/text/backspace.rs b/masonry/src/text/backspace.rs index 287022f4a..0c70bb80d 100644 --- a/masonry/src/text/backspace.rs +++ b/masonry/src/text/backspace.rs @@ -3,6 +3,11 @@ //! Calc start of a backspace delete interval +// TODO: `expect` doesn't work here +#[allow( + clippy::wildcard_imports, + reason = "Mostly a wrapper around xi_unicode." +)] use xi_unicode::*; use crate::text::StringCursor; diff --git a/xilem/README.md b/xilem/README.md index 41b48cb57..fe60f3785 100644 --- a/xilem/README.md +++ b/xilem/README.md @@ -33,7 +33,7 @@ Lots of things need improvements. ## Minimum supported Rust Version (MSRV) -This version of Xilem has been verified to compile with **Rust 1.79** and later. +This version of Xilem has been verified to compile with **Rust 1.81** and later. Future versions of Xilem might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases. diff --git a/xilem/examples/calc.rs b/xilem/examples/calc.rs index 0d2bea396..a7e1a4746 100644 --- a/xilem/examples/calc.rs +++ b/xilem/examples/calc.rs @@ -1,6 +1,11 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A simple calculator example +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] + use masonry::widget::{CrossAxisAlignment, GridParams, MainAxisAlignment}; use winit::dpi::LogicalSize; use winit::error::EventLoopError; @@ -301,21 +306,22 @@ fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { Ok(()) } -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -325,11 +331,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/examples/components.rs b/xilem/examples/components.rs index 28468c403..cab739c93 100644 --- a/xilem/examples/components.rs +++ b/xilem/examples/components.rs @@ -3,6 +3,8 @@ //! Modularizing state can be done with `lens` which allows using modular components. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use masonry::widget::MainAxisAlignment; use winit::error::EventLoopError; use xilem::core::lens; diff --git a/xilem/examples/elm.rs b/xilem/examples/elm.rs index 68c68052e..0eddc643d 100644 --- a/xilem/examples/elm.rs +++ b/xilem/examples/elm.rs @@ -5,6 +5,8 @@ //! You can also emulate the elm architecture for a subset of your app. //! Though usually it's more idiomatic to modularize state with `map_state` and update state directly within event callbacks, as seen in the `components` example. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use masonry::widget::{CrossAxisAlignment, MainAxisAlignment}; use winit::error::EventLoopError; use xilem::core::{adapt, map_action, MessageResult}; diff --git a/xilem/examples/external_event_loop.rs b/xilem/examples/external_event_loop.rs index e92458a5b..1f22ffbf8 100644 --- a/xilem/examples/external_event_loop.rs +++ b/xilem/examples/external_event_loop.rs @@ -5,6 +5,8 @@ //! Currently, this supports running as its own window alongside an existing application, or //! accessing raw events from winit. //! Support for more custom embeddings would be welcome, but needs more design work +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use std::sync::Arc; use masonry::event_loop_runner::MasonryUserEvent; diff --git a/xilem/examples/flex.rs b/xilem/examples/flex.rs index 2a704ee8e..003513cd0 100644 --- a/xilem/examples/flex.rs +++ b/xilem/examples/flex.rs @@ -1,6 +1,9 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! Flex properties can be set in Xilem. + +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] use masonry::text::ArcStr; use masonry::widget::{CrossAxisAlignment, MainAxisAlignment}; use winit::error::EventLoopError; diff --git a/xilem/examples/http_cats.rs b/xilem/examples/http_cats.rs index 83a3b1631..a6d869527 100644 --- a/xilem/examples/http_cats.rs +++ b/xilem/examples/http_cats.rs @@ -4,6 +4,10 @@ //! An example demonstrating the use of Async web requests in Xilem to access the API. //! This also demonstrates image loading. +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] + use std::sync::Arc; use vello::peniko::{Blob, Image}; @@ -244,21 +248,22 @@ const STATUS_CODES_CSV: &str = include_str!(concat!( "/resources/data/http_cats_status/status.csv", )); -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -268,11 +273,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/examples/mason.rs b/xilem/examples/mason.rs index 6cde49206..c1bb393ee 100644 --- a/xilem/examples/mason.rs +++ b/xilem/examples/mason.rs @@ -1,11 +1,15 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A playground used in the development for new Xilem Masonry features. + // On Windows platform, don't show a console when opening the app. #![windows_subsystem = "windows"] +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] use std::time::Duration; +use winit::error::EventLoopError; use xilem::core::{fork, run_once}; use xilem::tokio::time; use xilem::view::{ @@ -137,7 +141,7 @@ struct AppData { active: bool, } -fn run(event_loop: EventLoopBuilder) { +fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { let data = AppData { count: 0, textbox_contents: "Not quite a placeholder".into(), @@ -147,41 +151,30 @@ fn run(event_loop: EventLoopBuilder) { Xilem::new(data, app_logic) .background_color(Color::rgb8(0x20, 0x20, 0x20)) .run_windowed(event_loop, "First Example".into()) - .unwrap(); } -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop -fn main() { - run(EventLoop::with_user_event()); +fn main() -> Result<(), EventLoopError> { + run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - -#[cfg(target_os = "android")] -use winit::platform::android::activity::AndroidApp; - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] -fn android_main(app: AndroidApp) { +fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; let mut event_loop = EventLoop::with_user_event(); event_loop.with_android_app(app); - run(event_loop); -} - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() + run(event_loop).expect("Can create app"); } diff --git a/xilem/examples/memoization.rs b/xilem/examples/memoization.rs index 7ae4192c2..97f9e5c2b 100644 --- a/xilem/examples/memoization.rs +++ b/xilem/examples/memoization.rs @@ -1,6 +1,9 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! You can use memoization to avoid allocations. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use std::sync::Arc; use xilem::core::{frozen, memoize}; diff --git a/xilem/examples/state_machine.rs b/xilem/examples/state_machine.rs index 02a58643b..22007fc8a 100644 --- a/xilem/examples/state_machine.rs +++ b/xilem/examples/state_machine.rs @@ -3,6 +3,8 @@ //! A state machine to detect whether the button was pressed an even or an odd number of times. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use winit::error::EventLoopError; use xilem::core::one_of::{OneOf, OneOf3}; use xilem::view::{button, flex, label, prose, sized_box, spinner}; diff --git a/xilem/examples/stopwatch.rs b/xilem/examples/stopwatch.rs index edcb93e07..6fbb8772d 100644 --- a/xilem/examples/stopwatch.rs +++ b/xilem/examples/stopwatch.rs @@ -3,6 +3,8 @@ //! A stopwatch to display elapsed time. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use std::ops::{Add, Sub}; use std::time::{Duration, SystemTime}; @@ -222,21 +224,22 @@ fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { Ok(()) } -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -246,11 +249,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/examples/to_do_mvc.rs b/xilem/examples/to_do_mvc.rs index 73fd288a5..0f51f8b06 100644 --- a/xilem/examples/to_do_mvc.rs +++ b/xilem/examples/to_do_mvc.rs @@ -1,8 +1,11 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A to-do-list app, loosely inspired by todomvc. + // On Windows platform, don't show a console when opening the app. #![windows_subsystem = "windows"] +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] use winit::error::EventLoopError; use xilem::view::{button, checkbox, flex, textbox, Axis, FlexSpacer}; @@ -98,21 +101,22 @@ fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { app.run_windowed(event_loop, "First Example".into()) } -// Boilerplate code for android: Identical across all applications +// Boilerplate code: Identical across all applications which support Android -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -122,11 +126,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/examples/variable_clock.rs b/xilem/examples/variable_clock.rs index 5d22f8c92..42dde45a1 100644 --- a/xilem/examples/variable_clock.rs +++ b/xilem/examples/variable_clock.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 //! This example uses variable fonts in a touch sensitive digital clock. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] use std::time::Duration; @@ -33,7 +34,7 @@ struct TimeZone { /// An approximate region which this offset applies to. region: &'static str, /// The offset from UTC - offset: time::UtcOffset, + offset: UtcOffset, } fn app_logic(data: &mut Clocks) -> impl WidgetView { @@ -199,7 +200,7 @@ fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { const fn tz(region: &'static str, offset: i8) -> TimeZone { TimeZone { region, - offset: match time::UtcOffset::from_hms(offset, 0, 0) { + offset: match UtcOffset::from_hms(offset, 0, 0) { Ok(it) => it, Err(_) => { panic!("Component out of range."); @@ -234,21 +235,22 @@ const TIMEZONES: &[TimeZone] = &[ tz("Tonga", 13), ]; -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -258,11 +260,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/examples/widgets.rs b/xilem/examples/widgets.rs index eb3686797..846938e4c 100644 --- a/xilem/examples/widgets.rs +++ b/xilem/examples/widgets.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 //! A widget gallery for xilem/masonry +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] use masonry::dpi::LogicalSize; use masonry::event_loop_runner::{EventLoop, EventLoopBuilder}; @@ -105,21 +106,22 @@ fn run(event_loop: EventLoopBuilder) -> Result<(), EventLoopError> { Ok(()) } -#[cfg(not(target_os = "android"))] -#[allow(dead_code)] +// Boilerplate code: Identical across all applications which support Android + +#[expect(clippy::allow_attributes, reason = "No way to specify the condition")] +#[allow(dead_code, reason = "False positive: needed in not-_android version")] // This is treated as dead code by the Android version of the example, but is actually live // This hackery is required because Cargo doesn't care to support this use case, of one // example which works across Android and desktop fn main() -> Result<(), EventLoopError> { run(EventLoop::with_user_event()) } - -// Boilerplate code for android: Identical across all applications - #[cfg(target_os = "android")] // Safety: We are following `android_activity`'s docs here -// We believe that there are no other declarations using this name in the compiled objects here -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "We believe that there are no other declarations using this name in the compiled objects here" +)] #[no_mangle] fn android_main(app: winit::platform::android::activity::AndroidApp) { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -129,11 +131,3 @@ fn android_main(app: winit::platform::android::activity::AndroidApp) { run(event_loop).expect("Can create app"); } - -// TODO: This is a hack because of how we handle our examples in Cargo.toml -// Ideally, we change Cargo to be more sensible here? -#[cfg(target_os = "android")] -#[allow(dead_code)] -fn main() { - unreachable!() -} diff --git a/xilem/src/lib.rs b/xilem/src/lib.rs index 2e6138bb4..acb9d937e 100644 --- a/xilem/src/lib.rs +++ b/xilem/src/lib.rs @@ -1,11 +1,42 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -// False-positive with dev-dependencies only used in examples -#![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![warn(unnameable_types, unreachable_pub)] -#![warn(clippy::print_stdout, clippy::print_stderr, clippy::dbg_macro)] +#![deny(clippy::trivially_copy_pass_by_ref)] +// LINEBENDER LINT SET - v1 +// See https://linebender.org/wiki/canonical-lints/ +// These lints aren't included in Cargo.toml because they +// shouldn't apply to examples and tests +#![warn(unused_crate_dependencies)] +#![warn(clippy::print_stdout, clippy::print_stderr)] +#![cfg_attr( + test, + expect( + unused_crate_dependencies, + reason = "False-positive with dev-dependencies only used in examples" + ) +)] +// TODO: Remove any items listed as "Deferred" +#![cfg_attr(not(debug_assertions), allow(unused))] +#![expect(missing_debug_implementations, reason = "Deferred: Noisy")] +#![expect(unused_qualifications, reason = "Deferred: Noisy")] +#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] +#![expect(clippy::return_self_not_must_use, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +// https://github.com/rust-lang/rust/pull/130025 +#![allow(missing_docs, reason = "We have many as-yet undocumented items")] +#![expect(clippy::missing_errors_doc, reason = "Can be quite noisy?")] +#![expect(clippy::missing_panics_doc, reason = "Can be quite noisy?")] +#![expect( + clippy::shadow_unrelated, + reason = "Potentially controversial code style" +)] +#![expect(clippy::allow_attributes, reason = "Deferred: Noisy")] +#![expect(clippy::allow_attributes_without_reason, reason = "Deferred: Noisy")] use std::collections::HashMap; use std::sync::Arc; diff --git a/xilem_core/README.md b/xilem_core/README.md index f8c19cef4..fd684d181 100644 --- a/xilem_core/README.md +++ b/xilem_core/README.md @@ -47,7 +47,7 @@ If you wish to use Xilem Core in environments where an allocator is not availabl ## Minimum supported Rust Version (MSRV) -This version of Xilem Core has been verified to compile with **Rust 1.79** and later. +This version of Xilem Core has been verified to compile with **Rust 1.81** and later. Future versions of Xilem Core might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases. diff --git a/xilem_core/examples/filesystem.rs b/xilem_core/examples/filesystem.rs index 35d5851ef..58bd853f7 100644 --- a/xilem_core/examples/filesystem.rs +++ b/xilem_core/examples/filesystem.rs @@ -1,6 +1,12 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! An example using Xilem Core to manipulate a filesystem. + +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(let_underscore_drop, reason = "Deferred: Noisy")] + use std::io::stdin; use std::path::PathBuf; @@ -34,7 +40,7 @@ fn app_logic(state: &mut State) -> impl FileView { seq: (), }) */ { - todo!() + unimplemented!() } State::Complex(value) => Box::new(complex_state(value.as_str())), }; diff --git a/xilem_core/examples/user_interface.rs b/xilem_core/examples/user_interface.rs index f461732e8..f0707a83b 100644 --- a/xilem_core/examples/user_interface.rs +++ b/xilem_core/examples/user_interface.rs @@ -3,6 +3,8 @@ //! Model version of Masonry for exploration +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] + use core::any::Any; use xilem_core::{ @@ -10,11 +12,11 @@ use xilem_core::{ ViewPathTracker, }; -pub fn app_logic(_: &mut u32) -> impl WidgetView { +fn app_logic(_: &mut u32) -> impl WidgetView { Button {} } -pub fn main() { +fn main() { let view = app_logic(&mut 10); let mut ctx = ViewCtx { path: vec![] }; let (_widget_tree, _state) = view.build(&mut ctx); @@ -22,13 +24,13 @@ pub fn main() { } // Toy version of Masonry -pub trait Widget: 'static + Any { +trait Widget: 'static + Any { fn as_mut_any(&mut self) -> &mut dyn Any; } -pub struct WidgetPod { +struct WidgetPod { widget: W, } -pub struct WidgetMut<'a, W: Widget> { +struct WidgetMut<'a, W: Widget> { value: &'a mut W, } impl Widget for Box { @@ -89,9 +91,9 @@ impl View for Button { } } -pub struct Button {} +struct Button {} -pub struct ButtonWidget {} +struct ButtonWidget {} impl Widget for ButtonWidget { fn as_mut_any(&mut self) -> &mut dyn Any { self @@ -118,7 +120,7 @@ impl SuperElement, ViewCtx> for WidgetPod, } @@ -136,7 +138,7 @@ impl ViewPathTracker for ViewCtx { } } -pub trait WidgetView: +trait WidgetView: View> + Send + Sync { type Widget: Widget + Send + Sync; diff --git a/xilem_core/src/lib.rs b/xilem_core/src/lib.rs index e156381f5..4007b0c44 100644 --- a/xilem_core/src/lib.rs +++ b/xilem_core/src/lib.rs @@ -1,11 +1,6 @@ // Copyright 2022 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -#![cfg_attr(not(test), no_std)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![forbid(unsafe_code)] -#![warn(missing_docs, unreachable_pub, unused_crate_dependencies)] -#![warn(clippy::print_stdout, clippy::print_stderr, clippy::dbg_macro)] // https://linebender.org/blog/doc-include //! //! [LICENSE]: https://github.com/linebender/xilem/blob/main/xilem_core/LICENSE @@ -18,7 +13,31 @@ //! .rustdoc-hidden { display: none; } //! #![doc = include_str!("../README.md")] - +#![cfg_attr(not(test), no_std)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] +// LINEBENDER LINT SET - v1 +// See https://linebender.org/wiki/canonical-lints/ +// These lints aren't included in Cargo.toml because they +// shouldn't apply to examples and tests +#![warn(unused_crate_dependencies)] +#![warn(clippy::print_stdout, clippy::print_stderr)] +// TODO: Remove any items listed as "Deferred" +#![deny(clippy::trivially_copy_pass_by_ref)] +#![expect(missing_debug_implementations, reason = "Deferred: Noisy")] +#![expect(unused_qualifications, reason = "Deferred: Noisy")] +#![expect(single_use_lifetimes, reason = "Deferred: Noisy")] +#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +#![expect(clippy::missing_errors_doc, reason = "Can be quite noisy?")] +#![expect( + clippy::shadow_unrelated, + reason = "Potentially controversial code style" +)] +#![expect(clippy::allow_attributes, reason = "Deferred: Noisy")] +#![expect(clippy::allow_attributes_without_reason, reason = "Deferred: Noisy")] extern crate alloc; mod deferred; diff --git a/xilem_core/tests/array_sequence.rs b/xilem_core/tests/array_sequence.rs index ab8152dd6..bba2de5d8 100644 --- a/xilem_core/tests/array_sequence.rs +++ b/xilem_core/tests/array_sequence.rs @@ -1,6 +1,11 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +#![expect( + clippy::shadow_unrelated, + reason = "Deferred: Noisy. Fix is to use scopes" +)] + mod common; use common::*; use xilem_core::View; diff --git a/xilem_core/tests/base_sequence.rs b/xilem_core/tests/base_sequence.rs index 2b0eb9b72..8f05dba78 100644 --- a/xilem_core/tests/base_sequence.rs +++ b/xilem_core/tests/base_sequence.rs @@ -5,6 +5,11 @@ //! //! [`ViewSequence`]: xilem_core::ViewSequence +#![expect( + clippy::shadow_unrelated, + reason = "Deferred: Noisy. Fix is to use scopes" +)] + mod common; use common::*; use xilem_core::{MessageResult, View}; diff --git a/xilem_core/tests/common/mod.rs b/xilem_core/tests/common/mod.rs index ee5d65723..2c59bedcd 100644 --- a/xilem_core/tests/common/mod.rs +++ b/xilem_core/tests/common/mod.rs @@ -1,8 +1,17 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -#![allow(dead_code)] // This is a utility module, which means that some exposed items aren't +#![allow( + dead_code, + reason = "This is a utility module, which means that some exposed items aren't used in all instantiations" +)] #![deny(unreachable_pub)] +#![expect(clippy::allow_attributes, reason = "Deferred: Noisy")] +#![expect(clippy::allow_attributes_without_reason, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +#![expect(single_use_lifetimes, reason = "Deferred: Noisy")] use xilem_core::*; diff --git a/xilem_core/tests/one_of.rs b/xilem_core/tests/one_of.rs index 45bc4c7bd..900f9401d 100644 --- a/xilem_core/tests/one_of.rs +++ b/xilem_core/tests/one_of.rs @@ -5,6 +5,10 @@ //! //! This is an integration test so that it can use the infrastructure in [`common`]. +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] + use xilem_core::one_of::{OneOf, OneOf2, OneOfCtx, PhantomElementCtx}; use xilem_core::{MessageResult, Mut, View, ViewId}; diff --git a/xilem_core/tests/orphan.rs b/xilem_core/tests/orphan.rs index f3768d948..3c4862c6c 100644 --- a/xilem_core/tests/orphan.rs +++ b/xilem_core/tests/orphan.rs @@ -6,6 +6,9 @@ //! //! This is an integration test so that it can use the infrastructure in [`common`]. +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] + use xilem_core::{DynMessage, MessageResult, Mut, OrphanView, View, ViewId, ViewPathTracker}; mod common; diff --git a/xilem_core/tests/tuple_sequence.rs b/xilem_core/tests/tuple_sequence.rs index af1976e6a..c9d9fcc90 100644 --- a/xilem_core/tests/tuple_sequence.rs +++ b/xilem_core/tests/tuple_sequence.rs @@ -1,6 +1,11 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +#![expect( + clippy::shadow_unrelated, + reason = "Deferred: Noisy. Fix is to use scopes" +)] + mod common; use common::*; use xilem_core::View; diff --git a/xilem_core/tests/vec_sequence.rs b/xilem_core/tests/vec_sequence.rs index ba7330618..6e01df399 100644 --- a/xilem_core/tests/vec_sequence.rs +++ b/xilem_core/tests/vec_sequence.rs @@ -1,6 +1,11 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +#![expect( + clippy::shadow_unrelated, + reason = "Deferred: Noisy. Fix is to use scopes" +)] + mod common; use common::*; use xilem_core::{MessageResult, View}; diff --git a/xilem_web/README.md b/xilem_web/README.md index b610aa4ac..871ca890c 100644 --- a/xilem_web/README.md +++ b/xilem_web/README.md @@ -52,7 +52,7 @@ pub fn main() { ## Minimum supported Rust Version (MSRV) -This version of Xilem Web has been verified to compile with **Rust 1.79** and later. +This version of Xilem Web has been verified to compile with **Rust 1.81** and later. Future versions of Xilem Web might increase the Rust version requirement. It will not be treated as a breaking change and as such can even happen with small patch releases. diff --git a/xilem_web/src/lib.rs b/xilem_web/src/lib.rs index 80c1fa31f..344149286 100644 --- a/xilem_web/src/lib.rs +++ b/xilem_web/src/lib.rs @@ -12,6 +12,40 @@ //! #![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +// LINEBENDER LINT SET - v1 +// See https://linebender.org/wiki/canonical-lints/ +// These lints aren't included in Cargo.toml because they +// shouldn't apply to examples and tests +#![warn(unused_crate_dependencies)] +#![warn(clippy::print_stdout, clippy::print_stderr)] +// TODO: Remove any items listed as "Deferred" +#![cfg_attr(test, expect(clippy::print_stdout, reason = "Deferred: Noisy"))] +#![expect(let_underscore_drop, reason = "Deferred: Noisy")] +#![expect(missing_debug_implementations, reason = "Deferred: Noisy")] +#![expect(unused_qualifications, reason = "Deferred: Noisy")] +#![expect(single_use_lifetimes, reason = "Deferred: Noisy")] +#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] +#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] +#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")] +#![expect(clippy::return_self_not_must_use, reason = "Deferred: Noisy")] +#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")] +#![expect(clippy::use_self, reason = "Deferred: Noisy")] +// expect doesn't work here: https://github.com/rust-lang/rust/pull/130025 +#![allow(missing_docs, reason = "We have many as-yet undocumented items")] +#![expect(unreachable_pub, reason = "Potentially controversial code style")] +#![expect( + unnameable_types, + reason = "Requires lint_reasons rustc feature for exceptions" +)] +#![expect(clippy::todo, reason = "We have a lot of 'real' todos")] +#![expect(clippy::missing_panics_doc, reason = "Can be quite noisy?")] +#![expect( + clippy::shadow_unrelated, + reason = "Potentially controversial code style" +)] +#![expect(clippy::allow_attributes, reason = "Deferred: Noisy")] +#![expect(clippy::allow_attributes_without_reason, reason = "Deferred: Noisy")] use std::{any::Any, ops::Deref as _}; diff --git a/xilem_web/web_examples/counter/src/main.rs b/xilem_web/web_examples/counter/src/main.rs index d9dfda7e8..08d27aea5 100644 --- a/xilem_web/web_examples/counter/src/main.rs +++ b/xilem_web/web_examples/counter/src/main.rs @@ -1,6 +1,9 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A simple counter +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use xilem_web::{ document_body, elements::html as el, @@ -72,7 +75,7 @@ fn app_logic(state: &mut AppState) -> impl DomFragment { ) } -pub fn main() { +fn main() { console_error_panic_hook::set_once(); App::new(document_body(), AppState::default(), app_logic).run(); } diff --git a/xilem_web/web_examples/counter_custom_element/src/main.rs b/xilem_web/web_examples/counter_custom_element/src/main.rs index a09cea4e6..7ba4d0b3f 100644 --- a/xilem_web/web_examples/counter_custom_element/src/main.rs +++ b/xilem_web/web_examples/counter_custom_element/src/main.rs @@ -1,6 +1,10 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! Shows creating a element by raw tag name. This can be useful for web components + +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use xilem_web::{ document_body, elements::custom_element, @@ -46,7 +50,7 @@ fn app_logic(state: &mut AppState) -> impl DomView { ) } -pub fn main() { +fn main() { console_error_panic_hook::set_once(); App::new(document_body(), AppState::default(), app_logic).run(); } diff --git a/xilem_web/web_examples/elm/src/main.rs b/xilem_web/web_examples/elm/src/main.rs index 116c5efcb..ad81cc32e 100644 --- a/xilem_web/web_examples/elm/src/main.rs +++ b/xilem_web/web_examples/elm/src/main.rs @@ -50,7 +50,7 @@ fn counter_view(count: i32) -> impl HtmlDivElement { )) } -pub fn main() { +fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); log::info!("Start web application"); diff --git a/xilem_web/web_examples/fetch/src/main.rs b/xilem_web/web_examples/fetch/src/main.rs index e630a5262..cd1c8a157 100644 --- a/xilem_web/web_examples/fetch/src/main.rs +++ b/xilem_web/web_examples/fetch/src/main.rs @@ -1,6 +1,12 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! Demonstrates fetching other web content from Xilem Web + +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] +// TODO: `expect` doesn't work here for unknown reasons +#![allow(clippy::wildcard_imports, reason = "HTML elements are an exception")] + use gloo_net::http::Request; use serde::{Deserialize, Serialize}; use wasm_bindgen::{JsCast, UnwrapThrowExt}; @@ -16,10 +22,10 @@ use xilem_web::{ const TOO_MANY_CATS: usize = 8; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Cat { - pub url: String, - pub width: u16, - pub height: u16, +struct Cat { + url: String, + width: u16, + height: u16, } struct AppState { @@ -88,7 +94,7 @@ async fn fetch_cats(count: usize) -> Result, gloo_net::Error> { .collect()) } -pub fn input_target(event: &T) -> web_sys::HtmlInputElement +fn input_target(event: &T) -> web_sys::HtmlInputElement where T: JsCast, { @@ -209,7 +215,7 @@ fn cat_fetch_controls(state: &AppState) -> impl Element { .class("cat-fetch-controls") } -pub fn main() { +fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); diff --git a/xilem_web/web_examples/mathml_svg/src/main.rs b/xilem_web/web_examples/mathml_svg/src/main.rs index fcd9eba7d..4ca395885 100644 --- a/xilem_web/web_examples/mathml_svg/src/main.rs +++ b/xilem_web/web_examples/mathml_svg/src/main.rs @@ -1,6 +1,13 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! Shows using mathml and SVG on the web + +// TODO: `expect` doesn't work here for unknown reasons +#![allow(clippy::wildcard_imports, reason = "HTML elements are an exception")] +#![expect(clippy::cast_possible_truncation, reason = "Deferred: Noisy")] +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use wasm_bindgen::{JsCast, UnwrapThrowExt}; use xilem_web::{ document_body, elements::html, elements::mathml as ml, elements::svg, interfaces::*, @@ -48,7 +55,7 @@ fn slider( .on_input(cb) } -pub fn main() { +fn main() { console_error_panic_hook::set_once(); App::new(document_body(), Triangle { a: 200, b: 100 }, |t| { let x1 = 390; diff --git a/xilem_web/web_examples/spawn_tasks/src/main.rs b/xilem_web/web_examples/spawn_tasks/src/main.rs index 10fee7578..76e67912f 100644 --- a/xilem_web/web_examples/spawn_tasks/src/main.rs +++ b/xilem_web/web_examples/spawn_tasks/src/main.rs @@ -4,6 +4,8 @@ //! This example shows how (external) tasks can send messages //! to be able to change the app state. +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + use futures::{select, FutureExt}; use gloo_timers::future::TimeoutFuture; use xilem_web::{ @@ -35,10 +37,6 @@ async fn create_ping_task(proxy: TaskProxy, shutdown_signal: ShutdownSignal) { log::debug!("Start ping task"); let mut abort = shutdown_signal.into_future().fuse(); - #[allow( - clippy::infinite_loop, - // reason = "False-Positive of clippy, not recognizing that the loop will be aborted" - )] loop { let mut timeout = TimeoutFuture::new(1_000).fuse(); @@ -83,8 +81,7 @@ fn app_logic(state: &mut AppState) -> impl Element { }, )) } - -pub fn main() { +fn main() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); log::info!("Start web application"); diff --git a/xilem_web/web_examples/svgtoy/src/main.rs b/xilem_web/web_examples/svgtoy/src/main.rs index 460d56e02..f430ae746 100644 --- a/xilem_web/web_examples/svgtoy/src/main.rs +++ b/xilem_web/web_examples/svgtoy/src/main.rs @@ -1,6 +1,10 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A simple example showing the interaction between SVG and event handling +// TODO: `expect` doesn't work here +#![allow(clippy::wildcard_imports, reason = "HTML elements are an exception")] + use xilem_web::{ document_body, elements::svg::{g, svg, text}, @@ -96,7 +100,7 @@ fn app_logic(state: &mut AppState) -> impl DomView { .attr("height", 600) } -pub fn main() { +fn main() { console_error_panic_hook::set_once(); App::new(document_body(), AppState::default(), app_logic).run(); } diff --git a/xilem_web/web_examples/todomvc/src/main.rs b/xilem_web/web_examples/todomvc/src/main.rs index 97c4d990d..6c9e98091 100644 --- a/xilem_web/web_examples/todomvc/src/main.rs +++ b/xilem_web/web_examples/todomvc/src/main.rs @@ -1,6 +1,13 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +//! A recreation of todomvc in Xilem Web +// TODO: Link + +// TODO: `expect` doesn't work here +#![allow(clippy::wildcard_imports, reason = "HTML elements are an exception")] +#![expect(clippy::shadow_unrelated, reason = "Idiomatic for Xilem users")] + mod state; use state::{AppState, Filter, Todo}; @@ -208,7 +215,7 @@ fn app_logic(state: &mut AppState) -> impl DomView { )) } -pub fn main() { +fn main() { console_error_panic_hook::set_once(); tracing_wasm::set_as_global_default(); App::new(get_element_by_id("todoapp"), AppState::load(), app_logic).run(); diff --git a/xilem_web/web_examples/todomvc/src/state.rs b/xilem_web/web_examples/todomvc/src/state.rs index f27b1a6e1..122b3ad05 100644 --- a/xilem_web/web_examples/todomvc/src/state.rs +++ b/xilem_web/web_examples/todomvc/src/state.rs @@ -1,6 +1,8 @@ // Copyright 2023 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 +#![expect(clippy::partial_pub_fields, reason = "Deferred: Noisy")] + use serde::{Deserialize, Serialize}; use wasm_bindgen::UnwrapThrowExt;