Skip to content

Commit eb01fe8

Browse files
authored
Rollup merge of #93267 - lcnr:auto-trait-lint, r=nikomatsakis
implement a lint for suspicious auto trait impls cc #85048 (comment) r? ``@nikomatsakis``
2 parents 741b62a + 94b0a7b commit eb01fe8

File tree

12 files changed

+421
-58
lines changed

12 files changed

+421
-58
lines changed

compiler/rustc_index/src/bit_set.rs

+6
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,12 @@ pub struct GrowableBitSet<T: Idx> {
938938
bit_set: BitSet<T>,
939939
}
940940

941+
impl<T: Idx> Default for GrowableBitSet<T> {
942+
fn default() -> Self {
943+
GrowableBitSet::new_empty()
944+
}
945+
}
946+
941947
impl<T: Idx> GrowableBitSet<T> {
942948
/// Ensure that the set can hold at least `min_domain_size` elements.
943949
pub fn ensure(&mut self, min_domain_size: usize) {

compiler/rustc_lint_defs/src/builtin.rs

+43
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,10 @@ declare_lint! {
17931793
Warn,
17941794
"detects name collision with an existing but unstable method",
17951795
@future_incompatible = FutureIncompatibleInfo {
1796+
reason: FutureIncompatibilityReason::Custom(
1797+
"once this associated item is added to the standard library, \
1798+
the ambiguity may cause an error or change in behavior!"
1799+
),
17961800
reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
17971801
// Note: this item represents future incompatibility of all unstable functions in the
17981802
// standard library, and thus should never be removed or changed to an error.
@@ -2335,6 +2339,10 @@ declare_lint! {
23352339
Warn,
23362340
"reservation of a two-phased borrow conflicts with other shared borrows",
23372341
@future_incompatible = FutureIncompatibleInfo {
2342+
reason: FutureIncompatibilityReason::Custom(
2343+
"this borrowing pattern was not meant to be accepted, \
2344+
and may become a hard error in the future"
2345+
),
23382346
reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
23392347
};
23402348
}
@@ -3046,6 +3054,7 @@ declare_lint_pass! {
30463054
DEREF_INTO_DYN_SUPERTRAIT,
30473055
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
30483056
DUPLICATE_MACRO_ATTRIBUTES,
3057+
SUSPICIOUS_AUTO_TRAIT_IMPLS,
30493058
]
30503059
}
30513060

@@ -3622,3 +3631,37 @@ declare_lint! {
36223631
Warn,
36233632
"duplicated attribute"
36243633
}
3634+
3635+
declare_lint! {
3636+
/// The `suspicious_auto_trait_impls` lint checks for potentially incorrect
3637+
/// implementations of auto traits.
3638+
///
3639+
/// ### Example
3640+
///
3641+
/// ```rust
3642+
/// struct Foo<T>(T);
3643+
///
3644+
/// unsafe impl<T> Send for Foo<*const T> {}
3645+
/// ```
3646+
///
3647+
/// {{produces}}
3648+
///
3649+
/// ### Explanation
3650+
///
3651+
/// A type can implement auto traits, e.g. `Send`, `Sync` and `Unpin`,
3652+
/// in two different ways: either by writing an explicit impl or if
3653+
/// all fields of the type implement that auto trait.
3654+
///
3655+
/// The compiler disables the automatic implementation if an explicit one
3656+
/// exists for given type constructor. The exact rules governing this
3657+
/// are currently unsound and quite subtle and and will be modified in the future.
3658+
/// This change will cause the automatic implementation to be disabled in more
3659+
/// cases, potentially breaking some code.
3660+
pub SUSPICIOUS_AUTO_TRAIT_IMPLS,
3661+
Warn,
3662+
"the rules governing auto traits will change in the future",
3663+
@future_incompatible = FutureIncompatibleInfo {
3664+
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
3665+
reference: "issue #93367 <https://github.com/rust-lang/rust/issues/93367>",
3666+
};
3667+
}

compiler/rustc_lint_defs/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,17 @@ pub enum FutureIncompatibilityReason {
163163
/// This will be an error in a future release, and
164164
/// Cargo should create a report even for dependencies
165165
FutureReleaseErrorReportNow,
166+
/// Code that changes meaning in some way in a
167+
/// future release.
168+
FutureReleaseSemanticsChange,
166169
/// Previously accepted code that will become an
167170
/// error in the provided edition
168171
EditionError(Edition),
169172
/// Code that changes meaning in some way in
170173
/// the provided edition
171174
EditionSemanticsChange(Edition),
175+
/// A custom reason.
176+
Custom(&'static str),
172177
}
173178

174179
impl FutureIncompatibilityReason {

compiler/rustc_middle/src/lint.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ pub fn struct_lint_level<'s, 'd>(
221221
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>,
222222
) {
223223
// Check for future incompatibility lints and issue a stronger warning.
224-
let lint_id = LintId::of(lint);
225224
let future_incompatible = lint.future_incompatible;
226225

227226
let has_future_breakage = future_incompatible.map_or(
@@ -345,31 +344,29 @@ pub fn struct_lint_level<'s, 'd>(
345344
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
346345

347346
if let Some(future_incompatible) = future_incompatible {
348-
let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
349-
"once this associated item is added to the standard library, the ambiguity may \
350-
cause an error or change in behavior!"
351-
.to_owned()
352-
} else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
353-
"this borrowing pattern was not meant to be accepted, and may become a hard error \
354-
in the future"
355-
.to_owned()
356-
} else if let FutureIncompatibilityReason::EditionError(edition) =
357-
future_incompatible.reason
358-
{
359-
let current_edition = sess.edition();
360-
format!(
361-
"this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!",
362-
current_edition, edition
363-
)
364-
} else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) =
365-
future_incompatible.reason
366-
{
367-
format!("this changes meaning in Rust {}", edition)
368-
} else {
369-
"this was previously accepted by the compiler but is being phased out; \
370-
it will become a hard error in a future release!"
371-
.to_owned()
347+
let explanation = match future_incompatible.reason {
348+
FutureIncompatibilityReason::FutureReleaseError
349+
| FutureIncompatibilityReason::FutureReleaseErrorReportNow => {
350+
"this was previously accepted by the compiler but is being phased out; \
351+
it will become a hard error in a future release!"
352+
.to_owned()
353+
}
354+
FutureIncompatibilityReason::FutureReleaseSemanticsChange => {
355+
"this will change its meaning in a future release!".to_owned()
356+
}
357+
FutureIncompatibilityReason::EditionError(edition) => {
358+
let current_edition = sess.edition();
359+
format!(
360+
"this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!",
361+
current_edition, edition
362+
)
363+
}
364+
FutureIncompatibilityReason::EditionSemanticsChange(edition) => {
365+
format!("this changes meaning in Rust {}", edition)
366+
}
367+
FutureIncompatibilityReason::Custom(reason) => reason.to_owned(),
372368
};
369+
373370
if future_incompatible.explain_reason {
374371
err.warn(&explanation);
375372
}

compiler/rustc_middle/src/ty/trait_def.rs

+17
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,23 @@ impl<'tcx> TyCtxt<'tcx> {
144144
});
145145
}
146146

147+
pub fn non_blanket_impls_for_ty(
148+
self,
149+
def_id: DefId,
150+
self_ty: Ty<'tcx>,
151+
) -> impl Iterator<Item = DefId> + 'tcx {
152+
let impls = self.trait_impls_of(def_id);
153+
if let Some(simp) =
154+
fast_reject::simplify_type(self, self_ty, SimplifyParams::No, StripReferences::No)
155+
{
156+
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
157+
return impls.iter().copied();
158+
}
159+
}
160+
161+
[].iter().copied()
162+
}
163+
147164
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
148165
/// the first non-none value.
149166
pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(

0 commit comments

Comments
 (0)