summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/coherence
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/coherence')
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs66
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs59
3 files changed, 26 insertions, 116 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index b6c91d425..193ecdb16 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -114,7 +114,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
traits::ObligationCause::dummy_with_span(field_ty_span),
param_env,
ty,
- tcx.lang_items().copy_trait().unwrap(),
+ tcx.require_lang_item(LangItem::Copy, Some(span)),
) {
let error_predicate = error.obligation.predicate;
// Only note if it's not the root obligation, otherwise it's trivial and
@@ -128,11 +128,11 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
.or_default()
.push(error.obligation.cause.span);
}
- if let ty::PredicateKind::Trait(ty::TraitPredicate {
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::ImplPolarity::Positive,
..
- }) = error_predicate.kind().skip_binder()
+ })) = error_predicate.kind().skip_binder()
{
let ty = trait_ref.self_ty();
if let ty::Param(_) = ty.kind() {
@@ -315,13 +315,12 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
cause.clone(),
dispatch_from_dyn_trait,
0,
- field.ty(tcx, substs_a),
- &[field.ty(tcx, substs_b).into()],
+ [field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
)
}),
);
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None);
}
// Finally, resolve all regions.
@@ -371,7 +370,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
mt_b: ty::TypeAndMut<'tcx>,
mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
- if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
+ if mt_a.mutbl < mt_b.mutbl {
infcx
.err_ctxt()
.report_mismatched_types(
@@ -558,10 +557,10 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// Register an obligation for `A: Trait<B>`.
let cause = traits::ObligationCause::misc(span, impl_hir_id);
let predicate =
- predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
+ predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
let errors = traits::fully_solve_obligation(&infcx, predicate);
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None);
}
// Finally, resolve all regions.
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index ae9ebe590..1bf3768fe 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -5,10 +5,11 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
-use rustc_errors::struct_span_err;
+use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_span::sym;
use rustc_trait_selection::traits;
mod builtin;
@@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
impl_def_id: LocalDefId,
trait_def_id: DefId,
) {
- let did = Some(trait_def_id);
- let li = tcx.lang_items();
let impl_header_span = tcx.def_span(impl_def_id);
- // Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
- if did == li.pointee_trait() {
- struct_span_err!(
+ // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
+ if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
+ let trait_name = tcx.item_name(trait_def_id);
+ let mut err = struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
- "explicit impls for the `Pointee` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Pointee` not allowed")
- .emit();
- return;
- }
-
- if did == li.discriminant_kind_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0322,
- "explicit impls for the `DiscriminantKind` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
- .emit();
- return;
- }
-
- if did == li.sized_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0322,
- "explicit impls for the `Sized` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Sized` not allowed")
- .emit();
- return;
- }
-
- if did == li.unsize_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0328,
- "explicit impls for the `Unsize` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Unsize` not allowed")
- .emit();
- return;
- }
+ "explicit impls for the `{trait_name}` trait are not permitted"
+ );
+ err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));
+
+ // Maintain explicit error code for `Unsize`, since it has a useful
+ // explanation about using `CoerceUnsized` instead.
+ if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
+ err.code(error_code!(E0328));
+ }
- if tcx.features().unboxed_closures {
- // the feature gate allows all Fn traits
+ err.emit();
return;
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index bb45c3823..cc5114dba 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{
@@ -23,9 +22,7 @@ pub(crate) fn orphan_check_impl(
impl_def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
- if let Some(err) = trait_ref.error_reported() {
- return Err(err);
- }
+ trait_ref.error_reported()?;
let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id);
if tcx.trait_is_auto(trait_ref.def_id) {
@@ -49,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
let sp = tcx.def_span(def_id);
let tr = impl_.of_trait.as_ref().unwrap();
- // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
- // and #84660 where it would otherwise allow unsoundness.
- if trait_ref.has_opaque_types() {
- trace!("{:#?}", item);
- // First we find the opaque type in question.
- for ty in trait_ref.substs {
- for ty in ty.walk() {
- let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
- let ty::Opaque(def_id, _) = *ty.kind() else { continue };
- trace!(?def_id);
-
- // Then we search for mentions of the opaque type's type alias in the HIR
- struct SpanFinder<'tcx> {
- sp: Span,
- def_id: DefId,
- tcx: TyCtxt<'tcx>,
- }
- impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
- #[instrument(level = "trace", skip(self, _id))]
- fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
- // You can't mention an opaque type directly, so we look for type aliases
- if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
- // And check if that type alias's type contains the opaque type we're looking for
- for arg in self.tcx.type_of(def_id).walk() {
- if let GenericArgKind::Type(ty) = arg.unpack() {
- if let ty::Opaque(def_id, _) = *ty.kind() {
- if def_id == self.def_id {
- // Finally we update the span to the mention of the type alias
- self.sp = path.span;
- return;
- }
- }
- }
- }
- }
- hir::intravisit::walk_path(self, path)
- }
- }
-
- let mut visitor = SpanFinder { sp, def_id, tcx };
- hir::intravisit::walk_item(&mut visitor, item);
- let reported = tcx
- .sess
- .struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
- .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
- .emit();
- return Err(reported);
- }
- }
- span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
- }
-
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
Ok(()) => {}
Err(err) => emit_orphan_check_error(
@@ -347,7 +292,7 @@ fn emit_newtype_suggestion_for_raw_ptr(
diag: &mut Diagnostic,
) {
if !self_ty.needs_subst() {
- let mut_key = if ptr_ty.mutbl == rustc_middle::mir::Mutability::Mut { "mut " } else { "" };
+ let mut_key = ptr_ty.mutbl.prefix_str();
let msg_sugg = "consider introducing a new wrapper type".to_owned();
let sugg = vec![
(