diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-02-01 16:08:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-01 16:08:04 +0100 |
| commit | eb01fe85f721bb669305ff30cb0081d15495919f (patch) | |
| tree | b590ff9e86a417f4fb3d041a7a621b7fccb297d9 | |
| parent | 741b62af0749ddf88ebbd7cad6ec7a15ab1fc1cb (diff) | |
| parent | 94b0a7b8e9affe00c83c7afdb725edd530d855ee (diff) | |
| download | rust-eb01fe85f721bb669305ff30cb0081d15495919f.tar.gz rust-eb01fe85f721bb669305ff30cb0081d15495919f.zip | |
Rollup merge of #93267 - lcnr:auto-trait-lint, r=nikomatsakis
implement a lint for suspicious auto trait impls cc https://github.com/rust-lang/rust/pull/85048#issuecomment-1019805102 r? ``@nikomatsakis``
| -rw-r--r-- | compiler/rustc_index/src/bit_set.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 43 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/lib.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/lint.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/trait_def.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/coherence/orphan.rs | 213 | ||||
| -rw-r--r-- | src/test/ui/auto-traits/suspicious-impls-lint.rs | 34 | ||||
| -rw-r--r-- | src/test/ui/auto-traits/suspicious-impls-lint.stderr | 52 | ||||
| -rw-r--r-- | src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr | 8 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs | 1 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr | 52 |
12 files changed, 421 insertions, 58 deletions
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 5aa213cb701..cf86c450a5b 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -938,6 +938,12 @@ pub struct GrowableBitSet<T: Idx> { bit_set: BitSet<T>, } +impl<T: Idx> Default for GrowableBitSet<T> { + fn default() -> Self { + GrowableBitSet::new_empty() + } +} + impl<T: Idx> GrowableBitSet<T> { /// Ensure that the set can hold at least `min_domain_size` elements. pub fn ensure(&mut self, min_domain_size: usize) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 4af68233f0d..f4eba25475e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1793,6 +1793,10 @@ declare_lint! { Warn, "detects name collision with an existing but unstable method", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::Custom( + "once this associated item is added to the standard library, \ + the ambiguity may cause an error or change in behavior!" + ), reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>", // Note: this item represents future incompatibility of all unstable functions in the // standard library, and thus should never be removed or changed to an error. @@ -2335,6 +2339,10 @@ declare_lint! { Warn, "reservation of a two-phased borrow conflicts with other shared borrows", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::Custom( + "this borrowing pattern was not meant to be accepted, \ + and may become a hard error in the future" + ), reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>", }; } @@ -3046,6 +3054,7 @@ declare_lint_pass! { DEREF_INTO_DYN_SUPERTRAIT, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DUPLICATE_MACRO_ATTRIBUTES, + SUSPICIOUS_AUTO_TRAIT_IMPLS, ] } @@ -3622,3 +3631,37 @@ declare_lint! { Warn, "duplicated attribute" } + +declare_lint! { + /// The `suspicious_auto_trait_impls` lint checks for potentially incorrect + /// implementations of auto traits. + /// + /// ### Example + /// + /// ```rust + /// struct Foo<T>(T); + /// + /// unsafe impl<T> Send for Foo<*const T> {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A type can implement auto traits, e.g. `Send`, `Sync` and `Unpin`, + /// in two different ways: either by writing an explicit impl or if + /// all fields of the type implement that auto trait. + /// + /// The compiler disables the automatic implementation if an explicit one + /// exists for given type constructor. The exact rules governing this + /// are currently unsound and quite subtle and and will be modified in the future. + /// This change will cause the automatic implementation to be disabled in more + /// cases, potentially breaking some code. + pub SUSPICIOUS_AUTO_TRAIT_IMPLS, + Warn, + "the rules governing auto traits will change in the future", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange, + reference: "issue #93367 <https://github.com/rust-lang/rust/issues/93367>", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 3b5d636124d..1f834b7212f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -163,12 +163,17 @@ pub enum FutureIncompatibilityReason { /// This will be an error in a future release, and /// Cargo should create a report even for dependencies FutureReleaseErrorReportNow, + /// Code that changes meaning in some way in a + /// future release. + FutureReleaseSemanticsChange, /// Previously accepted code that will become an /// error in the provided edition EditionError(Edition), /// Code that changes meaning in some way in /// the provided edition EditionSemanticsChange(Edition), + /// A custom reason. + Custom(&'static str), } impl FutureIncompatibilityReason { diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index c6226c69f30..17c77c1bbd8 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -221,7 +221,6 @@ pub fn struct_lint_level<'s, 'd>( decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>, ) { // Check for future incompatibility lints and issue a stronger warning. - let lint_id = LintId::of(lint); let future_incompatible = lint.future_incompatible; let has_future_breakage = future_incompatible.map_or( @@ -345,31 +344,29 @@ pub fn struct_lint_level<'s, 'd>( err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); if let Some(future_incompatible) = future_incompatible { - let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { - "once this associated item is added to the standard library, the ambiguity may \ - cause an error or change in behavior!" - .to_owned() - } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { - "this borrowing pattern was not meant to be accepted, and may become a hard error \ - in the future" - .to_owned() - } else if let FutureIncompatibilityReason::EditionError(edition) = - future_incompatible.reason - { - let current_edition = sess.edition(); - format!( - "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!", - current_edition, edition - ) - } else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) = - future_incompatible.reason - { - format!("this changes meaning in Rust {}", edition) - } else { - "this was previously accepted by the compiler but is being phased out; \ - it will become a hard error in a future release!" - .to_owned() + let explanation = match future_incompatible.reason { + FutureIncompatibilityReason::FutureReleaseError + | FutureIncompatibilityReason::FutureReleaseErrorReportNow => { + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in a future release!" + .to_owned() + } + FutureIncompatibilityReason::FutureReleaseSemanticsChange => { + "this will change its meaning in a future release!".to_owned() + } + FutureIncompatibilityReason::EditionError(edition) => { + let current_edition = sess.edition(); + format!( + "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!", + current_edition, edition + ) + } + FutureIncompatibilityReason::EditionSemanticsChange(edition) => { + format!("this changes meaning in Rust {}", edition) + } + FutureIncompatibilityReason::Custom(reason) => reason.to_owned(), }; + if future_incompatible.explain_reason { err.warn(&explanation); } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 9f8053d4a4e..9e32c0162e6 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -144,6 +144,23 @@ impl<'tcx> TyCtxt<'tcx> { }); } + pub fn non_blanket_impls_for_ty( + self, + def_id: DefId, + self_ty: Ty<'tcx>, + ) -> impl Iterator<Item = DefId> + 'tcx { + let impls = self.trait_impls_of(def_id); + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, SimplifyParams::No, StripReferences::No) + { + if let Some(impls) = impls.non_blanket_impls.get(&simp) { + return impls.iter().copied(); + } + } + + [].iter().copied() + } + /// Applies function to every impl that could possibly match the self type `self_ty` and returns /// the first non-none value. pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>( diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index e954b4cf512..777bd640669 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -1,24 +1,33 @@ //! Orphan checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_errors::ErrorReported; use rustc_hir as hir; +use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::TyCtxtInferExt; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::def_id::LocalDefId; +use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; +use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor}; +use rustc_session::lint; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; use rustc_trait_selection::traits; +use std::ops::ControlFlow; pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] { let mut errors = Vec::new(); - for (_trait, impls_of_trait) in tcx.all_local_trait_impls(()) { + for (&trait_def_id, impls_of_trait) in tcx.all_local_trait_impls(()) { for &impl_of_trait in impls_of_trait { match orphan_check_impl(tcx, impl_of_trait) { Ok(()) => {} Err(ErrorReported) => errors.push(impl_of_trait), } } + + if tcx.trait_is_auto(trait_def_id) { + lint_auto_trait_impls(tcx, trait_def_id, impls_of_trait); + } } tcx.arena.alloc_slice(&errors) } @@ -265,3 +274,201 @@ fn emit_orphan_check_error<'tcx>( Err(ErrorReported) } + +#[derive(Default)] +struct AreUniqueParamsVisitor { + seen: GrowableBitSet<u32>, +} + +#[derive(Copy, Clone)] +enum NotUniqueParam<'tcx> { + DuplicateParam(GenericArg<'tcx>), + NotParam(GenericArg<'tcx>), +} + +impl<'tcx> TypeVisitor<'tcx> for AreUniqueParamsVisitor { + type BreakTy = NotUniqueParam<'tcx>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + match t.kind() { + ty::Param(p) => { + if self.seen.insert(p.index) { + ControlFlow::CONTINUE + } else { + ControlFlow::Break(NotUniqueParam::DuplicateParam(t.into())) + } + } + _ => ControlFlow::Break(NotUniqueParam::NotParam(t.into())), + } + } + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + match r { + ty::ReEarlyBound(p) => { + if self.seen.insert(p.index) { + ControlFlow::CONTINUE + } else { + ControlFlow::Break(NotUniqueParam::DuplicateParam(r.into())) + } + } + _ => ControlFlow::Break(NotUniqueParam::NotParam(r.into())), + } + } + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + match c.val { + ty::ConstKind::Param(p) => { + if self.seen.insert(p.index) { + ControlFlow::CONTINUE + } else { + ControlFlow::Break(NotUniqueParam::DuplicateParam(c.into())) + } + } + _ => ControlFlow::Break(NotUniqueParam::NotParam(c.into())), + } + } +} + +/// Lint impls of auto traits if they are likely to have +/// unsound or surprising effects on auto impls. +fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) { + let mut non_covering_impls = Vec::new(); + for &impl_def_id in impls { + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + if trait_ref.references_error() { + return; + } + + if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive { + return; + } + + assert_eq!(trait_ref.substs.len(), 1); + let self_ty = trait_ref.self_ty(); + let (self_type_did, substs) = match self_ty.kind() { + ty::Adt(def, substs) => (def.did, substs), + _ => { + // FIXME: should also lint for stuff like `&i32` but + // considering that auto traits are unstable, that + // isn't too important for now as this only affects + // crates using `nightly`, and std. + continue; + } + }; + + // Impls which completely cover a given root type are fine as they + // disable auto impls entirely. So only lint if the substs + // are not a permutation of the identity substs. + match substs.visit_with(&mut AreUniqueParamsVisitor::default()) { + ControlFlow::Continue(()) => {} // ok + ControlFlow::Break(arg) => { + // Ideally: + // + // - compute the requirements for the auto impl candidate + // - check whether these are implied by the non covering impls + // - if not, emit the lint + // + // What we do here is a bit simpler: + // + // - badly check if an auto impl candidate definitely does not apply + // for the given simplified type + // - if so, do not lint + if fast_reject_auto_impl(tcx, trait_def_id, self_ty) { + // ok + } else { + non_covering_impls.push((impl_def_id, self_type_did, arg)); + } + } + } + } + + for &(impl_def_id, self_type_did, arg) in &non_covering_impls { + tcx.struct_span_lint_hir( + lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS, + tcx.hir().local_def_id_to_hir_id(impl_def_id), + tcx.def_span(impl_def_id), + |err| { + let mut err = err.build(&format!( + "cross-crate traits with a default impl, like `{}`, \ + should not be specialized", + tcx.def_path_str(trait_def_id), + )); + let item_span = tcx.def_span(self_type_did); + let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); + err.span_note( + item_span, + &format!( + "try using the same sequence of generic parameters as the {} definition", + self_descr, + ), + ); + match arg { + NotUniqueParam::DuplicateParam(arg) => { + err.note(&format!("`{}` is mentioned multiple times", arg)); + } + NotUniqueParam::NotParam(arg) => { + err.note(&format!("`{}` is not a generic parameter", arg)); + } + } + err.emit(); + }, + ); + } +} + +fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool { + struct DisableAutoTraitVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + self_ty_root: Ty<'tcx>, + seen: FxHashSet<DefId>, + } + + impl<'tcx> TypeVisitor<'tcx> for DisableAutoTraitVisitor<'tcx> { + type BreakTy = (); + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + let tcx = self.tcx; + if t != self.self_ty_root { + for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) { + match tcx.impl_polarity(impl_def_id) { + ImplPolarity::Negative => return ControlFlow::BREAK, + ImplPolarity::Reservation => {} + // FIXME(@lcnr): That's probably not good enough, idk + // + // We might just want to take the rustdoc code and somehow avoid + // explicit impls for `Self`. + ImplPolarity::Positive => return ControlFlow::CONTINUE, + } + } + } + + match t.kind() { + ty::Adt(def, substs) => { + // @lcnr: This is the only place where cycles can happen. We avoid this + // by only visiting each `DefId` once. + // + // This will be is incorrect in subtle cases, but I don't care :) + if self.seen.insert(def.did) { + for ty in def.all_fields().map(|field| field.ty(tcx, substs)) { + ty.visit_with(self)?; + } + } + + ControlFlow::CONTINUE + } + _ => t.super_visit_with(self), + } + } + } + + let self_ty_root = match self_ty.kind() { + ty::Adt(def, _) => tcx.mk_adt(def, InternalSubsts::identity_for_item(tcx, def.did)), + _ => unimplemented!("unexpected self ty {:?}", self_ty), + }; + + self_ty_root + .visit_with(&mut DisableAutoTraitVisitor { + tcx, + self_ty_root, + trait_def_id, + seen: FxHashSet::default(), + }) + .is_break() +} diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.rs b/src/test/ui/auto-traits/suspicious-impls-lint.rs new file mode 100644 index 00000000000..1026a35a455 --- /dev/null +++ b/src/test/ui/auto-traits/suspicious-impls-lint.rs @@ -0,0 +1,34 @@ +#![deny(suspicious_auto_trait_impls)] + +struct MayImplementSendOk<T>(T); +unsafe impl<T: Send> Send for MayImplementSendOk<T> {} // ok + +struct MayImplementSendErr<T>(T); +unsafe impl<T: Send> Send for MayImplementSendErr<&T> {} +//~^ ERROR +//~| WARNING this will change its meaning + +struct ContainsNonSendDirect<T>(*const T); +unsafe impl<T: Send> Send for ContainsNonSendDirect<&T> {} // ok + +struct ContainsPtr<T>(*const T); +struct ContainsIndirectNonSend<T>(ContainsPtr<T>); +unsafe impl<T: Send> Send for ContainsIndirectNonSend<&T> {} // ok + +struct ContainsVec<T>(Vec<T>); +unsafe impl Send for ContainsVec<i32> {} +//~^ ERROR +//~| WARNING this will change its meaning + +struct TwoParams<T, U>(T, U); +unsafe impl<T: Send, U: Send> Send for TwoParams<T, U> {} // ok + +struct TwoParamsFlipped<T, U>(T, U); +unsafe impl<T: Send, U: Send> Send for TwoParamsFlipped<U, T> {} // ok + +struct TwoParamsSame<T, U>(T, U); +unsafe impl<T: Send> Send for TwoParamsSame<T, T> {} +//~^ ERROR +//~| WARNING this will change its meaning + +fn main() {} diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.stderr b/src/test/ui/auto-traits/suspicious-impls-lint.stderr new file mode 100644 index 00000000000..f91aa862271 --- /dev/null +++ b/src/test/ui/auto-traits/suspicious-impls-lint.stderr @@ -0,0 +1,52 @@ +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:7:1 + | +LL | unsafe impl<T: Send> Send for MayImplementSendErr<&T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/suspicious-impls-lint.rs:1:9 + | +LL | #![deny(suspicious_auto_trait_impls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:6:1 + | +LL | struct MayImplementSendErr<T>(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&T` is not a generic parameter + +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:19:1 + | +LL | unsafe impl Send for ContainsVec<i32> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:18:1 + | +LL | struct ContainsVec<T>(Vec<T>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `i32` is not a generic parameter + +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:30:1 + | +LL | unsafe impl<T: Send> Send for TwoParamsSame<T, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:29:1 + | +LL | struct TwoParamsSame<T, U>(T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `T` is mentioned multiple times + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs index 772ac322032..cc75cd4909a 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs @@ -1,4 +1,5 @@ // aux-build:tdticc_coherence_lib.rs +#![allow(suspicious_auto_trait_impls)] // Test that we do not consider associated types to be sendable without // some applicable trait bound (and we don't ICE). diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr index 90ab5be016c..cf5c15df705 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:13:1 + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:14:1 | LL | impl DefaultedTrait for (A,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^---- @@ -10,7 +10,7 @@ LL | impl DefaultedTrait for (A,) { } = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:16:1 + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:17:1 | LL | impl !DefaultedTrait for (B,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^---- @@ -21,13 +21,13 @@ LL | impl !DefaultedTrait for (B,) { } = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate - --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:20:1 + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1 | LL | impl DefaultedTrait for Box<C> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1 + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:22:1 | LL | impl DefaultedTrait for lib::Something<C> { } | ^^^^^^^^^^^^^^^^^^^^^^^^----------------- diff --git a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs index 828248d922f..514fb25c8cf 100644 --- a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs @@ -1,4 +1,5 @@ #![warn(clippy::non_send_fields_in_send_ty)] +#![allow(suspicious_auto_trait_impls)] #![feature(extern_types)] use std::cell::UnsafeCell; diff --git a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr index 60df4e226e4..b6c904a147a 100644 --- a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr +++ b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr @@ -1,167 +1,167 @@ error: some fields in `RingBuffer<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:16:1 + --> $DIR/non_send_fields_in_send_ty.rs:17:1 | LL | unsafe impl<T> Send for RingBuffer<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings` note: it is not safe to send field `data` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:11:5 + --> $DIR/non_send_fields_in_send_ty.rs:12:5 | LL | data: Vec<UnsafeCell<T>>, | ^^^^^^^^^^^^^^^^^^^^^^^^ = help: add bounds on type parameter `T` that satisfy `Vec<UnsafeCell<T>>: Send` error: some fields in `MvccRwLock<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:24:1 + --> $DIR/non_send_fields_in_send_ty.rs:25:1 | LL | unsafe impl<T> Send for MvccRwLock<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `lock` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:21:5 + --> $DIR/non_send_fields_in_send_ty.rs:22:5 | LL | lock: Mutex<Box<T>>, | ^^^^^^^^^^^^^^^^^^^ = help: add bounds on type parameter `T` that satisfy `Mutex<Box<T>>: Send` error: some fields in `ArcGuard<RC, T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:32:1 + --> $DIR/non_send_fields_in_send_ty.rs:33:1 | LL | unsafe impl<RC, T: Send> Send for ArcGuard<RC, T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `head` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:29:5 + --> $DIR/non_send_fields_in_send_ty.rs:30:5 | LL | head: Arc<RC>, | ^^^^^^^^^^^^^ = help: add bounds on type parameter `RC` that satisfy `Arc<RC>: Send` error: some fields in `DeviceHandle<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:48:1 + --> $DIR/non_send_fields_in_send_ty.rs:49:1 | LL | unsafe impl<T: UsbContext> Send for DeviceHandle<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `context` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:44:5 + --> $DIR/non_send_fields_in_send_ty.rs:45:5 | LL | context: T, | ^^^^^^^^^^ = help: add `T: Send` bound in `Send` impl error: some fields in `NoGeneric` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:55:1 + --> $DIR/non_send_fields_in_send_ty.rs:56:1 | LL | unsafe impl Send for NoGeneric {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `rc_is_not_send` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:52:5 + --> $DIR/non_send_fields_in_send_ty.rs:53:5 | LL | rc_is_not_send: Rc<String>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` error: some fields in `MultiField<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:63:1 + --> $DIR/non_send_fields_in_send_ty.rs:64:1 | LL | unsafe impl<T> Send for MultiField<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field1` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:58:5 + --> $DIR/non_send_fields_in_send_ty.rs:59:5 | LL | field1: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl note: it is not safe to send field `field2` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:59:5 + --> $DIR/non_send_fields_in_send_ty.rs:60:5 | LL | field2: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl note: it is not safe to send field `field3` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:60:5 + --> $DIR/non_send_fields_in_send_ty.rs:61:5 | LL | field3: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl error: some fields in `MyOption<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:70:1 + --> $DIR/non_send_fields_in_send_ty.rs:71:1 | LL | unsafe impl<T> Send for MyOption<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `0` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:66:12 + --> $DIR/non_send_fields_in_send_ty.rs:67:12 | LL | MySome(T), | ^ = help: add `T: Send` bound in `Send` impl error: some fields in `MultiParam<A, B>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:82:1 + --> $DIR/non_send_fields_in_send_ty.rs:83:1 | LL | unsafe impl<A, B> Send for MultiParam<A, B> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `vec` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:79:5 + --> $DIR/non_send_fields_in_send_ty.rs:80:5 | LL | vec: Vec<(A, B)>, | ^^^^^^^^^^^^^^^^ = help: add bounds on type parameters `A, B` that satisfy `Vec<(A, B)>: Send` error: some fields in `HeuristicTest` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:100:1 + --> $DIR/non_send_fields_in_send_ty.rs:101:1 | LL | unsafe impl Send for HeuristicTest {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field4` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:95:5 + --> $DIR/non_send_fields_in_send_ty.rs:96:5 | LL | field4: (*const NonSend, Rc<u8>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` error: some fields in `AttrTest3<T>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:119:1 + --> $DIR/non_send_fields_in_send_ty.rs:120:1 | LL | unsafe impl<T> Send for AttrTest3<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `0` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:114:11 + --> $DIR/non_send_fields_in_send_ty.rs:115:11 | LL | Enum2(T), | ^ = help: add `T: Send` bound in `Send` impl error: some fields in `Complex<P, u32>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:127:1 + --> $DIR/non_send_fields_in_send_ty.rs:128:1 | LL | unsafe impl<P> Send for Complex<P, u32> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field1` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:123:5 + --> $DIR/non_send_fields_in_send_ty.rs:124:5 | LL | field1: A, | ^^^^^^^^^ = help: add `P: Send` bound in `Send` impl error: some fields in `Complex<Q, MutexGuard<'static, bool>>` are not safe to be sent to another thread - --> $DIR/non_send_fields_in_send_ty.rs:130:1 + --> $DIR/non_send_fields_in_send_ty.rs:131:1 | LL | unsafe impl<Q: Send> Send for Complex<Q, MutexGuard<'static, bool>> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field2` to another thread - --> $DIR/non_send_fields_in_send_ty.rs:124:5 + --> $DIR/non_send_fields_in_send_ty.rs:125:5 | LL | field2: B, | ^^^^^^^^^ |
