@@ -5,7 +5,7 @@ use rustc_hir::{CRATE_HIR_ID, HirId};
55use rustc_middle:: mir:: { self , Location , traversal} ;
66use rustc_middle:: ty:: { self , Instance , InstanceKind , Ty , TyCtxt } ;
77use rustc_span:: def_id:: DefId ;
8- use rustc_span:: { DUMMY_SP , Span , Symbol , sym} ;
8+ use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
99use rustc_target:: callconv:: { FnAbi , PassMode } ;
1010
1111use crate :: errors;
@@ -57,7 +57,8 @@ fn do_check_simd_vector_abi<'tcx>(
5757 def_id : DefId ,
5858 is_call : bool ,
5959 loc : impl Fn ( ) -> ( Span , HirId ) ,
60- ) {
60+ ) -> Option < ErrorGuaranteed > {
61+ let mut res = None ;
6162 let codegen_attrs = tcx. codegen_fn_attrs ( def_id) ;
6263 let have_feature = |feat : Symbol | {
6364 let target_feats = tcx. sess . unstable_target_features . contains ( & feat) ;
@@ -74,23 +75,25 @@ fn do_check_simd_vector_abi<'tcx>(
7475 Some ( ( _, feature) ) => feature,
7576 None => {
7677 let ( span, _hir_id) = loc ( ) ;
77- tcx. dcx ( ) . emit_err ( errors:: AbiErrorUnsupportedVectorType {
78- span,
79- ty : arg_abi. layout . ty ,
80- is_call,
81- } ) ;
78+ res = res. or ( Some ( tcx. dcx ( ) . emit_err (
79+ errors:: AbiErrorUnsupportedVectorType {
80+ span,
81+ ty : arg_abi. layout . ty ,
82+ is_call,
83+ } ,
84+ ) ) ) ;
8285 continue ;
8386 }
8487 } ;
8588 if !feature. is_empty ( ) && !have_feature ( Symbol :: intern ( feature) ) {
8689 let ( span, _hir_id) = loc ( ) ;
87- tcx. dcx ( ) . emit_err ( errors:: AbiErrorDisabledVectorType {
90+ res = res . or ( Some ( tcx. dcx ( ) . emit_err ( errors:: AbiErrorDisabledVectorType {
8891 span,
8992 required_feature : feature,
9093 ty : arg_abi. layout . ty ,
9194 is_call,
9295 is_scalable : false ,
93- } ) ;
96+ } ) ) ) ;
9497 }
9598 }
9699 UsesVectorRegisters :: ScalableVector => {
@@ -101,13 +104,13 @@ fn do_check_simd_vector_abi<'tcx>(
101104 } ;
102105 if !required_feature. is_empty ( ) && !have_feature ( Symbol :: intern ( required_feature) ) {
103106 let ( span, _) = loc ( ) ;
104- tcx. dcx ( ) . emit_err ( errors:: AbiErrorDisabledVectorType {
107+ res = res . or ( Some ( tcx. dcx ( ) . emit_err ( errors:: AbiErrorDisabledVectorType {
105108 span,
106109 required_feature,
107110 ty : arg_abi. layout . ty ,
108111 is_call,
109112 is_scalable : true ,
110- } ) ;
113+ } ) ) ) ;
111114 }
112115 }
113116 UsesVectorRegisters :: No => {
@@ -118,13 +121,14 @@ fn do_check_simd_vector_abi<'tcx>(
118121 // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
119122 if abi. conv == CanonAbi :: X86 ( X86Call :: Vectorcall ) && !have_feature ( sym:: sse2) {
120123 let ( span, _hir_id) = loc ( ) ;
121- tcx. dcx ( ) . emit_err ( errors:: AbiRequiredTargetFeature {
124+ res = res . or ( Some ( tcx. dcx ( ) . emit_err ( errors:: AbiRequiredTargetFeature {
122125 span,
123126 required_feature : "sse2" ,
124127 abi : "vectorcall" ,
125128 is_call,
126- } ) ;
129+ } ) ) ) ;
127130 }
131+ res
128132}
129133
130134/// Emit an error when a non-rustic ABI has unsized parameters.
@@ -136,42 +140,47 @@ fn do_check_unsized_params<'tcx>(
136140 fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
137141 is_call : bool ,
138142 loc : impl Fn ( ) -> ( Span , HirId ) ,
139- ) {
143+ ) -> Option < ErrorGuaranteed > {
140144 // Unsized parameters are allowed with the (unstable) "Rust" (and similar) ABIs.
141145 if fn_abi. conv . is_rustic_abi ( ) {
142- return ;
146+ return None ;
143147 }
144148
149+ let mut res = None ;
145150 for arg_abi in fn_abi. args . iter ( ) {
146151 if !arg_abi. layout . layout . is_sized ( ) {
147152 let ( span, _hir_id) = loc ( ) ;
148- tcx. dcx ( ) . emit_err ( errors:: AbiErrorUnsupportedUnsizedParameter {
153+ res = res . or ( Some ( tcx. dcx ( ) . emit_err ( errors:: AbiErrorUnsupportedUnsizedParameter {
149154 span,
150155 ty : arg_abi. layout . ty ,
151156 is_call,
152- } ) ;
157+ } ) ) ) ;
153158 }
154159 }
160+ res
155161}
156162
157163/// Checks the ABI of an Instance, emitting an error when:
158164///
159165/// - a non-rustic ABI uses unsized parameters
160166/// - the signature requires target features that are not enabled
161- fn check_instance_abi < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) {
167+ fn check_instance_abi < ' tcx > (
168+ tcx : TyCtxt < ' tcx > ,
169+ instance : Instance < ' tcx > ,
170+ ) -> Option < ErrorGuaranteed > {
162171 let typing_env = ty:: TypingEnv :: fully_monomorphized ( ) ;
163172 let ty = instance. ty ( tcx, typing_env) ;
164173 if ty. is_fn ( ) && ty. fn_sig ( tcx) . abi ( ) == ExternAbi :: Unadjusted {
165174 // We disable all checks for the unadjusted ABI to allow linking to arbitrary LLVM
166175 // intrinsics
167- return ;
176+ return None ;
168177 }
169178 let Ok ( abi) = tcx. fn_abi_of_instance ( typing_env. as_query_input ( ( instance, ty:: List :: empty ( ) ) ) )
170179 else {
171180 // An error will be reported during codegen if we cannot determine the ABI of this
172181 // function.
173182 tcx. dcx ( ) . delayed_bug ( "ABI computation failure should lead to compilation failure" ) ;
174- return ;
183+ return None ;
175184 } ;
176185 // Unlike the call-site check, we do also check "Rust" ABI functions here.
177186 // This should never trigger, *except* if we start making use of vector registers
@@ -186,8 +195,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
186195 def_id. as_local ( ) . map ( |did| tcx. local_def_id_to_hir_id ( did) ) . unwrap_or ( CRATE_HIR_ID ) ,
187196 )
188197 } ;
189- do_check_unsized_params ( tcx, abi, /*is_call*/ false , loc) ;
190- do_check_simd_vector_abi ( tcx, abi, instance. def_id ( ) , /*is_call*/ false , loc) ;
198+ // Call both checks unconditionally for their diagnostic side effects before combining.
199+ let unsized_res = do_check_unsized_params ( tcx, abi, /*is_call*/ false , loc) ;
200+ let simd_res = do_check_simd_vector_abi ( tcx, abi, instance. def_id ( ) , /*is_call*/ false , loc) ;
201+ unsized_res. or ( simd_res)
191202}
192203
193204/// Check the ABI at a call site, emitting an error when:
@@ -199,14 +210,14 @@ fn check_call_site_abi<'tcx>(
199210 callee : Ty < ' tcx > ,
200211 caller : InstanceKind < ' tcx > ,
201212 loc : impl Fn ( ) -> ( Span , HirId ) + Copy ,
202- ) {
213+ ) -> Option < ErrorGuaranteed > {
203214 let extern_abi = callee. fn_sig ( tcx) . abi ( ) ;
204215 if extern_abi. is_rustic_abi ( ) || extern_abi == ExternAbi :: Unadjusted {
205216 // We directly handle the soundness of Rust ABIs -- so let's skip the majority of
206217 // call sites to avoid a perf regression.
207218 // We disable all checks for the unadjusted ABI to allow linking to arbitrary LLVM
208219 // intrinsics
209- return ;
220+ return None ;
210221 }
211222 let typing_env = ty:: TypingEnv :: fully_monomorphized ( ) ;
212223 let callee_abi = match * callee. kind ( ) {
@@ -216,7 +227,7 @@ fn check_call_site_abi<'tcx>(
216227 ty:: FnDef ( def_id, args) => {
217228 // Intrinsics are handled separately by the compiler.
218229 if tcx. intrinsic ( def_id) . is_some ( ) {
219- return ;
230+ return None ;
220231 }
221232 let instance = ty:: Instance :: expect_resolve ( tcx, typing_env, def_id, args, DUMMY_SP ) ;
222233 tcx. fn_abi_of_instance ( typing_env. as_query_input ( ( instance, ty:: List :: empty ( ) ) ) )
@@ -228,13 +239,21 @@ fn check_call_site_abi<'tcx>(
228239
229240 let Ok ( callee_abi) = callee_abi else {
230241 // ABI failed to compute; this will not get through codegen.
231- return ;
242+ return None ;
232243 } ;
233- do_check_unsized_params ( tcx, callee_abi, /*is_call*/ true , loc) ;
234- do_check_simd_vector_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , loc) ;
244+ // Call both checks unconditionally for their diagnostic side effects before combining.
245+ let unsized_res = do_check_unsized_params ( tcx, callee_abi, /*is_call*/ true , loc) ;
246+ let simd_res =
247+ do_check_simd_vector_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , loc) ;
248+ unsized_res. or ( simd_res)
235249}
236250
237- fn check_callees_abi < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > , body : & mir:: Body < ' tcx > ) {
251+ fn check_callees_abi < ' tcx > (
252+ tcx : TyCtxt < ' tcx > ,
253+ instance : Instance < ' tcx > ,
254+ body : & mir:: Body < ' tcx > ,
255+ ) -> Option < ErrorGuaranteed > {
256+ let mut res = None ;
238257 // Check all function call terminators.
239258 for ( bb, _data) in traversal:: mono_reachable ( body, tcx, instance) {
240259 let terminator = body. basic_blocks [ bb] . terminator ( ) ;
@@ -247,7 +266,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
247266 ty:: TypingEnv :: fully_monomorphized ( ) ,
248267 ty:: EarlyBinder :: bind ( callee_ty) ,
249268 ) ;
250- check_call_site_abi ( tcx, callee_ty, body. source . instance , || {
269+ res = res . or ( check_call_site_abi ( tcx, callee_ty, body. source . instance , || {
251270 let loc = Location {
252271 block : bb,
253272 statement_index : body. basic_blocks [ bb] . statements . len ( ) ,
@@ -259,18 +278,21 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
259278 . lint_root ( & body. source_scopes )
260279 . unwrap_or ( CRATE_HIR_ID ) ,
261280 )
262- } ) ;
281+ } ) ) ;
263282 }
264283 _ => { }
265284 }
266285 }
286+ res
267287}
268288
269289pub ( crate ) fn check_feature_dependent_abi < ' tcx > (
270290 tcx : TyCtxt < ' tcx > ,
271291 instance : Instance < ' tcx > ,
272292 body : & ' tcx mir:: Body < ' tcx > ,
273- ) {
274- check_instance_abi ( tcx, instance) ;
275- check_callees_abi ( tcx, instance, body) ;
293+ ) -> Option < ErrorGuaranteed > {
294+ // Call both checks unconditionally for their diagnostic side effects before combining.
295+ let instance_res = check_instance_abi ( tcx, instance) ;
296+ let callees_res = check_callees_abi ( tcx, instance, body) ;
297+ instance_res. or ( callees_res)
276298}
0 commit comments