diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_hir_analysis/src/coherence | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-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')
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>( |