diff --git a/Cargo.toml b/Cargo.toml index f1fdc317a..387a3629f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ rust-version = "1.88" [workspace.lints.clippy] arithmetic-side-effects.level = "warn" +allow-attributes.level = "warn" [workspace.lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(doc_cfg)'] } diff --git a/sentry-anyhow/src/lib.rs b/sentry-anyhow/src/lib.rs index d5cde23f8..739615eb0 100644 --- a/sentry-anyhow/src/lib.rs +++ b/sentry-anyhow/src/lib.rs @@ -63,12 +63,11 @@ pub fn capture_anyhow(e: &anyhow::Error) -> Uuid { pub fn event_from_error(err: &anyhow::Error) -> Event<'static> { let dyn_err: &dyn std::error::Error = err.as_ref(); - // It's not mutated for not(feature = "backtrace") - #[allow(unused_mut)] - let mut event = sentry_core::event_from_error(dyn_err); + let event = sentry_core::event_from_error(dyn_err); #[cfg(feature = "backtrace")] - { + let event = { + let mut event = event; // exception records are sorted in reverse if let Some(exc) = event.exception.iter_mut().last() { let backtrace = err.backtrace(); @@ -79,7 +78,8 @@ pub fn event_from_error(err: &anyhow::Error) -> Event<'static> { exc.stacktrace = sentry_backtrace::parse_stacktrace(&format!("{backtrace:#}")); } } - } + event + }; event } diff --git a/sentry-contexts/build.rs b/sentry-contexts/build.rs index c42137376..43a7d65f8 100644 --- a/sentry-contexts/build.rs +++ b/sentry-contexts/build.rs @@ -16,6 +16,7 @@ fn main() -> Result<(), Box> { // See https://github.com/rust-lang/rust/issues/46871 let arch = target_bits.next().unwrap(); target_bits.next(); + #[cfg(windows)] let platform = target_bits.next().unwrap(); writeln!( @@ -51,11 +52,12 @@ fn main() -> Result<(), Box> { } )?; - writeln!(f, "/// The platform identifier.")?; - writeln!( - f, - "#[allow(unused)] pub const PLATFORM: &str = \"{platform}\";" - )?; + #[cfg(windows)] + { + writeln!(f, "/// The platform identifier.")?; + writeln!(f, "pub const PLATFORM: &str = \"{platform}\";")?; + } + writeln!(f, "/// The CPU architecture identifier.")?; writeln!(f, "pub const ARCH: &str = \"{arch}\";")?; diff --git a/sentry-core/src/client/batcher.rs b/sentry-core/src/client/batcher.rs index 73132c33a..bedf350fa 100644 --- a/sentry-core/src/client/batcher.rs +++ b/sentry-core/src/client/batcher.rs @@ -65,7 +65,6 @@ where /// Creates a new Batcher that will submit envelopes to the transport. pub(super) fn new(envelope_sender: EnvelopeSender) -> Self { let queue = Arc::new(Mutex::new(BatchQueue { items: Vec::new() })); - #[allow(clippy::mutex_atomic)] let shutdown = Arc::new((Mutex::new(false), Condvar::new())); let worker_envelope_sender = envelope_sender.clone(); diff --git a/sentry-core/src/client/mod.rs b/sentry-core/src/client/mod.rs index 77abec836..bc75919a3 100644 --- a/sentry-core/src/client/mod.rs +++ b/sentry-core/src/client/mod.rs @@ -216,8 +216,7 @@ impl Client { .then(|| Batcher::new(envelope_sender.clone())), ); - #[allow(unused_mut)] - let mut client = Client { + let client = Client { options, envelope_sender, #[cfg(feature = "release-health")] @@ -235,16 +234,16 @@ impl Client { }; #[cfg(feature = "logs")] - client.cache_default_log_attributes(); + let client = client.with_cached_default_log_attributes(); #[cfg(feature = "metrics")] - client.cache_default_metric_attributes(); + let client = client.with_cached_default_metric_attributes(); client } #[cfg(feature = "logs")] - fn cache_default_log_attributes(&mut self) { + fn with_cached_default_log_attributes(mut self) -> Self { let mut attributes = BTreeMap::new(); if let Some(environment) = self.options.environment.as_ref() { @@ -292,10 +291,12 @@ impl Client { } self.default_log_attributes = Some(attributes); + + self } #[cfg(feature = "metrics")] - fn cache_default_metric_attributes(&mut self) { + fn with_cached_default_metric_attributes(mut self) -> Self { let always_present_attributes = [ ("sentry.sdk.name", &self.sdk_info.name), ("sentry.sdk.version", &self.sdk_info.version), @@ -314,6 +315,8 @@ impl Client { self.default_metric_attributes = maybe_present_attributes .chain(always_present_attributes) .collect(); + + self } pub(crate) fn get_integration(&self) -> Option<&I> @@ -389,6 +392,7 @@ impl Client { } } + #[cfg(feature = "release-health")] if let Some(scope) = scope { scope.update_session_from_event(&event); } diff --git a/sentry-core/src/error.rs b/sentry-core/src/error.rs index 0540c569b..78e4a7dcd 100644 --- a/sentry-core/src/error.rs +++ b/sentry-core/src/error.rs @@ -9,8 +9,9 @@ impl Hub { /// /// See the global [`capture_error`](fn.capture_error.html) /// for more documentation. - #[allow(unused)] pub fn capture_error(&self, error: &E) -> Uuid { + #[cfg(not(feature = "client"))] + let _ = error; with_client_impl! {{ self.inner.with(|stack| { let top = stack.top(); @@ -46,7 +47,6 @@ impl Hub { /// ``` /// /// [sentry event payloads]: https://develop.sentry.dev/sdk/event-payloads/exception/ -#[allow(unused_variables)] pub fn capture_error(error: &E) -> Uuid { Hub::with_active(|hub| hub.capture_error(error)) } diff --git a/sentry-core/src/macros.rs b/sentry-core/src/macros.rs index 8789e0f67..d593b1049 100644 --- a/sentry-core/src/macros.rs +++ b/sentry-core/src/macros.rs @@ -93,7 +93,7 @@ macro_rules! debug_assert_or_log { }}; } -#[allow(unused_macros)] +#[cfg(not(feature = "client"))] macro_rules! minimal_unreachable { () => { panic!( diff --git a/sentry-core/src/scope/real.rs b/sentry-core/src/scope/real.rs index 76482e1b9..44ebfd33e 100644 --- a/sentry-core/src/scope/real.rs +++ b/sentry-core/src/scope/real.rs @@ -456,9 +456,8 @@ impl Scope { self.span.as_ref().clone() } - #[allow(unused_variables)] + #[cfg(feature = "release-health")] pub(crate) fn update_session_from_event(&self, event: &Event<'static>) { - #[cfg(feature = "release-health")] if let Some(session) = self.session.lock().unwrap().as_mut() { session.update_from_event(event); } diff --git a/sentry-core/src/session.rs b/sentry-core/src/session.rs index 1238ec800..05590ad41 100644 --- a/sentry-core/src/session.rs +++ b/sentry-core/src/session.rs @@ -201,7 +201,6 @@ mod session_impl { /// Creates a new Flusher that will submit envelopes to the transport. pub fn new(envelope_sender: EnvelopeSender, mode: SessionMode) -> Self { let queue = Arc::new(Mutex::new(Default::default())); - #[allow(clippy::mutex_atomic)] let shutdown = Arc::new((Mutex::new(false), Condvar::new())); let worker_envelope_sender = envelope_sender.clone(); diff --git a/sentry-core/src/test.rs b/sentry-core/src/test.rs index ccd78037c..76319b2cc 100644 --- a/sentry-core/src/test.rs +++ b/sentry-core/src/test.rs @@ -49,7 +49,6 @@ pub struct TestTransport { impl TestTransport { /// Creates a new test transport. - #[allow(clippy::new_ret_no_self)] pub fn new() -> Arc { Arc::new(TestTransport { collected: Mutex::new(vec![]), diff --git a/sentry-log/src/logger.rs b/sentry-log/src/logger.rs index d7bc24404..81f3ff751 100644 --- a/sentry-log/src/logger.rs +++ b/sentry-log/src/logger.rs @@ -28,7 +28,7 @@ bitflags! { /// The type of Data Sentry should ingest for a [`log::Record`]. #[derive(Debug)] #[non_exhaustive] -#[allow(clippy::large_enum_variant)] +#[expect(clippy::large_enum_variant)] pub enum RecordMapping { /// Ignore the [`Record`]. Ignore, @@ -89,7 +89,7 @@ impl log::Log for NoopLogger { pub struct SentryLogger { dest: L, filter: Box) -> LogFilter + Send + Sync>, - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] mapper: Option) -> Vec + Send + Sync>>, } diff --git a/sentry-slog/src/drain.rs b/sentry-slog/src/drain.rs index 827cc9cf1..97558f7b2 100644 --- a/sentry-slog/src/drain.rs +++ b/sentry-slog/src/drain.rs @@ -17,7 +17,7 @@ pub enum LevelFilter { } /// The type of Data Sentry should ingest for a [`slog::Record`]. -#[allow(clippy::large_enum_variant)] +#[expect(clippy::large_enum_variant)] pub enum RecordMapping { /// Ignore the [`Record`]. Ignore, @@ -44,7 +44,7 @@ pub fn default_filter(level: slog::Level) -> LevelFilter { pub struct SentryDrain { drain: D, filter: Box LevelFilter + Send + Sync>, - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] mapper: Option RecordMapping + Send + Sync>>, } diff --git a/sentry-tracing/src/converters.rs b/sentry-tracing/src/converters.rs index 9ae410946..c29366793 100644 --- a/sentry-tracing/src/converters.rs +++ b/sentry-tracing/src/converters.rs @@ -38,7 +38,7 @@ fn level_to_log_level(level: &tracing_core::Level) -> LogLevel { } /// Converts a [`tracing_core::Level`] to the corresponding Sentry [`Exception::ty`] entry. -#[allow(unused)] +#[cfg(feature = "backtrace")] fn level_to_exception_type(level: &tracing_core::Level) -> &'static str { match *level { tracing_core::Level::TRACE => "tracing::trace!", @@ -285,8 +285,7 @@ where // proper grouping and issue metadata generation. tracing_core::Record does not contain sufficient // information for this. However, it may contain a serialized error which we can parse to emit // an exception record. - #[allow(unused_mut)] - let (mut message, visitor) = extract_event_data_with_context(event, ctx.into(), false); + let (message, visitor) = extract_event_data_with_context(event, ctx.into(), false); let FieldVisitor { mut exceptions, mut json_values, @@ -299,26 +298,30 @@ where // We should only do this if we're capturing stack traces, otherwise the issue title will be `` // as Sentry will attempt to use missing stack trace to determine the title. #[cfg(feature = "backtrace")] - if !exceptions.is_empty() && message.is_some() { - if let Some(client) = sentry_core::Hub::current().client() { - if client.options().attach_stacktrace { - let thread = sentry_backtrace::current_thread(true); - let exception = Exception { - ty: level_to_exception_type(event.metadata().level()).to_owned(), - value: message.take(), - module: event.metadata().module_path().map(str::to_owned), - stacktrace: thread.stacktrace, - raw_stacktrace: thread.raw_stacktrace, - thread_id: thread.id, - mechanism: Some(Mechanism { - synthetic: Some(true), - ..Mechanism::default() - }), - }; - exceptions.push(exception) + let message = { + let mut message = message; + if !exceptions.is_empty() && message.is_some() { + if let Some(client) = sentry_core::Hub::current().client() { + if client.options().attach_stacktrace { + let thread = sentry_backtrace::current_thread(true); + let exception = Exception { + ty: level_to_exception_type(event.metadata().level()).to_owned(), + value: message.take(), + module: event.metadata().module_path().map(str::to_owned), + stacktrace: thread.stacktrace, + raw_stacktrace: thread.raw_stacktrace, + thread_id: thread.id, + mechanism: Some(Mechanism { + synthetic: Some(true), + ..Mechanism::default() + }), + }; + exceptions.push(exception) + } } } - } + message + }; if let Some(exception) = exceptions.last_mut() { "tracing".clone_into( diff --git a/sentry-tracing/src/layer/mod.rs b/sentry-tracing/src/layer/mod.rs index fba1a4e0a..e6f22b70d 100644 --- a/sentry-tracing/src/layer/mod.rs +++ b/sentry-tracing/src/layer/mod.rs @@ -38,7 +38,7 @@ bitflags! { /// The type of data Sentry should ingest for an [`Event`]. #[derive(Debug)] #[non_exhaustive] -#[allow(clippy::large_enum_variant)] +#[expect(clippy::large_enum_variant)] pub enum EventMapping { /// Ignore the [`Event`] Ignore, diff --git a/sentry-types/src/macros.rs b/sentry-types/src/macros.rs index 4a66553b7..5d41eb229 100644 --- a/sentry-types/src/macros.rs +++ b/sentry-types/src/macros.rs @@ -23,7 +23,6 @@ macro_rules! impl_str_ser { /// If a type implements `FromStr` then this automatically /// implements a deserializer for that type that dispatches /// appropriately. -#[allow(unused_macros)] macro_rules! impl_str_de { ($type:ty) => { impl<'de> ::serde::de::Deserialize<'de> for $type { @@ -44,7 +43,6 @@ macro_rules! impl_str_de { /// If a type implements `FromStr` and `Display` then this automatically /// implements a serializer/deserializer for that type that dispatches /// appropriately. -#[allow(unused_macros)] macro_rules! impl_str_serde { ($type:ty) => { impl_str_ser!($type); diff --git a/sentry-types/src/protocol/envelope.rs b/sentry-types/src/protocol/envelope.rs index e76ce3549..e3ef41521 100644 --- a/sentry-types/src/protocol/envelope.rs +++ b/sentry-types/src/protocol/envelope.rs @@ -155,7 +155,7 @@ struct EnvelopeItemHeader { /// for more details. #[derive(Clone, Debug, PartialEq)] #[non_exhaustive] -#[allow(clippy::large_enum_variant)] +#[expect(clippy::large_enum_variant)] pub enum EnvelopeItem { /// An Event Item. /// @@ -206,7 +206,6 @@ pub enum ItemContainer { Metrics(Vec), } -#[allow(clippy::len_without_is_empty, reason = "is_empty is not needed")] impl ItemContainer { /// The number of items in this item container. pub fn len(&self) -> usize { @@ -231,6 +230,14 @@ impl ItemContainer { Self::Metrics(_) => "application/vnd.sentry.items.trace-metric+json", } } + + /// Determine if the item container is empty. + pub fn is_empty(&self) -> bool { + match self { + Self::Logs(logs) => logs.is_empty(), + Self::Metrics(metrics) => metrics.is_empty(), + } + } } impl From> for ItemContainer { diff --git a/sentry-types/src/protocol/session.rs b/sentry-types/src/protocol/session.rs index 948efd301..2bd0f4a57 100644 --- a/sentry-types/src/protocol/session.rs +++ b/sentry-types/src/protocol/session.rs @@ -132,7 +132,7 @@ pub struct SessionUpdate<'a> { pub attributes: SessionAttributes<'a>, } -#[allow(clippy::trivially_copy_pass_by_ref)] +#[expect(clippy::trivially_copy_pass_by_ref, reason = "serde requires this API")] fn is_zero(val: &u32) -> bool { *val == 0 }