diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /compiler/rustc_hir_analysis/src/coherence | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/coherence')
3 files changed, 104 insertions, 203 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index c930537d4..be70acfc3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,11 +1,10 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use crate::errors::{ - ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem, -}; +use crate::errors; + use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let impl_ = tcx.hir().expect_item(impl_did).expect_impl(); - tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span }); + tcx.sess.emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { @@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span); } Err(CopyImplementationError::NotAnAdt) => { - tcx.sess.emit_err(CopyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::CopyImplOnNonAdt { span }); } Err(CopyImplementationError::HasDestructor) => { - tcx.sess.emit_err(CopyImplOnTypeWithDtor { span }); + tcx.sess.emit_err(errors::CopyImplOnTypeWithDtor { span }); } } } @@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span); } Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { - tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::ConstParamTyImplOnNonAdt { span }); } } } @@ -152,11 +151,17 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let param_env = tcx.param_env(impl_did); - let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg); - let infcx = tcx.infer_ctxt().build(); let cause = ObligationCause::misc(span, impl_did); + // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw + // pointers. This is enforced here: we only allow impls for references, raw pointers, and things + // that are effectively repr(transparent) newtypes around types that already hav a + // DispatchedFromDyn impl. We cannot literally use repr(transparent) on those tpyes since some + // of them support an allocator, but we ensure that for the cases where the type implements this + // 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::*; match (source.kind(), target.kind()) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) @@ -168,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - create_err(&format!( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{source_path}`, found `{target_path}`", - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynCoercion { + span, + trait_name: "DispatchFromDyn", + note: true, + source_path, + target_path, + }); return; } if def_a.repr().c() || def_a.repr().packed() { - create_err( - "structs implementing `DispatchFromDyn` may not have \ - `#[repr(packed)]` or `#[repr(C)]`", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynRepr { span }); } let fields = &def_a.non_enum_variant().fields; @@ -195,8 +197,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let ty_b = field.ty(tcx, args_b); if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { - if layout.is_zst() && layout.align.abi.bytes() == 1 { - // ignore ZST fields with alignment of 1 byte + if layout.is_1zst() { + // ignore 1-ZST fields return false; } } @@ -205,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) { if ok.obligations.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for structs containing the field being coerced, \ - ZST fields with 1 byte alignment, and nothing else", - ) - .note(format!( - "extra field `{}` of type `{}` is not allowed", - field.name, ty_a, - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynZST { + span, + name: field.name, + ty: ty_a, + }); return false; } @@ -225,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef .collect::<Vec<_>>(); if coerced_fields.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced, none found", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynSingle { + span, + trait_name: "DispatchFromDyn", + note: true, + }); } else if coerced_fields.len() > 1 { - create_err("implementing the `DispatchFromDyn` trait requires multiple coercions") - .note( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - coerced_fields.len(), - coerced_fields - .iter() - .map(|field| { - format!( - "`{}` (`{}` to `{}`)", - field.name, - field.ty(tcx, args_a), - field.ty(tcx, args_b), - ) - }) - .collect::<Vec<_>>() - .join(", ") - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynMulti { + span, + coercions_note: true, + number: coerced_fields.len(), + coercions: coerced_fields + .iter() + .map(|field| { + format!( + "`{}` (`{}` to `{}`)", + field.name, + field.ty(tcx, args_a), + field.ty(tcx, args_b), + ) + }) + .collect::<Vec<_>>() + .join(", "), + }); } else { let ocx = ObligationCtxt::new(&infcx); for field in coerced_fields { @@ -280,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } _ => { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures", - ) - .emit(); + tcx.sess.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" }); } } } @@ -351,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe if def_a != def_b { let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::DispatchFromDynSame { span, - E0377, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{}`, found `{}`", + trait_name: "CoerceUnsized", + note: true, source_path, - target_path - ) - .emit(); + target_path, + }); return err_info; } @@ -437,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe .collect::<Vec<_>>(); if diff_fields.is_empty() { - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedOneField { span, - E0374, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with one field \ - being coerced, none found" - ) - .emit(); + trait_name: "CoerceUnsized", + note: true, + }); return err_info; } else if diff_fields.len() > 1 { let item = tcx.hir().expect_item(impl_did); @@ -455,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe tcx.def_span(impl_did) }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedMulti { span, - E0375, - "implementing the trait \ - `CoerceUnsized` requires multiple \ - coercions" - ) - .note( - "`CoerceUnsized` may only be implemented for \ - a coercion between structures with one field being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - diff_fields.len(), - diff_fields + coercions_note: true, + number: diff_fields.len(), + coercions: diff_fields .iter() - .map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) }) + .map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b)) .collect::<Vec<_>>() - .join(", ") - )) - .span_label(span, "requires multiple coercions") - .emit(); + .join(", "), + }); + return err_info; } @@ -487,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe } _ => { - struct_span_err!( - tcx.sess, - span, - E0376, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures" - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" }); return err_info; } }; @@ -532,13 +491,6 @@ fn infringing_fields_error( let trait_name = tcx.def_path_str(trait_did); - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0204, - "the trait `{trait_name}` cannot be implemented for this type" - ); - // We'll try to suggest constraining type parameters to fulfill the requirements of // their `Copy` implementation. let mut errors: BTreeMap<_, Vec<_>> = Default::default(); @@ -546,14 +498,15 @@ fn infringing_fields_error( let mut seen_tys = FxHashSet::default(); + let mut label_spans = Vec::new(); + for (field, ty, reason) in fields { // Only report an error once per type. if !seen_tys.insert(ty) { continue; } - let field_span = tcx.def_span(field.did); - err.span_label(field_span, format!("this field does not implement `{trait_name}`")); + label_spans.push(tcx.def_span(field.did)); match reason { InfringingFieldsReason::Fulfill(fulfillment_errors) => { @@ -617,13 +570,24 @@ fn infringing_fields_error( } } } + let mut notes = Vec::new(); for ((ty, error_predicate), spans) in errors { let span: MultiSpan = spans.into(); - err.span_note( + notes.push(errors::ImplForTyRequires { span, - format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"), - ); + error_predicate, + trait_name: trait_name.clone(), + ty, + }); } + + let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy { + span: impl_span, + trait_name, + label_spans, + notes, + }); + suggest_constraining_type_params( tcx, tcx.hir().get_generics(impl_did).expect("impls always have generics"), diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index a94c75f91..0042d683b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -7,7 +7,6 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -15,6 +14,8 @@ use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; +use crate::errors; + /// On-demand query: yields a map containing all types mapped to their inherent impls. pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { let mut collect = InherentCollect { tcx, impls_map: Default::default() }; @@ -45,14 +46,6 @@ struct InherentCollect<'tcx> { impls_map: CrateInherentImpls, } -const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible"; -const INTO_DEFINING_CRATE: &str = - "consider moving this inherent impl into the crate defining the type if possible"; -const ADD_ATTR_TO_TY: &str = "alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type \ - and `#[rustc_allow_incoherent_impl]` to the relevant impl items"; -const ADD_ATTR: &str = - "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items"; - impl<'tcx> InherentCollect<'tcx> { fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) { if let Some(ty_def_id) = ty_def_id.as_local() { @@ -69,30 +62,17 @@ impl<'tcx> InherentCollect<'tcx> { if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) { let impl_span = self.tcx.def_span(impl_def_id); - struct_span_err!( - self.tcx.sess, - impl_span, - E0390, - "cannot define inherent `impl` for a type outside of the crate where the type is defined", - ) - .help(INTO_DEFINING_CRATE) - .span_help(impl_span, ADD_ATTR_TO_TY) - .emit(); + self.tcx.sess.emit_err(errors::InherentTyOutside { span: impl_span }); return; } for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let impl_span = self.tcx.def_span(impl_def_id); - struct_span_err!( - self.tcx.sess, - impl_span, - E0390, - "cannot define inherent `impl` for a type outside of the crate where the type is defined", - ) - .help(INTO_DEFINING_CRATE) - .span_help(self.tcx.def_span(impl_item), ADD_ATTR) - .emit(); + self.tcx.sess.emit_err(errors::InherentTyOutsideRelevant { + span: impl_span, + help_span: self.tcx.def_span(impl_item), + }); return; } } @@ -104,16 +84,7 @@ impl<'tcx> InherentCollect<'tcx> { } } else { let impl_span = self.tcx.def_span(impl_def_id); - struct_span_err!( - self.tcx.sess, - impl_span, - E0116, - "cannot define inherent `impl` for a type outside of the crate \ - where the type is defined" - ) - .span_label(impl_span, "impl for type defined outside of crate.") - .note("define and implement a trait or new type instead") - .emit(); + self.tcx.sess.emit_err(errors::InherentTyOutsideNew { span: impl_span }); } } @@ -124,34 +95,20 @@ impl<'tcx> InherentCollect<'tcx> { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let span = self.tcx.def_span(impl_def_id); - struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(errors::InherentTyOutsidePrimitive { span, - E0390, - "cannot define inherent `impl` for primitive types outside of `core`", - ) - .help(INTO_CORE) - .span_help(self.tcx.def_span(impl_item), ADD_ATTR) - .emit(); + help_span: self.tcx.def_span(impl_item), + }); return; } } } else { let span = self.tcx.def_span(impl_def_id); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0390, - "cannot define inherent `impl` for primitive types", - ); - err.help("consider using an extension trait instead"); + let mut note = None; if let ty::Ref(_, subty, _) = ty.kind() { - err.note(format!( - "you could also try moving the reference to \ - uses of `{subty}` (such as `self`) within the implementation" - )); + note = Some(errors::InherentPrimitiveTyNote { subty: *subty }); } - err.emit(); + self.tcx.sess.emit_err(errors::InherentPrimitiveTy { span, note }); return; } } @@ -178,15 +135,7 @@ impl<'tcx> InherentCollect<'tcx> { self.check_def_id(id, self_ty, data.principal_def_id().unwrap()); } ty::Dynamic(..) => { - struct_span_err!( - self.tcx.sess, - item_span, - E0785, - "cannot define inherent `impl` for a dyn auto trait" - ) - .span_label(item_span, "impl requires at least one non-auto trait") - .note("define and implement a new trait or type instead") - .emit(); + self.tcx.sess.emit_err(errors::InherentDyn { span: item_span }); } ty::Bool | ty::Char @@ -202,23 +151,12 @@ impl<'tcx> InherentCollect<'tcx> { | ty::FnPtr(_) | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), ty::Alias(..) | ty::Param(_) => { - let mut err = struct_span_err!( - self.tcx.sess, - item_span, - E0118, - "no nominal type found for inherent implementation" - ); - - err.span_label(item_span, "impl requires a nominal type") - .note("either implement a trait on it or create a newtype to wrap it instead"); - - err.emit(); + self.tcx.sess.emit_err(errors::InherentNominal { span: item_span }); } ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | 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 bbdb108c5..69020b1f1 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -245,7 +245,6 @@ fn do_orphan_check_impl<'tcx>( ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { |