1
1
use crate :: check:: intrinsicck:: InlineAsmCtxt ;
2
2
3
- use super :: coercion:: CoerceMany ;
4
3
use super :: compare_method:: check_type_bounds;
5
4
use super :: compare_method:: { compare_impl_method, compare_ty_impl} ;
6
5
use super :: * ;
@@ -10,10 +9,8 @@ use rustc_hir as hir;
10
9
use rustc_hir:: def:: { DefKind , Res } ;
11
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
12
11
use rustc_hir:: intravisit:: Visitor ;
13
- use rustc_hir:: lang_items:: LangItem ;
14
12
use rustc_hir:: { ItemKind , Node , PathSegment } ;
15
13
use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
16
- use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
17
14
use rustc_infer:: infer:: { DefiningAnchor , RegionVariableOrigin , TyCtxtInferExt } ;
18
15
use rustc_infer:: traits:: Obligation ;
19
16
use rustc_lint:: builtin:: REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS ;
@@ -34,7 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
34
31
35
32
use std:: ops:: ControlFlow ;
36
33
37
- pub ( super ) fn check_abi ( tcx : TyCtxt < ' _ > , hir_id : hir:: HirId , span : Span , abi : Abi ) {
34
+ pub fn check_abi ( tcx : TyCtxt < ' _ > , hir_id : hir:: HirId , span : Span , abi : Abi ) {
38
35
match tcx. sess . target . is_abi_supported ( abi) {
39
36
Some ( true ) => ( ) ,
40
37
Some ( false ) => {
@@ -69,313 +66,6 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
69
66
}
70
67
}
71
68
72
- /// Helper used for fns and closures. Does the grungy work of checking a function
73
- /// body and returns the function context used for that purpose, since in the case of a fn item
74
- /// there is still a bit more to do.
75
- ///
76
- /// * ...
77
- /// * inherited: other fields inherited from the enclosing fn (if any)
78
- #[ instrument( skip( inherited, body) , level = "debug" ) ]
79
- pub ( super ) fn check_fn < ' a , ' tcx > (
80
- inherited : & ' a Inherited < ' tcx > ,
81
- param_env : ty:: ParamEnv < ' tcx > ,
82
- fn_sig : ty:: FnSig < ' tcx > ,
83
- decl : & ' tcx hir:: FnDecl < ' tcx > ,
84
- fn_id : hir:: HirId ,
85
- body : & ' tcx hir:: Body < ' tcx > ,
86
- can_be_generator : Option < hir:: Movability > ,
87
- return_type_pre_known : bool ,
88
- ) -> ( FnCtxt < ' a , ' tcx > , Option < GeneratorTypes < ' tcx > > ) {
89
- // Create the function context. This is either derived from scratch or,
90
- // in the case of closures, based on the outer context.
91
- let mut fcx = FnCtxt :: new ( inherited, param_env, body. value . hir_id ) ;
92
- fcx. ps . set ( UnsafetyState :: function ( fn_sig. unsafety , fn_id) ) ;
93
- fcx. return_type_pre_known = return_type_pre_known;
94
-
95
- let tcx = fcx. tcx ;
96
- let hir = tcx. hir ( ) ;
97
-
98
- let declared_ret_ty = fn_sig. output ( ) ;
99
-
100
- let ret_ty =
101
- fcx. register_infer_ok_obligations ( fcx. infcx . replace_opaque_types_with_inference_vars (
102
- declared_ret_ty,
103
- body. value . hir_id ,
104
- decl. output . span ( ) ,
105
- param_env,
106
- ) ) ;
107
- // If we replaced declared_ret_ty with infer vars, then we must be inferring
108
- // an opaque type, so set a flag so we can improve diagnostics.
109
- fcx. return_type_has_opaque = ret_ty != declared_ret_ty;
110
-
111
- fcx. ret_coercion = Some ( RefCell :: new ( CoerceMany :: new ( ret_ty) ) ) ;
112
-
113
- let span = body. value . span ;
114
-
115
- fn_maybe_err ( tcx, span, fn_sig. abi ) ;
116
-
117
- if fn_sig. abi == Abi :: RustCall {
118
- let expected_args = if let ImplicitSelfKind :: None = decl. implicit_self { 1 } else { 2 } ;
119
-
120
- let err = || {
121
- let item = match tcx. hir ( ) . get ( fn_id) {
122
- Node :: Item ( hir:: Item { kind : ItemKind :: Fn ( header, ..) , .. } ) => Some ( header) ,
123
- Node :: ImplItem ( hir:: ImplItem {
124
- kind : hir:: ImplItemKind :: Fn ( header, ..) , ..
125
- } ) => Some ( header) ,
126
- Node :: TraitItem ( hir:: TraitItem {
127
- kind : hir:: TraitItemKind :: Fn ( header, ..) ,
128
- ..
129
- } ) => Some ( header) ,
130
- // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
131
- Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Closure { .. } , .. } ) => None ,
132
- node => bug ! ( "Item being checked wasn't a function/closure: {:?}" , node) ,
133
- } ;
134
-
135
- if let Some ( header) = item {
136
- tcx. sess . span_err ( header. span , "functions with the \" rust-call\" ABI must take a single non-self argument that is a tuple" ) ;
137
- }
138
- } ;
139
-
140
- if fn_sig. inputs ( ) . len ( ) != expected_args {
141
- err ( )
142
- } else {
143
- // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
144
- // This will probably require wide-scale changes to support a TupleKind obligation
145
- // We can't resolve this without knowing the type of the param
146
- if !matches ! ( fn_sig. inputs( ) [ expected_args - 1 ] . kind( ) , ty:: Tuple ( _) | ty:: Param ( _) ) {
147
- err ( )
148
- }
149
- }
150
- }
151
-
152
- if body. generator_kind . is_some ( ) && can_be_generator. is_some ( ) {
153
- let yield_ty = fcx
154
- . next_ty_var ( TypeVariableOrigin { kind : TypeVariableOriginKind :: TypeInference , span } ) ;
155
- fcx. require_type_is_sized ( yield_ty, span, traits:: SizedYieldType ) ;
156
-
157
- // Resume type defaults to `()` if the generator has no argument.
158
- let resume_ty = fn_sig. inputs ( ) . get ( 0 ) . copied ( ) . unwrap_or_else ( || tcx. mk_unit ( ) ) ;
159
-
160
- fcx. resume_yield_tys = Some ( ( resume_ty, yield_ty) ) ;
161
- }
162
-
163
- GatherLocalsVisitor :: new ( & fcx) . visit_body ( body) ;
164
-
165
- // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
166
- // (as it's created inside the body itself, not passed in from outside).
167
- let maybe_va_list = if fn_sig. c_variadic {
168
- let span = body. params . last ( ) . unwrap ( ) . span ;
169
- let va_list_did = tcx. require_lang_item ( LangItem :: VaList , Some ( span) ) ;
170
- let region = fcx. next_region_var ( RegionVariableOrigin :: MiscVariable ( span) ) ;
171
-
172
- Some ( tcx. bound_type_of ( va_list_did) . subst ( tcx, & [ region. into ( ) ] ) )
173
- } else {
174
- None
175
- } ;
176
-
177
- // Add formal parameters.
178
- let inputs_hir = hir. fn_decl_by_hir_id ( fn_id) . map ( |decl| & decl. inputs ) ;
179
- let inputs_fn = fn_sig. inputs ( ) . iter ( ) . copied ( ) ;
180
- for ( idx, ( param_ty, param) ) in inputs_fn. chain ( maybe_va_list) . zip ( body. params ) . enumerate ( ) {
181
- // Check the pattern.
182
- let ty_span = try { inputs_hir?. get ( idx) ?. span } ;
183
- fcx. check_pat_top ( & param. pat , param_ty, ty_span, false ) ;
184
-
185
- // Check that argument is Sized.
186
- // The check for a non-trivial pattern is a hack to avoid duplicate warnings
187
- // for simple cases like `fn foo(x: Trait)`,
188
- // where we would error once on the parameter as a whole, and once on the binding `x`.
189
- if param. pat . simple_ident ( ) . is_none ( ) && !tcx. features ( ) . unsized_fn_params {
190
- fcx. require_type_is_sized ( param_ty, param. pat . span , traits:: SizedArgumentType ( ty_span) ) ;
191
- }
192
-
193
- fcx. write_ty ( param. hir_id , param_ty) ;
194
- }
195
-
196
- inherited. typeck_results . borrow_mut ( ) . liberated_fn_sigs_mut ( ) . insert ( fn_id, fn_sig) ;
197
-
198
- fcx. in_tail_expr = true ;
199
- if let ty:: Dynamic ( ..) = declared_ret_ty. kind ( ) {
200
- // FIXME: We need to verify that the return type is `Sized` after the return expression has
201
- // been evaluated so that we have types available for all the nodes being returned, but that
202
- // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
203
- // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
204
- // while keeping the current ordering we will ignore the tail expression's type because we
205
- // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
206
- // because we will trigger "unreachable expression" lints unconditionally.
207
- // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
208
- // case that a newcomer might make, returning a bare trait, and in that case we populate
209
- // the tail expression's type so that the suggestion will be correct, but ignore all other
210
- // possible cases.
211
- fcx. check_expr ( & body. value ) ;
212
- fcx. require_type_is_sized ( declared_ret_ty, decl. output . span ( ) , traits:: SizedReturnType ) ;
213
- } else {
214
- fcx. require_type_is_sized ( declared_ret_ty, decl. output . span ( ) , traits:: SizedReturnType ) ;
215
- fcx. check_return_expr ( & body. value , false ) ;
216
- }
217
- fcx. in_tail_expr = false ;
218
-
219
- // We insert the deferred_generator_interiors entry after visiting the body.
220
- // This ensures that all nested generators appear before the entry of this generator.
221
- // resolve_generator_interiors relies on this property.
222
- let gen_ty = if let ( Some ( _) , Some ( gen_kind) ) = ( can_be_generator, body. generator_kind ) {
223
- let interior = fcx
224
- . next_ty_var ( TypeVariableOrigin { kind : TypeVariableOriginKind :: MiscVariable , span } ) ;
225
- fcx. deferred_generator_interiors . borrow_mut ( ) . push ( ( body. id ( ) , interior, gen_kind) ) ;
226
-
227
- let ( resume_ty, yield_ty) = fcx. resume_yield_tys . unwrap ( ) ;
228
- Some ( GeneratorTypes {
229
- resume_ty,
230
- yield_ty,
231
- interior,
232
- movability : can_be_generator. unwrap ( ) ,
233
- } )
234
- } else {
235
- None
236
- } ;
237
-
238
- // Finalize the return check by taking the LUB of the return types
239
- // we saw and assigning it to the expected return type. This isn't
240
- // really expected to fail, since the coercions would have failed
241
- // earlier when trying to find a LUB.
242
- let coercion = fcx. ret_coercion . take ( ) . unwrap ( ) . into_inner ( ) ;
243
- let mut actual_return_ty = coercion. complete ( & fcx) ;
244
- debug ! ( "actual_return_ty = {:?}" , actual_return_ty) ;
245
- if let ty:: Dynamic ( ..) = declared_ret_ty. kind ( ) {
246
- // We have special-cased the case where the function is declared
247
- // `-> dyn Foo` and we don't actually relate it to the
248
- // `fcx.ret_coercion`, so just substitute a type variable.
249
- actual_return_ty =
250
- fcx. next_ty_var ( TypeVariableOrigin { kind : TypeVariableOriginKind :: DynReturnFn , span } ) ;
251
- debug ! ( "actual_return_ty replaced with {:?}" , actual_return_ty) ;
252
- }
253
-
254
- // HACK(oli-obk, compiler-errors): We should be comparing this against
255
- // `declared_ret_ty`, but then anything uninferred would be inferred to
256
- // the opaque type itself. That again would cause writeback to assume
257
- // we have a recursive call site and do the sadly stabilized fallback to `()`.
258
- fcx. demand_suptype ( span, ret_ty, actual_return_ty) ;
259
-
260
- // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
261
- if let Some ( panic_impl_did) = tcx. lang_items ( ) . panic_impl ( )
262
- && panic_impl_did == hir. local_def_id ( fn_id) . to_def_id ( )
263
- {
264
- check_panic_info_fn ( tcx, panic_impl_did. expect_local ( ) , fn_sig, decl, declared_ret_ty) ;
265
- }
266
-
267
- // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
268
- if let Some ( alloc_error_handler_did) = tcx. lang_items ( ) . oom ( )
269
- && alloc_error_handler_did == hir. local_def_id ( fn_id) . to_def_id ( )
270
- {
271
- check_alloc_error_fn ( tcx, alloc_error_handler_did. expect_local ( ) , fn_sig, decl, declared_ret_ty) ;
272
- }
273
-
274
- ( fcx, gen_ty)
275
- }
276
-
277
- fn check_panic_info_fn (
278
- tcx : TyCtxt < ' _ > ,
279
- fn_id : LocalDefId ,
280
- fn_sig : ty:: FnSig < ' _ > ,
281
- decl : & hir:: FnDecl < ' _ > ,
282
- declared_ret_ty : Ty < ' _ > ,
283
- ) {
284
- let Some ( panic_info_did) = tcx. lang_items ( ) . panic_info ( ) else {
285
- tcx. sess . err ( "language item required, but not found: `panic_info`" ) ;
286
- return ;
287
- } ;
288
-
289
- if * declared_ret_ty. kind ( ) != ty:: Never {
290
- tcx. sess . span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
291
- }
292
-
293
- let inputs = fn_sig. inputs ( ) ;
294
- if inputs. len ( ) != 1 {
295
- tcx. sess . span_err ( tcx. def_span ( fn_id) , "function should have one argument" ) ;
296
- return ;
297
- }
298
-
299
- let arg_is_panic_info = match * inputs[ 0 ] . kind ( ) {
300
- ty:: Ref ( region, ty, mutbl) => match * ty. kind ( ) {
301
- ty:: Adt ( ref adt, _) => {
302
- adt. did ( ) == panic_info_did && mutbl == hir:: Mutability :: Not && !region. is_static ( )
303
- }
304
- _ => false ,
305
- } ,
306
- _ => false ,
307
- } ;
308
-
309
- if !arg_is_panic_info {
310
- tcx. sess . span_err ( decl. inputs [ 0 ] . span , "argument should be `&PanicInfo`" ) ;
311
- }
312
-
313
- let DefKind :: Fn = tcx. def_kind ( fn_id) else {
314
- let span = tcx. def_span ( fn_id) ;
315
- tcx. sess . span_err ( span, "should be a function" ) ;
316
- return ;
317
- } ;
318
-
319
- let generic_counts = tcx. generics_of ( fn_id) . own_counts ( ) ;
320
- if generic_counts. types != 0 {
321
- let span = tcx. def_span ( fn_id) ;
322
- tcx. sess . span_err ( span, "should have no type parameters" ) ;
323
- }
324
- if generic_counts. consts != 0 {
325
- let span = tcx. def_span ( fn_id) ;
326
- tcx. sess . span_err ( span, "should have no const parameters" ) ;
327
- }
328
- }
329
-
330
- fn check_alloc_error_fn (
331
- tcx : TyCtxt < ' _ > ,
332
- fn_id : LocalDefId ,
333
- fn_sig : ty:: FnSig < ' _ > ,
334
- decl : & hir:: FnDecl < ' _ > ,
335
- declared_ret_ty : Ty < ' _ > ,
336
- ) {
337
- let Some ( alloc_layout_did) = tcx. lang_items ( ) . alloc_layout ( ) else {
338
- tcx. sess . err ( "language item required, but not found: `alloc_layout`" ) ;
339
- return ;
340
- } ;
341
-
342
- if * declared_ret_ty. kind ( ) != ty:: Never {
343
- tcx. sess . span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
344
- }
345
-
346
- let inputs = fn_sig. inputs ( ) ;
347
- if inputs. len ( ) != 1 {
348
- tcx. sess . span_err ( tcx. def_span ( fn_id) , "function should have one argument" ) ;
349
- return ;
350
- }
351
-
352
- let arg_is_alloc_layout = match inputs[ 0 ] . kind ( ) {
353
- ty:: Adt ( ref adt, _) => adt. did ( ) == alloc_layout_did,
354
- _ => false ,
355
- } ;
356
-
357
- if !arg_is_alloc_layout {
358
- tcx. sess . span_err ( decl. inputs [ 0 ] . span , "argument should be `Layout`" ) ;
359
- }
360
-
361
- let DefKind :: Fn = tcx. def_kind ( fn_id) else {
362
- let span = tcx. def_span ( fn_id) ;
363
- tcx. sess . span_err ( span, "`#[alloc_error_handler]` should be a function" ) ;
364
- return ;
365
- } ;
366
-
367
- let generic_counts = tcx. generics_of ( fn_id) . own_counts ( ) ;
368
- if generic_counts. types != 0 {
369
- let span = tcx. def_span ( fn_id) ;
370
- tcx. sess . span_err ( span, "`#[alloc_error_handler]` function should have no type parameters" ) ;
371
- }
372
- if generic_counts. consts != 0 {
373
- let span = tcx. def_span ( fn_id) ;
374
- tcx. sess
375
- . span_err ( span, "`#[alloc_error_handler]` function should have no const parameters" ) ;
376
- }
377
- }
378
-
379
69
fn check_struct ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
380
70
let def = tcx. adt_def ( def_id) ;
381
71
let span = tcx. def_span ( def_id) ;
0 commit comments