@@ -4,14 +4,15 @@ use std::ops::ControlFlow;
44use rustc_abi:: { ExternAbi , FieldIdx , ScalableElt } ;
55use rustc_data_structures:: unord:: { UnordMap , UnordSet } ;
66use rustc_errors:: codes:: * ;
7- use rustc_errors:: { EmissionGuarantee , MultiSpan } ;
7+ use rustc_errors:: { Diag , DiagCtxtHandle , Diagnostic , EmissionGuarantee , Level , MultiSpan } ;
88use rustc_hir as hir;
99use rustc_hir:: attrs:: ReprAttr :: ReprPacked ;
1010use rustc_hir:: def:: { CtorKind , DefKind } ;
1111use rustc_hir:: { LangItem , Node , find_attr, intravisit} ;
1212use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
1313use rustc_infer:: traits:: { Obligation , ObligationCauseCode , WellFormedLoc } ;
1414use rustc_lint_defs:: builtin:: { REPR_TRANSPARENT_NON_ZST_FIELDS , UNSUPPORTED_CALLING_CONVENTIONS } ;
15+ use rustc_macros:: Diagnostic ;
1516use rustc_middle:: hir:: nested_filter;
1617use rustc_middle:: middle:: resolve_bound_vars:: ResolvedArg ;
1718use rustc_middle:: middle:: stability:: EvalResult ;
@@ -53,6 +54,22 @@ fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T
5354}
5455
5556pub fn check_abi ( tcx : TyCtxt < ' _ > , hir_id : hir:: HirId , span : Span , abi : ExternAbi ) {
57+ struct UnsupportedCallingConventions {
58+ abi : ExternAbi ,
59+ }
60+
61+ impl < ' a > Diagnostic < ' a , ( ) > for UnsupportedCallingConventions {
62+ fn into_diag ( self , dcx : DiagCtxtHandle < ' a > , level : Level ) -> Diag < ' a , ( ) > {
63+ let Self { abi } = self ;
64+ let mut lint = Diag :: new (
65+ dcx,
66+ level,
67+ format ! ( "{abi} is not a supported ABI for the current target" ) ,
68+ ) ;
69+ add_abi_diag_help ( abi, & mut lint) ;
70+ lint
71+ }
72+ }
5673 // FIXME: This should be checked earlier, e.g. in `rustc_ast_lowering`, as this
5774 // currently only guards function imports, function definitions, and function pointer types.
5875 // Functions in trait declarations can still use "deprecated" ABIs without any warning.
@@ -64,12 +81,12 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi
6481 tcx. dcx ( ) . span_delayed_bug ( span, format ! ( "{abi} should be rejected in ast_lowering" ) ) ;
6582 }
6683 AbiMapping :: Deprecated ( ..) => {
67- tcx. node_span_lint ( UNSUPPORTED_CALLING_CONVENTIONS , hir_id , span , |lint| {
68- lint . primary_message ( format ! (
69- "{abi} is not a supported ABI for the current target"
70- ) ) ;
71- add_abi_diag_help ( abi, lint ) ;
72- } ) ;
84+ tcx. emit_node_span_lint (
85+ UNSUPPORTED_CALLING_CONVENTIONS ,
86+ hir_id ,
87+ span ,
88+ UnsupportedCallingConventions { abi } ,
89+ ) ;
7390 }
7491 }
7592}
@@ -174,6 +191,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
174191
175192/// Check that a `static` is inhabited.
176193fn check_static_inhabited ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
194+ #[ derive( Diagnostic ) ]
195+ #[ diag( "static of uninhabited type" ) ]
196+ #[ note( "uninhabited statics cannot be initialized, and any access would be an immediate error" ) ]
197+ struct StaticOfUninhabitedType ;
198+
177199 // Make sure statics are inhabited.
178200 // Other parts of the compiler assume that there are no uninhabited places. In principle it
179201 // would be enough to check this for `extern` statics, as statics with an initializer will
@@ -204,15 +226,11 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
204226 }
205227 } ;
206228 if layout. is_uninhabited ( ) {
207- tcx. node_span_lint (
229+ tcx. emit_node_span_lint (
208230 UNINHABITED_STATIC ,
209231 tcx. local_def_id_to_hir_id ( def_id) ,
210232 span,
211- |lint| {
212- lint. primary_message ( "static of uninhabited type" ) ;
213- lint
214- . note ( "uninhabited statics cannot be initialized, and any access would be an immediate error" ) ;
215- } ,
233+ StaticOfUninhabitedType ,
216234 ) ;
217235 }
218236}
@@ -1637,6 +1655,39 @@ pub(super) fn check_packed_inner(
16371655}
16381656
16391657pub ( super ) fn check_transparent < ' tcx > ( tcx : TyCtxt < ' tcx > , adt : ty:: AdtDef < ' tcx > ) {
1658+ struct ZeroSizedFieldReprTransparentIncompatibility < ' tcx > {
1659+ unsuited : UnsuitedInfo < ' tcx > ,
1660+ }
1661+
1662+ impl < ' a , ' tcx > Diagnostic < ' a , ( ) > for ZeroSizedFieldReprTransparentIncompatibility < ' tcx > {
1663+ fn into_diag ( self , dcx : DiagCtxtHandle < ' a > , level : Level ) -> Diag < ' a , ( ) > {
1664+ let Self { unsuited } = self ;
1665+ let ( title, note) = match unsuited. reason {
1666+ UnsuitedReason :: NonExhaustive => (
1667+ "external non-exhaustive types" ,
1668+ "is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future." ,
1669+ ) ,
1670+ UnsuitedReason :: PrivateField => (
1671+ "external types with private fields" ,
1672+ "contains private fields, so it could become non-zero-sized in the future." ,
1673+ ) ,
1674+ UnsuitedReason :: ReprC => (
1675+ "`repr(C)` types" ,
1676+ "is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets." ,
1677+ ) ,
1678+ } ;
1679+ Diag :: new (
1680+ dcx,
1681+ level,
1682+ format ! ( "zero-sized fields in `repr(transparent)` cannot contain {title}" ) ,
1683+ )
1684+ . with_note ( format ! (
1685+ "this field contains `{field_ty}`, which {note}" ,
1686+ field_ty = unsuited. ty,
1687+ ) )
1688+ }
1689+ }
1690+
16401691 if !adt. repr ( ) . transparent ( ) {
16411692 return ;
16421693 }
@@ -1747,29 +1798,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
17471798 // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
17481799 // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
17491800 if non_trivial_count > 0 || prev_unsuited_1zst {
1750- tcx. node_span_lint (
1801+ tcx. emit_node_span_lint (
17511802 REPR_TRANSPARENT_NON_ZST_FIELDS ,
17521803 tcx. local_def_id_to_hir_id ( adt. did ( ) . expect_local ( ) ) ,
17531804 field. span ,
1754- |lint| {
1755- let title = match unsuited. reason {
1756- UnsuitedReason :: NonExhaustive => "external non-exhaustive types" ,
1757- UnsuitedReason :: PrivateField => "external types with private fields" ,
1758- UnsuitedReason :: ReprC => "`repr(C)` types" ,
1759- } ;
1760- lint. primary_message (
1761- format ! ( "zero-sized fields in `repr(transparent)` cannot contain {title}" ) ,
1762- ) ;
1763- let note = match unsuited. reason {
1764- UnsuitedReason :: NonExhaustive => "is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future." ,
1765- UnsuitedReason :: PrivateField => "contains private fields, so it could become non-zero-sized in the future." ,
1766- UnsuitedReason :: ReprC => "is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets." ,
1767- } ;
1768- lint. note ( format ! (
1769- "this field contains `{field_ty}`, which {note}" ,
1770- field_ty = unsuited. ty,
1771- ) ) ;
1772- } ,
1805+ ZeroSizedFieldReprTransparentIncompatibility { unsuited } ,
17731806 ) ;
17741807 } else {
17751808 prev_unsuited_1zst = true ;
0 commit comments