summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/coherence
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_hir_analysis/src/coherence
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/coherence')
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs295
3 files changed, 141 insertions, 172 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index be70acfc3..e5e192e00 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -162,7 +162,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
// trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else
// in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
// even if they do not carry that attribute.
- use rustc_type_ir::sty::TyKind::*;
+ use rustc_type_ir::TyKind::*;
match (source.kind(), target.kind()) {
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
@@ -261,7 +261,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors);
+ infcx.err_ctxt().report_fulfillment_errors(errors);
}
// Finally, resolve all regions.
@@ -470,7 +470,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors);
+ infcx.err_ctxt().report_fulfillment_errors(errors);
}
// Finally, resolve all regions.
@@ -550,9 +550,11 @@ fn infringing_fields_error(
.entry((ty.clone(), predicate.clone()))
.or_default()
.push(origin.span());
- if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
- bounds.push((b.to_string(), a.to_string(), None));
- }
+ if let ty::RegionKind::ReEarlyBound(ebr) = *b
+ && ebr.has_name()
+ {
+ bounds.push((b.to_string(), a.to_string(), None));
+ }
}
RegionResolutionError::GenericBoundFailure(origin, a, b) => {
let predicate = format!("{a}: {b}");
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 0042d683b..1b4df31b5 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -155,8 +155,8 @@ impl<'tcx> InherentCollect<'tcx> {
}
ty::FnDef(..)
| ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 69020b1f1..7eeb78374 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -2,8 +2,7 @@
//! crate or pertains to a type defined in this crate.
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_err, DelayDm};
-use rustc_errors::{Diagnostic, ErrorGuaranteed};
+use rustc_errors::{DelayDm, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_middle::ty::util::CheckRegions;
use rustc_middle::ty::GenericArgs;
@@ -17,6 +16,8 @@ use rustc_span::Span;
use rustc_trait_selection::traits;
use std::ops::ControlFlow;
+use crate::errors;
+
#[instrument(skip(tcx), level = "debug")]
pub(crate) fn orphan_check_impl(
tcx: TyCtxt<'_>,
@@ -243,8 +244,8 @@ fn do_orphan_check_impl<'tcx>(
| ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..) => {
@@ -259,49 +260,30 @@ fn do_orphan_check_impl<'tcx>(
match local_impl {
LocalImpl::Allow => {}
LocalImpl::Disallow { problematic_kind } => {
- let msg = format!(
- "traits with a default impl, like `{trait}`, \
- cannot be implemented for {problematic_kind} `{self_ty}`",
- trait = tcx.def_path_str(trait_def_id),
- );
- let label = format!(
- "a trait object implements `{trait}` if and only if `{trait}` \
- is one of the trait object's trait bounds",
- trait = tcx.def_path_str(trait_def_id),
- );
- let sp = tcx.def_span(def_id);
- let reported =
- struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
- return Err(reported);
+ return Err(tcx.sess.emit_err(errors::TraitsWithDefaultImpl {
+ span: tcx.def_span(def_id),
+ traits: tcx.def_path_str(trait_def_id),
+ problematic_kind,
+ self_ty,
+ }));
}
}
} else {
- if let Some((msg, label)) = match nonlocal_impl {
- NonlocalImpl::Allow => None,
- NonlocalImpl::DisallowBecauseNonlocal => Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, \
- can only be implemented for a struct/enum type \
- defined in the current crate",
- tcx.def_path_str(trait_def_id)
- ),
- "can't implement cross-crate trait for type in another crate",
- )),
- NonlocalImpl::DisallowOther => Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, can \
- only be implemented for a struct/enum type, not `{}`",
- tcx.def_path_str(trait_def_id),
- self_ty
- ),
- "can't implement cross-crate trait with a default impl for \
- non-struct/enum type",
- )),
- } {
- let sp = tcx.def_span(def_id);
- let reported =
- struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
- return Err(reported);
+ match nonlocal_impl {
+ NonlocalImpl::Allow => {}
+ NonlocalImpl::DisallowBecauseNonlocal => {
+ return Err(tcx.sess.emit_err(errors::CrossCrateTraitsDefined {
+ span: tcx.def_span(def_id),
+ traits: tcx.def_path_str(trait_def_id),
+ }));
+ }
+ NonlocalImpl::DisallowOther => {
+ return Err(tcx.sess.emit_err(errors::CrossCrateTraits {
+ span: tcx.def_span(def_id),
+ traits: tcx.def_path_str(trait_def_id),
+ self_ty,
+ }));
+ }
}
}
}
@@ -322,19 +304,18 @@ fn emit_orphan_check_error<'tcx>(
let self_ty = trait_ref.self_ty();
Err(match err {
traits::OrphanCheckErr::NonLocalInputType(tys) => {
- let msg = match self_ty.kind() {
- ty::Adt(..) => "can be implemented for types defined outside of the crate",
- _ if self_ty.is_primitive() => "can be implemented for primitive types",
- _ => "can be implemented for arbitrary types",
- };
- let mut err = struct_span_err!(
- tcx.sess,
- sp,
- E0117,
- "only traits defined in the current crate {msg}"
- );
- err.span_label(sp, "impl doesn't use only types from inside the current crate");
+ let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) =
+ (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
+ let mut sugg = None;
for &(mut ty, is_target_ty) in &tys {
+ let span = if is_target_ty {
+ // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
+ self_ty_span
+ } else {
+ // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
+ trait_span
+ };
+
ty = tcx.erase_regions(ty);
ty = match ty.kind() {
// Remove the type arguments from the output, as they are not relevant.
@@ -345,50 +326,103 @@ fn emit_orphan_check_error<'tcx>(
ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
_ => ty,
};
- let msg = |ty: &str, postfix: &str| {
- format!("{ty} is not defined in the current crate{postfix}")
- };
- let this = |name: &str| {
- if !trait_ref.def_id.is_local() && !is_target_ty {
- msg("this", " because this is a foreign trait")
+ fn push_to_foreign_or_name<'tcx>(
+ is_foreign: bool,
+ foreign: &mut Vec<errors::OnlyCurrentTraitsForeign>,
+ name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>,
+ span: Span,
+ sname: &'tcx str,
+ ) {
+ if is_foreign {
+ foreign.push(errors::OnlyCurrentTraitsForeign { span })
} else {
- msg("this", &format!(" because {name} are always foreign"))
+ name.push(errors::OnlyCurrentTraitsName { span, name: sname });
+ }
+ }
+
+ let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty;
+
+ match &ty.kind() {
+ ty::Slice(_) => {
+ push_to_foreign_or_name(
+ is_foreign,
+ &mut foreign,
+ &mut name,
+ span,
+ "slices",
+ );
+ }
+ ty::Array(..) => {
+ push_to_foreign_or_name(
+ is_foreign,
+ &mut foreign,
+ &mut name,
+ span,
+ "arrays",
+ );
+ }
+ ty::Tuple(..) => {
+ push_to_foreign_or_name(
+ is_foreign,
+ &mut foreign,
+ &mut name,
+ span,
+ "tuples",
+ );
}
- };
- let msg = match &ty.kind() {
- ty::Slice(_) => this("slices"),
- ty::Array(..) => this("arrays"),
- ty::Tuple(..) => this("tuples"),
ty::Alias(ty::Opaque, ..) => {
- "type alias impl trait is treated as if it were foreign, \
- because its hidden type could be from a foreign crate"
- .to_string()
+ opaque.push(errors::OnlyCurrentTraitsOpaque { span })
}
ty::RawPtr(ptr_ty) => {
- emit_newtype_suggestion_for_raw_ptr(
- full_impl_span,
- self_ty,
- self_ty_span,
- ptr_ty,
- &mut err,
- );
-
- msg(&format!("`{ty}`"), " because raw pointers are always foreign")
+ if !self_ty.has_param() {
+ let mut_key = ptr_ty.mutbl.prefix_str();
+ sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
+ wrapper_span: self_ty_span,
+ struct_span: full_impl_span.shrink_to_lo(),
+ mut_key,
+ ptr_ty: ptr_ty.ty,
+ });
+ }
+ pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
}
- _ => msg(&format!("`{ty}`"), ""),
- };
-
- if is_target_ty {
- // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
- err.span_label(self_ty_span, msg);
- } else {
- // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
- err.span_label(trait_span, msg);
+ _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }),
}
}
- err.note("define and implement a trait or new type instead");
- err.emit()
+
+ let err_struct = match self_ty.kind() {
+ ty::Adt(..) => errors::OnlyCurrentTraits::Outside {
+ span: sp,
+ note: (),
+ opaque,
+ foreign,
+ name,
+ pointer,
+ ty: ty_diag,
+ sugg,
+ },
+ _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive {
+ span: sp,
+ note: (),
+ opaque,
+ foreign,
+ name,
+ pointer,
+ ty: ty_diag,
+ sugg,
+ },
+ _ => errors::OnlyCurrentTraits::Arbitrary {
+ span: sp,
+ note: (),
+ opaque,
+ foreign,
+ name,
+ pointer,
+ ty: ty_diag,
+ sugg,
+ },
+ };
+ tcx.sess.emit_err(err_struct)
}
traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
let mut sp = sp;
@@ -399,85 +433,18 @@ fn emit_orphan_check_error<'tcx>(
}
match local_type {
- Some(local_type) => struct_span_err!(
- tcx.sess,
- sp,
- E0210,
- "type parameter `{}` must be covered by another type \
- when it appears before the first local type (`{}`)",
- param_ty,
- local_type
- )
- .span_label(
- sp,
- format!(
- "type parameter `{param_ty}` must be covered by another type \
- when it appears before the first local type (`{local_type}`)"
- ),
- )
- .note(
- "implementing a foreign trait is only possible if at \
- least one of the types for which it is implemented is local, \
- and no uncovered type parameters appear before that first \
- local type",
- )
- .note(
- "in this case, 'before' refers to the following order: \
- `impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
- where `T0` is the first and `Tn` is the last",
- )
- .emit(),
- None => struct_span_err!(
- tcx.sess,
- sp,
- E0210,
- "type parameter `{}` must be used as the type parameter for some \
- local type (e.g., `MyStruct<{}>`)",
+ Some(local_type) => tcx.sess.emit_err(errors::TyParamFirstLocal {
+ span: sp,
+ note: (),
param_ty,
- param_ty
- )
- .span_label(
- sp,
- format!(
- "type parameter `{param_ty}` must be used as the type parameter for some \
- local type",
- ),
- )
- .note(
- "implementing a foreign trait is only possible if at \
- least one of the types for which it is implemented is local",
- )
- .note(
- "only traits defined in the current crate can be \
- implemented for a type parameter",
- )
- .emit(),
+ local_type,
+ }),
+ None => tcx.sess.emit_err(errors::TyParamSome { span: sp, note: (), param_ty }),
}
}
})
}
-fn emit_newtype_suggestion_for_raw_ptr(
- full_impl_span: Span,
- self_ty: Ty<'_>,
- self_ty_span: Span,
- ptr_ty: &ty::TypeAndMut<'_>,
- diag: &mut Diagnostic,
-) {
- if !self_ty.has_param() {
- let mut_key = ptr_ty.mutbl.prefix_str();
- let msg_sugg = "consider introducing a new wrapper type".to_owned();
- let sugg = vec![
- (
- full_impl_span.shrink_to_lo(),
- format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty),
- ),
- (self_ty_span, "WrapperType".to_owned()),
- ];
- diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect);
- }
-}
-
/// Lint impls of auto traits if they are likely to have
/// unsound or surprising effects on auto impls.
fn lint_auto_trait_impl<'tcx>(