11use crate :: check:: intrinsicck:: InlineAsmCtxt ;
22
3- use super :: coercion:: CoerceMany ;
43use super :: compare_method:: check_type_bounds;
54use super :: compare_method:: { compare_impl_method, compare_ty_impl} ;
65use super :: * ;
@@ -10,10 +9,8 @@ use rustc_hir as hir;
109use rustc_hir:: def:: { DefKind , Res } ;
1110use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1211use rustc_hir:: intravisit:: Visitor ;
13- use rustc_hir:: lang_items:: LangItem ;
1412use rustc_hir:: { ItemKind , Node , PathSegment } ;
1513use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
16- use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1714use rustc_infer:: infer:: { DefiningAnchor , RegionVariableOrigin , TyCtxtInferExt } ;
1815use rustc_infer:: traits:: Obligation ;
1916use rustc_lint:: builtin:: REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS ;
@@ -34,7 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
3431
3532use std:: ops:: ControlFlow ;
3633
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 ) {
3835 match tcx. sess . target . is_abi_supported ( abi) {
3936 Some ( true ) => ( ) ,
4037 Some ( false ) => {
@@ -69,313 +66,6 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
6966 }
7067}
7168
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-
37969fn check_struct ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
38070 let def = tcx. adt_def ( def_id) ;
38171 let span = tcx. def_span ( def_id) ;
0 commit comments