diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/intrinsic.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/builtin.rs | 170 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/errors.rs | 70 |
5 files changed, 134 insertions, 139 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index d468027602c..fedc197e7ef 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -699,7 +699,7 @@ pub fn check_intrinsic_type( | sym::simd_reduce_min | sym::simd_reduce_max => (2, 0, vec![param(0)], param(1)), sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)), - sym::simd_shuffle_generic => (2, 1, vec![param(0), param(0)], param(1)), + sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)), other => { tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other }); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index e1727fc48a8..51194740450 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -27,20 +27,19 @@ enum NonAsmTypeReason<'tcx> { UnevaluatedSIMDArrayLength(DefId, ty::Const<'tcx>), Invalid(Ty<'tcx>), InvalidElement(DefId, Ty<'tcx>), + NotSizedPtr(Ty<'tcx>), } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, def_id: LocalDefId, + typing_env: ty::TypingEnv<'tcx>, get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, ) -> Self { InlineAsmCtxt { tcx, - typing_env: ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env: ty::ParamEnv::empty(), - }, + typing_env, target_features: tcx.asm_target_features(def_id), expr_ty: Box::new(get_operand_ty), } @@ -83,7 +82,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Float(FloatTy::F64) => Ok(InlineAsmType::F64), ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128), ty::FnPtr(..) => Ok(asm_ty_isize), - ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Ok(asm_ty_isize), + ty::RawPtr(elem_ty, _) => { + if self.is_thin_ptr_ty(elem_ty) { + Ok(asm_ty_isize) + } else { + Err(NonAsmTypeReason::NotSizedPtr(ty)) + } + } ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; let field = &fields[FieldIdx::ZERO]; @@ -189,6 +194,16 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { can be used as arguments for inline assembly", ).emit(); } + NonAsmTypeReason::NotSizedPtr(ty) => { + let msg = format!( + "cannot use value of unsized pointer type `{ty}` for inline assembly" + ); + self.tcx + .dcx() + .struct_span_err(expr.span, msg) + .with_note("only sized pointers can be used in inline assembly") + .emit(); + } NonAsmTypeReason::InvalidElement(did, ty) => { let msg = format!( "cannot use SIMD vector with element type `{ty}` for inline assembly" diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b46b805f0a9..cee2f487639 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params, }; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::misc::{ ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason, @@ -195,8 +195,14 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E // Just compute this for the side-effects, in particular reporting // errors; other parts of the code may demand it for the info of // course. - let span = tcx.def_span(impl_did); - tcx.at(span).ensure_ok().coerce_unsized_info(impl_did) + tcx.ensure_ok().coerce_unsized_info(impl_did) +} + +fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool { + span.ctxt() + .outer_expn_data() + .macro_def_id + .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id)) } fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { @@ -206,17 +212,29 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did); + let trait_name = "DispatchFromDyn"; let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span)); let source = trait_ref.self_ty(); - assert!(!source.has_escaping_bound_vars()); let target = { assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait); trait_ref.args.type_at(1) }; + // Check `CoercePointee` impl is WF -- if not, then there's no reason to report + // redundant errors for `DispatchFromDyn`. This is best effort, though. + let mut res = Ok(()); + tcx.for_each_relevant_impl( + tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)), + source, + |impl_def_id| { + res = res.and(tcx.ensure_ok().coerce_unsized_info(impl_def_id)); + }, + ); + res?; + debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target); let param_env = tcx.param_env(impl_did); @@ -242,26 +260,25 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() 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()); - - return Err(tcx.dcx().emit_err(errors::DispatchFromDynCoercion { + return Err(tcx.dcx().emit_err(errors::CoerceSameStruct { span, - trait_name: "DispatchFromDyn", + trait_name, note: true, source_path, target_path, })); } - let mut res = Ok(()); if def_a.repr().c() || def_a.repr().packed() { - res = Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span })); + return Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span })); } let fields = &def_a.non_enum_variant().fields; + let mut res = Ok(()); let coerced_fields = fields - .iter() - .filter(|field| { + .iter_enumerated() + .filter_map(|(i, field)| { // Ignore PhantomData fields let unnormalized_ty = tcx.type_of(field.did).instantiate_identity(); if tcx @@ -272,7 +289,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() .unwrap_or(unnormalized_ty) .is_phantom_data() { - return false; + return None; } let ty_a = field.ty(tcx, args_a); @@ -290,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() && !ty_a.has_non_region_param() { // ignore 1-ZST fields - return false; + return None; } res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST { @@ -299,64 +316,57 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() ty: ty_a, })); - return false; + None + } else { + Some((i, ty_a, ty_b, tcx.def_span(field.did))) } - - true }) .collect::<Vec<_>>(); + res?; if coerced_fields.is_empty() { - res = Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle { + return Err(tcx.dcx().emit_err(errors::CoerceNoField { span, - trait_name: "DispatchFromDyn", + trait_name, note: true, })); - } else if coerced_fields.len() > 1 { - res = Err(tcx.dcx().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 { + } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] { let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - for field in coerced_fields { - ocx.register_obligation(Obligation::new( - tcx, - cause.clone(), - param_env, - ty::TraitRef::new( - tcx, - dispatch_from_dyn_trait, - [field.ty(tcx, args_a), field.ty(tcx, args_b)], - ), - )); - } + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::TraitRef::new(tcx, dispatch_from_dyn_trait, [ty_a, ty_b]), + )); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - res = Err(infcx.err_ctxt().report_fulfillment_errors(errors)); + if is_from_coerce_pointee_derive(tcx, span) { + return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity { + span, + trait_name, + ty: trait_ref.self_ty(), + field_span, + field_ty: ty_a, + })); + } else { + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); + } } // Finally, resolve all regions. - res = res.and(ocx.resolve_regions_and_report_errors(impl_did, param_env, [])); + ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?; + + Ok(()) + } else { + return Err(tcx.dcx().emit_err(errors::CoerceMulti { + span, + trait_name, + number: coerced_fields.len(), + fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(), + })); } - res } - _ => Err(tcx - .dcx() - .emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" })), + _ => Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name })), } } @@ -366,13 +376,14 @@ pub(crate) fn coerce_unsized_info<'tcx>( ) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); let span = tcx.def_span(impl_did); + let trait_name = "CoerceUnsized"; let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); - let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span)); let source = tcx.type_of(impl_did).instantiate_identity(); let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity(); + assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.args.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); @@ -399,9 +410,9 @@ pub(crate) fn coerce_unsized_info<'tcx>( ) .emit(); } - (mt_a.ty, mt_b.ty, unsize_trait, None) + (mt_a.ty, mt_b.ty, unsize_trait, None, span) }; - let (source, target, trait_def_id, kind) = match (source.kind(), target.kind()) { + let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) { (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; @@ -422,9 +433,9 @@ pub(crate) fn coerce_unsized_info<'tcx>( 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()); - return Err(tcx.dcx().emit_err(errors::DispatchFromDynSame { + return Err(tcx.dcx().emit_err(errors::CoerceSameStruct { span, - trait_name: "CoerceUnsized", + trait_name, note: true, source_path, target_path, @@ -504,14 +515,14 @@ pub(crate) fn coerce_unsized_info<'tcx>( // Collect up all fields that were significantly changed // i.e., those that contain T in coerce_unsized T -> U - Some((i, a, b)) + Some((i, a, b, tcx.def_span(f.did))) }) .collect::<Vec<_>>(); if diff_fields.is_empty() { - return Err(tcx.dcx().emit_err(errors::CoerceUnsizedOneField { + return Err(tcx.dcx().emit_err(errors::CoerceNoField { span, - trait_name: "CoerceUnsized", + trait_name, note: true, })); } else if diff_fields.len() > 1 { @@ -522,27 +533,21 @@ pub(crate) fn coerce_unsized_info<'tcx>( tcx.def_span(impl_did) }; - return Err(tcx.dcx().emit_err(errors::CoerceUnsizedMulti { + return Err(tcx.dcx().emit_err(errors::CoerceMulti { span, - coercions_note: true, + trait_name, number: diff_fields.len(), - coercions: diff_fields - .iter() - .map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b)) - .collect::<Vec<_>>() - .join(", "), + fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(), })); } - let (i, a, b) = diff_fields[0]; + let (i, a, b, field_span) = diff_fields[0]; let kind = ty::adjustment::CustomCoerceUnsized::Struct(i); - (a, b, coerce_unsized_trait, Some(kind)) + (a, b, coerce_unsized_trait, Some(kind), field_span) } _ => { - return Err(tcx - .dcx() - .emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" })); + return Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name })); } }; @@ -557,12 +562,23 @@ pub(crate) fn coerce_unsized_info<'tcx>( ); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); + if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); + if is_from_coerce_pointee_derive(tcx, span) { + return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity { + span, + trait_name, + ty: trait_ref.self_ty(), + field_span, + field_ty: source, + })); + } else { + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); + } } // Finally, resolve all regions. - let _ = ocx.resolve_regions_and_report_errors(impl_did, param_env, []); + ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?; Ok(CoerceUnsizedInfo { custom_kind: kind }) } diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 1bc60087ab5..0245d4c9fe4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -199,11 +199,7 @@ fn check_object_overlap<'tcx>( for component_def_id in component_def_ids { if !tcx.is_dyn_compatible(component_def_id) { - // Without the 'dyn_compatible_for_dispatch' feature this is an error - // which will be reported by wfcheck. Ignore it here. - // This is tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`. - // With the feature enabled, the trait is not implemented automatically, - // so this is valid. + // This is a WF error tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`. } else { let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id); if supertrait_def_ids diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 1a0b0edb257..99262f9871e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1165,18 +1165,6 @@ pub(crate) struct InherentTyOutside { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub(crate) struct DispatchFromDynCoercion<'a> { - #[primary_span] - pub span: Span, - pub trait_name: &'a str, - #[note(hir_analysis_coercion_between_struct_same_note)] - pub note: bool, - pub source_path: String, - pub target_path: String, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] pub(crate) struct DispatchFromDynRepr { #[primary_span] @@ -1293,41 +1281,40 @@ pub(crate) struct DispatchFromDynZST<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub(crate) struct DispatchFromDynSingle<'a> { +#[diag(hir_analysis_coerce_zero, code = E0374)] +pub(crate) struct CoerceNoField { #[primary_span] pub span: Span, - pub trait_name: &'a str, + pub trait_name: &'static str, #[note(hir_analysis_coercion_between_struct_single_note)] pub note: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)] -#[note] -pub(crate) struct DispatchFromDynMulti { +#[diag(hir_analysis_coerce_multi, code = E0375)] +pub(crate) struct CoerceMulti { + pub trait_name: &'static str, #[primary_span] pub span: Span, - #[note(hir_analysis_coercions_note)] - pub coercions_note: bool, pub number: usize, - pub coercions: String, + #[note] + pub fields: MultiSpan, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0376)] -pub(crate) struct DispatchFromDynStruct<'a> { +#[diag(hir_analysis_coerce_unsized_may, code = E0377)] +pub(crate) struct CoerceUnsizedNonStruct { #[primary_span] pub span: Span, - pub trait_name: &'a str, + pub trait_name: &'static str, } #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0377)] -pub(crate) struct DispatchFromDynSame<'a> { +pub(crate) struct CoerceSameStruct { #[primary_span] pub span: Span, - pub trait_name: &'a str, + pub trait_name: &'static str, #[note(hir_analysis_coercion_between_struct_same_note)] pub note: bool, pub source_path: String, @@ -1335,34 +1322,15 @@ pub(crate) struct DispatchFromDynSame<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0374)] -pub(crate) struct CoerceUnsizedOneField<'a> { +#[diag(hir_analysis_coerce_unsized_field_validity)] +pub(crate) struct CoerceFieldValidity<'tcx> { #[primary_span] pub span: Span, - pub trait_name: &'a str, - #[note(hir_analysis_coercion_between_struct_single_note)] - pub note: bool, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_multi, code = E0375)] -#[note] -pub(crate) struct CoerceUnsizedMulti { - #[primary_span] + pub ty: Ty<'tcx>, + pub trait_name: &'static str, #[label] - pub span: Span, - #[note(hir_analysis_coercions_note)] - pub coercions_note: bool, - pub number: usize, - pub coercions: String, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub(crate) struct CoerceUnsizedMay<'a> { - #[primary_span] - pub span: Span, - pub trait_name: &'a str, + pub field_span: Span, + pub field_ty: Ty<'tcx>, } #[derive(Diagnostic)] |
