Skip to content

Commit

Permalink
do not implement unsafe auto traits for types with unsafe fields
Browse files Browse the repository at this point in the history
If a type has unsafe fields, its safety invariants are not simply
the conjunction of its field types' safety invariants. Consequently,
it's invalid to reason about the safety properties of these types
in a purely structural manner — i.e., the manner in which `auto`
traits are implemented.

Makes progress towards rust-lang#132922.
  • Loading branch information
jswrenn committed Dec 5, 2024
1 parent 0e98766 commit e6e322f
Show file tree
Hide file tree
Showing 10 changed files with 20 additions and 0 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.trait_def(trait_def_id).has_auto_impl
}

/// Returns `true` if this is an `unsafe trait`.
pub fn trait_is_unsafe(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).safety == Safety::Unsafe
}

/// Returns `true` if this is coinductive, either because it is
/// an auto trait or because it has the `#[rustc_coinductive]` attribute.
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,15 @@ impl<'tcx> Ty<'tcx> {
}
}

/// Checks whether this type directly contains unsafe fields.
pub fn has_unsafe_fields(self) -> bool {
if let ty::Adt(adt_def, ..) = self.kind() {
adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe)
} else {
false
}
}

/// Get morphology of the async drop glue, needed for types which do not
/// use async drop. To get async drop glue morphology for a definition see
/// [`TyCtxt::async_drop_glue_morphology`]. Used for `AsyncDestruct::Destructor`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Never
| ty::Tuple(_)
| ty::CoroutineWitness(..) => {
// Only consider auto impls of unsafe traits when there are
// no unsafe fields.
if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
return;
}

// Only consider auto impls if there are no manual impls for the root of `self_ty`.
//
// For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit e6e322f

Please sign in to comment.