Don't reinvoke impl_trait_ref
query after it was already invoked
This commit is contained in:
parent
97b4b7f72b
commit
614ff0fae9
2 changed files with 81 additions and 84 deletions
|
@ -131,7 +131,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
|
||||||
res = res.and(check_impl(tcx, impl_def_id, trait_ref));
|
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_object_overlap(tcx, impl_def_id, trait_ref));
|
||||||
|
|
||||||
res = res.and(unsafety::check_item(tcx, impl_def_id));
|
res = res.and(unsafety::check_item(tcx, impl_def_id, trait_ref));
|
||||||
res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
|
res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
|
||||||
res = res.and(builtin::check_trait(tcx, def_id, impl_def_id));
|
res = res.and(builtin::check_trait(tcx, def_id, impl_def_id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,94 +4,91 @@
|
||||||
use rustc_errors::{codes::*, struct_span_code_err};
|
use rustc_errors::{codes::*, struct_span_code_err};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::Unsafety;
|
use rustc_hir::Unsafety;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::{TraitRef, TyCtxt};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::ErrorGuaranteed;
|
use rustc_span::ErrorGuaranteed;
|
||||||
|
|
||||||
pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
pub(super) fn check_item(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
trait_ref: TraitRef<'_>,
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let item = tcx.hir().expect_item(def_id);
|
let item = tcx.hir().expect_item(def_id);
|
||||||
let impl_ = item.expect_impl();
|
let impl_ = item.expect_impl();
|
||||||
|
let trait_def = tcx.trait_def(trait_ref.def_id);
|
||||||
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
|
let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
|
||||||
let trait_ref = trait_ref.instantiate_identity();
|
match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) {
|
||||||
let trait_def = tcx.trait_def(trait_ref.def_id);
|
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||||
let unsafe_attr =
|
return Err(struct_span_code_err!(
|
||||||
impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
|
tcx.dcx(),
|
||||||
match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) {
|
tcx.def_span(def_id),
|
||||||
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
E0199,
|
||||||
return Err(struct_span_code_err!(
|
"implementing the trait `{}` is not unsafe",
|
||||||
tcx.dcx(),
|
trait_ref.print_trait_sugared()
|
||||||
tcx.def_span(def_id),
|
)
|
||||||
E0199,
|
.with_span_suggestion_verbose(
|
||||||
"implementing the trait `{}` is not unsafe",
|
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
|
||||||
trait_ref.print_trait_sugared()
|
"remove `unsafe` from this trait implementation",
|
||||||
)
|
"",
|
||||||
.with_span_suggestion_verbose(
|
rustc_errors::Applicability::MachineApplicable,
|
||||||
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
|
)
|
||||||
"remove `unsafe` from this trait implementation",
|
.emit());
|
||||||
"",
|
|
||||||
rustc_errors::Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit());
|
|
||||||
}
|
|
||||||
|
|
||||||
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
|
||||||
return Err(struct_span_code_err!(
|
|
||||||
tcx.dcx(),
|
|
||||||
tcx.def_span(def_id),
|
|
||||||
E0200,
|
|
||||||
"the trait `{}` requires an `unsafe impl` declaration",
|
|
||||||
trait_ref.print_trait_sugared()
|
|
||||||
)
|
|
||||||
.with_note(format!(
|
|
||||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
|
||||||
Review the trait documentation and make sure this implementation \
|
|
||||||
upholds those invariants before adding the `unsafe` keyword",
|
|
||||||
trait_ref.print_trait_sugared()
|
|
||||||
))
|
|
||||||
.with_span_suggestion_verbose(
|
|
||||||
item.span.shrink_to_lo(),
|
|
||||||
"add `unsafe` to this trait implementation",
|
|
||||||
"unsafe ",
|
|
||||||
rustc_errors::Applicability::MaybeIncorrect,
|
|
||||||
)
|
|
||||||
.emit());
|
|
||||||
}
|
|
||||||
|
|
||||||
(Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
|
||||||
return Err(struct_span_code_err!(
|
|
||||||
tcx.dcx(),
|
|
||||||
tcx.def_span(def_id),
|
|
||||||
E0569,
|
|
||||||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
|
||||||
attr_name
|
|
||||||
)
|
|
||||||
.with_note(format!(
|
|
||||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
|
||||||
Review the trait documentation and make sure this implementation \
|
|
||||||
upholds those invariants before adding the `unsafe` keyword",
|
|
||||||
trait_ref.print_trait_sugared()
|
|
||||||
))
|
|
||||||
.with_span_suggestion_verbose(
|
|
||||||
item.span.shrink_to_lo(),
|
|
||||||
"add `unsafe` to this trait implementation",
|
|
||||||
"unsafe ",
|
|
||||||
rustc_errors::Applicability::MaybeIncorrect,
|
|
||||||
)
|
|
||||||
.emit());
|
|
||||||
}
|
|
||||||
|
|
||||||
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
|
|
||||||
// Reported in AST validation
|
|
||||||
tcx.dcx().span_delayed_bug(item.span, "unsafe negative impl");
|
|
||||||
}
|
|
||||||
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
|
|
||||||
| (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
|
|
||||||
| (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
|
|
||||||
| (Unsafety::Normal, None, Unsafety::Normal, _) => {
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||||
|
return Err(struct_span_code_err!(
|
||||||
|
tcx.dcx(),
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
E0200,
|
||||||
|
"the trait `{}` requires an `unsafe impl` declaration",
|
||||||
|
trait_ref.print_trait_sugared()
|
||||||
|
)
|
||||||
|
.with_note(format!(
|
||||||
|
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||||
|
Review the trait documentation and make sure this implementation \
|
||||||
|
upholds those invariants before adding the `unsafe` keyword",
|
||||||
|
trait_ref.print_trait_sugared()
|
||||||
|
))
|
||||||
|
.with_span_suggestion_verbose(
|
||||||
|
item.span.shrink_to_lo(),
|
||||||
|
"add `unsafe` to this trait implementation",
|
||||||
|
"unsafe ",
|
||||||
|
rustc_errors::Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit());
|
||||||
|
}
|
||||||
|
|
||||||
|
(Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||||
|
return Err(struct_span_code_err!(
|
||||||
|
tcx.dcx(),
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
E0569,
|
||||||
|
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||||
|
attr_name
|
||||||
|
)
|
||||||
|
.with_note(format!(
|
||||||
|
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||||
|
Review the trait documentation and make sure this implementation \
|
||||||
|
upholds those invariants before adding the `unsafe` keyword",
|
||||||
|
trait_ref.print_trait_sugared()
|
||||||
|
))
|
||||||
|
.with_span_suggestion_verbose(
|
||||||
|
item.span.shrink_to_lo(),
|
||||||
|
"add `unsafe` to this trait implementation",
|
||||||
|
"unsafe ",
|
||||||
|
rustc_errors::Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit());
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
|
||||||
|
// Reported in AST validation
|
||||||
|
tcx.dcx().span_delayed_bug(item.span, "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, None, Unsafety::Normal, _) => Ok(()),
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue