diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 7f59763f2a0..f1978a0fc35 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -132,12 +132,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - res = res.and(check_impl(tcx, impl_def_id, trait_ref)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); - res = res.and(unsafety::check_item(tcx, impl_def_id, trait_ref)); + res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); res = res.and(builtin::check_trait(tcx, def_id, impl_def_id)); } diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index d217d53587d..158d010b05d 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -2,23 +2,23 @@ //! crate or pertains to a type defined in this crate. use rustc_errors::{codes::*, struct_span_code_err}; -use rustc_hir as hir; use rustc_hir::Unsafety; -use rustc_middle::ty::{TraitRef, TyCtxt}; +use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::ErrorGuaranteed; pub(super) fn check_item( tcx: TyCtxt<'_>, def_id: LocalDefId, - trait_ref: TraitRef<'_>, + trait_header: ImplTraitHeader<'_>, ) -> Result<(), ErrorGuaranteed> { - let item = tcx.hir().expect_item(def_id); - let impl_ = item.expect_impl(); + let trait_ref = trait_header.trait_ref; let trait_def = tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); - match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) { - (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { + let unsafe_attr = + tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { + (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), tcx.def_span(def_id), @@ -27,7 +27,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() ) .with_span_suggestion_verbose( - item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), + span.with_hi(span.lo() + rustc_span::BytePos(7)), "remove `unsafe` from this trait implementation", "", rustc_errors::Applicability::MachineApplicable, @@ -35,10 +35,11 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { + (Unsafety::Unsafe, _, Unsafety::Normal, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), - tcx.def_span(def_id), + span, E0200, "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_trait_sugared() @@ -50,7 +51,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() )) .with_span_suggestion_verbose( - item.span.shrink_to_lo(), + span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", rustc_errors::Applicability::MaybeIncorrect, @@ -58,10 +59,11 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => { + (Unsafety::Normal, Some(attr_name), Unsafety::Normal, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), - tcx.def_span(def_id), + span, E0569, "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name @@ -73,7 +75,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() )) .with_span_suggestion_verbose( - item.span.shrink_to_lo(), + span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", rustc_errors::Applicability::MaybeIncorrect, @@ -81,14 +83,14 @@ pub(super) fn check_item( .emit()); } - (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { + (_, _, Unsafety::Unsafe, Negative) => { // Reported in AST validation - tcx.dcx().span_delayed_bug(item.span, "unsafe negative impl"); + tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "unsafe negative impl"); Ok(()) } - (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) - | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) - | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) + (_, _, Unsafety::Normal, Negative) + | (Unsafety::Unsafe, _, Unsafety::Unsafe, Positive | Reservation) + | (Unsafety::Normal, Some(_), Unsafety::Unsafe, Positive | Reservation) | (Unsafety::Normal, None, Unsafety::Normal, _) => Ok(()), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e8787d159ae..4891dae47c6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1539,6 +1539,7 @@ fn impl_trait_header( }; ty::EarlyBinder::bind(ty::ImplTraitHeader { trait_ref, + unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) }) }) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6ee74ef2fb6..2d6c6cfbcd1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -252,6 +252,7 @@ pub struct ImplHeader<'tcx> { pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub polarity: ImplPolarity, + pub unsafety: hir::Unsafety, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]