]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/mod.rs
Rollup merge of #100017 - solid-rs:patch/kmc-solid/adapt-to-78802, r=thomcc
[rust.git] / compiler / rustc_typeck / src / check / mod.rs
1 /*!
2
3 # typeck: check phase
4
5 Within the check phase of type check, we check each item one at a time
6 (bodies of function expressions are checked as part of the containing
7 function). Inference is used to supply types wherever they are unknown.
8
9 By far the most complex case is checking the body of a function. This
10 can be broken down into several distinct phases:
11
12 - gather: creates type variables to represent the type of each local
13   variable and pattern binding.
14
15 - main: the main pass does the lion's share of the work: it
16   determines the types of all expressions, resolves
17   methods, checks for most invalid conditions, and so forth.  In
18   some cases, where a type is unknown, it may create a type or region
19   variable and use that as the type of an expression.
20
21   In the process of checking, various constraints will be placed on
22   these type variables through the subtyping relationships requested
23   through the `demand` module.  The `infer` module is in charge
24   of resolving those constraints.
25
26 - regionck: after main is complete, the regionck pass goes over all
27   types looking for regions and making sure that they did not escape
28   into places where they are not in scope.  This may also influence the
29   final assignments of the various region variables if there is some
30   flexibility.
31
32 - writeback: writes the final types within a function body, replacing
33   type variables with their final inferred types.  These final types
34   are written into the `tcx.node_types` table, which should *never* contain
35   any reference to a type variable.
36
37 ## Intermediate types
38
39 While type checking a function, the intermediate types for the
40 expressions, blocks, and so forth contained within the function are
41 stored in `fcx.node_types` and `fcx.node_substs`.  These types
42 may contain unresolved type variables.  After type checking is
43 complete, the functions in the writeback module are used to take the
44 types from this table, resolve them, and then write them into their
45 permanent home in the type context `tcx`.
46
47 This means that during inferencing you should use `fcx.write_ty()`
48 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
49 nodes within the function.
50
51 The types of top-level items, which never contain unbound type
52 variables, are stored directly into the `tcx` typeck_results.
53
54 N.B., a type variable is not the same thing as a type parameter.  A
55 type variable is an instance of a type parameter. That is,
56 given a generic function `fn foo<T>(t: T)`, while checking the
57 function `foo`, the type `ty_param(0)` refers to the type `T`, which
58 is treated in abstract. However, when `foo()` is called, `T` will be
59 substituted for a fresh type variable `N`.  This variable will
60 eventually be resolved to some concrete type (which might itself be
61 a type parameter).
62
63 */
64
65 pub mod _match;
66 mod autoderef;
67 mod callee;
68 pub mod cast;
69 mod check;
70 mod closure;
71 pub mod coercion;
72 mod compare_method;
73 pub mod demand;
74 mod diverges;
75 pub mod dropck;
76 mod expectation;
77 mod expr;
78 mod fallback;
79 mod fn_ctxt;
80 mod gather_locals;
81 mod generator_interior;
82 mod inherited;
83 pub mod intrinsic;
84 mod intrinsicck;
85 pub mod method;
86 mod op;
87 mod pat;
88 mod place_op;
89 mod region;
90 pub mod regionck;
91 pub mod rvalue_scopes;
92 mod upvar;
93 pub mod wfcheck;
94 pub mod writeback;
95
96 use check::{check_abi, check_fn, check_mod_item_types};
97 pub use diverges::Diverges;
98 pub use expectation::Expectation;
99 pub use fn_ctxt::*;
100 use hir::def::CtorOf;
101 pub use inherited::{Inherited, InheritedBuilder};
102
103 use crate::astconv::AstConv;
104 use crate::check::gather_locals::GatherLocalsVisitor;
105 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
106 use rustc_errors::{
107     pluralize, struct_span_err, Applicability, DiagnosticBuilder, EmissionGuarantee, MultiSpan,
108 };
109 use rustc_hir as hir;
110 use rustc_hir::def::Res;
111 use rustc_hir::def_id::{DefId, LocalDefId};
112 use rustc_hir::intravisit::Visitor;
113 use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
114 use rustc_index::bit_set::BitSet;
115 use rustc_index::vec::Idx;
116 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
117 use rustc_middle::ty::query::Providers;
118 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
119 use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
120 use rustc_session::config;
121 use rustc_session::parse::feature_err;
122 use rustc_session::Session;
123 use rustc_span::source_map::DUMMY_SP;
124 use rustc_span::symbol::{kw, Ident};
125 use rustc_span::{self, BytePos, Span};
126 use rustc_target::abi::VariantIdx;
127 use rustc_target::spec::abi::Abi;
128 use rustc_trait_selection::traits;
129 use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
130 use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
131 use std::cell::RefCell;
132
133 use crate::require_c_abi_if_c_variadic;
134 use crate::util::common::indenter;
135
136 use self::coercion::DynamicCoerceMany;
137 use self::region::region_scope_tree;
138 pub use self::Expectation::*;
139
140 #[macro_export]
141 macro_rules! type_error_struct {
142     ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
143         let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
144
145         if $typ.references_error() {
146             err.downgrade_to_delayed_bug();
147         }
148
149         err
150     })
151 }
152
153 /// The type of a local binding, including the revealed type for anon types.
154 #[derive(Copy, Clone, Debug)]
155 pub struct LocalTy<'tcx> {
156     decl_ty: Ty<'tcx>,
157     revealed_ty: Ty<'tcx>,
158 }
159
160 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
161 pub enum Needs {
162     MutPlace,
163     None,
164 }
165
166 impl Needs {
167     fn maybe_mut_place(m: hir::Mutability) -> Self {
168         match m {
169             hir::Mutability::Mut => Needs::MutPlace,
170             hir::Mutability::Not => Needs::None,
171         }
172     }
173 }
174
175 #[derive(Copy, Clone)]
176 pub struct UnsafetyState {
177     pub def: hir::HirId,
178     pub unsafety: hir::Unsafety,
179     from_fn: bool,
180 }
181
182 impl UnsafetyState {
183     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
184         UnsafetyState { def, unsafety, from_fn: true }
185     }
186
187     pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
188         use hir::BlockCheckMode;
189         match self.unsafety {
190             // If this unsafe, then if the outer function was already marked as
191             // unsafe we shouldn't attribute the unsafe'ness to the block. This
192             // way the block can be warned about instead of ignoring this
193             // extraneous block (functions are never warned about).
194             hir::Unsafety::Unsafe if self.from_fn => self,
195
196             unsafety => {
197                 let (unsafety, def) = match blk.rules {
198                     BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
199                     BlockCheckMode::DefaultBlock => (unsafety, self.def),
200                 };
201                 UnsafetyState { def, unsafety, from_fn: false }
202             }
203         }
204     }
205 }
206
207 #[derive(Debug, Copy, Clone)]
208 pub enum PlaceOp {
209     Deref,
210     Index,
211 }
212
213 pub struct BreakableCtxt<'tcx> {
214     may_break: bool,
215
216     // this is `null` for loops where break with a value is illegal,
217     // such as `while`, `for`, and `while let`
218     coerce: Option<DynamicCoerceMany<'tcx>>,
219 }
220
221 pub struct EnclosingBreakables<'tcx> {
222     stack: Vec<BreakableCtxt<'tcx>>,
223     by_id: HirIdMap<usize>,
224 }
225
226 impl<'tcx> EnclosingBreakables<'tcx> {
227     fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
228         self.opt_find_breakable(target_id).unwrap_or_else(|| {
229             bug!("could not find enclosing breakable with id {}", target_id);
230         })
231     }
232
233     fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
234         match self.by_id.get(&target_id) {
235             Some(ix) => Some(&mut self.stack[*ix]),
236             None => None,
237         }
238     }
239 }
240
241 pub fn provide(providers: &mut Providers) {
242     method::provide(providers);
243     wfcheck::provide(providers);
244     *providers = Providers {
245         typeck_item_bodies,
246         typeck_const_arg,
247         typeck,
248         diagnostic_only_typeck,
249         has_typeck_results,
250         adt_destructor,
251         used_trait_imports,
252         check_mod_item_types,
253         region_scope_tree,
254         ..*providers
255     };
256 }
257
258 fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
259     tcx.calculate_dtor(def_id, dropck::check_drop_impl)
260 }
261
262 /// If this `DefId` is a "primary tables entry", returns
263 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
264 ///
265 /// If this function returns `Some`, then `typeck_results(def_id)` will
266 /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
267 /// may not succeed. In some cases where this function returns `None`
268 /// (notably closures), `typeck_results(def_id)` would wind up
269 /// redirecting to the owning function.
270 fn primary_body_of(
271     tcx: TyCtxt<'_>,
272     id: hir::HirId,
273 ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
274     match tcx.hir().get(id) {
275         Node::Item(item) => match item.kind {
276             hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
277                 Some((body, Some(ty), None))
278             }
279             hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
280             _ => None,
281         },
282         Node::TraitItem(item) => match item.kind {
283             hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
284             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
285                 Some((body, None, Some(sig)))
286             }
287             _ => None,
288         },
289         Node::ImplItem(item) => match item.kind {
290             hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
291             hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
292             _ => None,
293         },
294         Node::AnonConst(constant) => Some((constant.body, None, None)),
295         _ => None,
296     }
297 }
298
299 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
300     // Closures' typeck results come from their outermost function,
301     // as they are part of the same "inference environment".
302     let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
303     if typeck_root_def_id != def_id {
304         return tcx.has_typeck_results(typeck_root_def_id);
305     }
306
307     if let Some(def_id) = def_id.as_local() {
308         let id = tcx.hir().local_def_id_to_hir_id(def_id);
309         primary_body_of(tcx, id).is_some()
310     } else {
311         false
312     }
313 }
314
315 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
316     &*tcx.typeck(def_id).used_trait_imports
317 }
318
319 fn typeck_const_arg<'tcx>(
320     tcx: TyCtxt<'tcx>,
321     (did, param_did): (LocalDefId, DefId),
322 ) -> &ty::TypeckResults<'tcx> {
323     let fallback = move || tcx.type_of(param_did);
324     typeck_with_fallback(tcx, did, fallback)
325 }
326
327 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
328     if let Some(param_did) = tcx.opt_const_param_of(def_id) {
329         tcx.typeck_const_arg((def_id, param_did))
330     } else {
331         let fallback = move || tcx.type_of(def_id.to_def_id());
332         typeck_with_fallback(tcx, def_id, fallback)
333     }
334 }
335
336 /// Used only to get `TypeckResults` for type inference during error recovery.
337 /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
338 fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
339     let fallback = move || {
340         let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
341         tcx.ty_error_with_message(span, "diagnostic only typeck table used")
342     };
343     typeck_with_fallback(tcx, def_id, fallback)
344 }
345
346 #[instrument(skip(tcx, fallback))]
347 fn typeck_with_fallback<'tcx>(
348     tcx: TyCtxt<'tcx>,
349     def_id: LocalDefId,
350     fallback: impl Fn() -> Ty<'tcx> + 'tcx,
351 ) -> &'tcx ty::TypeckResults<'tcx> {
352     // Closures' typeck results come from their outermost function,
353     // as they are part of the same "inference environment".
354     let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
355     if typeck_root_def_id != def_id {
356         return tcx.typeck(typeck_root_def_id);
357     }
358
359     let id = tcx.hir().local_def_id_to_hir_id(def_id);
360     let span = tcx.hir().span(id);
361
362     // Figure out what primary body this item has.
363     let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
364         span_bug!(span, "can't type-check body of {:?}", def_id);
365     });
366     let body = tcx.hir().body(body_id);
367
368     let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
369         let param_env = tcx.param_env(def_id);
370         let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
371             let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
372                 let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
373                 <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
374             } else {
375                 tcx.fn_sig(def_id)
376             };
377
378             check_abi(tcx, id, span, fn_sig.abi());
379
380             // Compute the function signature from point of view of inside the fn.
381             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
382             let fn_sig = inh.normalize_associated_types_in(
383                 body.value.span,
384                 body_id.hir_id,
385                 param_env,
386                 fn_sig,
387             );
388             check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
389         } else {
390             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
391             let expected_type = body_ty
392                 .and_then(|ty| match ty.kind {
393                     hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
394                     _ => None,
395                 })
396                 .unwrap_or_else(|| match tcx.hir().get(id) {
397                     Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
398                         Node::Expr(&hir::Expr {
399                             kind: hir::ExprKind::ConstBlock(ref anon_const),
400                             ..
401                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
402                             kind: TypeVariableOriginKind::TypeInference,
403                             span,
404                         }),
405                         Node::Ty(&hir::Ty {
406                             kind: hir::TyKind::Typeof(ref anon_const), ..
407                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
408                             kind: TypeVariableOriginKind::TypeInference,
409                             span,
410                         }),
411                         Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
412                         | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
413                             let operand_ty = asm
414                                 .operands
415                                 .iter()
416                                 .filter_map(|(op, _op_sp)| match op {
417                                     hir::InlineAsmOperand::Const { anon_const }
418                                         if anon_const.hir_id == id =>
419                                     {
420                                         // Inline assembly constants must be integers.
421                                         Some(fcx.next_int_var())
422                                     }
423                                     hir::InlineAsmOperand::SymFn { anon_const }
424                                         if anon_const.hir_id == id =>
425                                     {
426                                         Some(fcx.next_ty_var(TypeVariableOrigin {
427                                             kind: TypeVariableOriginKind::MiscVariable,
428                                             span,
429                                         }))
430                                     }
431                                     _ => None,
432                                 })
433                                 .next();
434                             operand_ty.unwrap_or_else(fallback)
435                         }
436                         _ => fallback(),
437                     },
438                     _ => fallback(),
439                 });
440
441             let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
442             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
443
444             // Gather locals in statics (because of block expressions).
445             GatherLocalsVisitor::new(&fcx).visit_body(body);
446
447             fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
448
449             fcx.write_ty(id, expected_type);
450
451             fcx
452         };
453
454         let fallback_has_occurred = fcx.type_inference_fallback();
455
456         // Even though coercion casts provide type hints, we check casts after fallback for
457         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
458         fcx.check_casts();
459         fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
460
461         // Closure and generator analysis may run after fallback
462         // because they don't constrain other type variables.
463         fcx.closure_analyze(body);
464         assert!(fcx.deferred_call_resolutions.borrow().is_empty());
465         // Before the generator analysis, temporary scopes shall be marked to provide more
466         // precise information on types to be captured.
467         fcx.resolve_rvalue_scopes(def_id.to_def_id());
468         fcx.resolve_generator_interiors(def_id.to_def_id());
469
470         for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
471             let ty = fcx.normalize_ty(span, ty);
472             fcx.require_type_is_sized(ty, span, code);
473         }
474
475         fcx.select_all_obligations_or_error();
476
477         if !fcx.infcx.is_tainted_by_errors() {
478             fcx.check_transmutes();
479         }
480
481         fcx.check_asms();
482
483         fcx.infcx.skip_region_resolution();
484
485         fcx.resolve_type_vars_in_body(body)
486     });
487
488     // Consistency check our TypeckResults instance can hold all ItemLocalIds
489     // it will need to hold.
490     assert_eq!(typeck_results.hir_owner, id.owner);
491
492     typeck_results
493 }
494
495 /// When `check_fn` is invoked on a generator (i.e., a body that
496 /// includes yield), it returns back some information about the yield
497 /// points.
498 struct GeneratorTypes<'tcx> {
499     /// Type of generator argument / values returned by `yield`.
500     resume_ty: Ty<'tcx>,
501
502     /// Type of value that is yielded.
503     yield_ty: Ty<'tcx>,
504
505     /// Types that are captured (see `GeneratorInterior` for more).
506     interior: Ty<'tcx>,
507
508     /// Indicates if the generator is movable or static (immovable).
509     movability: hir::Movability,
510 }
511
512 /// Given a `DefId` for an opaque type in return position, find its parent item's return
513 /// expressions.
514 fn get_owner_return_paths<'tcx>(
515     tcx: TyCtxt<'tcx>,
516     def_id: LocalDefId,
517 ) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> {
518     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
519     let parent_id = tcx.hir().get_parent_item(hir_id);
520     tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| {
521         let body = tcx.hir().body(body_id);
522         let mut visitor = ReturnsVisitor::default();
523         visitor.visit_body(body);
524         (parent_id, visitor)
525     })
526 }
527
528 // Forbid defining intrinsics in Rust code,
529 // as they must always be defined by the compiler.
530 fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
531     if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
532         tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
533     }
534 }
535
536 fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
537     // Only restricted on wasm target for now
538     if !tcx.sess.target.is_like_wasm {
539         return;
540     }
541
542     // If `#[link_section]` is missing, then nothing to verify
543     let attrs = tcx.codegen_fn_attrs(id);
544     if attrs.link_section.is_none() {
545         return;
546     }
547
548     // For the wasm32 target statics with `#[link_section]` are placed into custom
549     // sections of the final output file, but this isn't link custom sections of
550     // other executable formats. Namely we can only embed a list of bytes,
551     // nothing with pointers to anything else or relocations. If any relocation
552     // show up, reject them here.
553     // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
554     // the consumer's responsibility to ensure all bytes that have been read
555     // have defined values.
556     if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
557         && alloc.inner().relocations().len() != 0
558     {
559         let msg = "statics with a custom `#[link_section]` must be a \
560                         simple list of bytes on the wasm target with no \
561                         extra levels of indirection such as references";
562         tcx.sess.span_err(tcx.def_span(id), msg);
563     }
564 }
565
566 fn report_forbidden_specialization(
567     tcx: TyCtxt<'_>,
568     impl_item: &hir::ImplItemRef,
569     parent_impl: DefId,
570 ) {
571     let mut err = struct_span_err!(
572         tcx.sess,
573         impl_item.span,
574         E0520,
575         "`{}` specializes an item from a parent `impl`, but \
576          that item is not marked `default`",
577         impl_item.ident
578     );
579     err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
580
581     match tcx.span_of_impl(parent_impl) {
582         Ok(span) => {
583             err.span_label(span, "parent `impl` is here");
584             err.note(&format!(
585                 "to specialize, `{}` in the parent `impl` must be marked `default`",
586                 impl_item.ident
587             ));
588         }
589         Err(cname) => {
590             err.note(&format!("parent implementation is in crate `{cname}`"));
591         }
592     }
593
594     err.emit();
595 }
596
597 fn missing_items_err(
598     tcx: TyCtxt<'_>,
599     impl_span: Span,
600     missing_items: &[&ty::AssocItem],
601     full_impl_span: Span,
602 ) {
603     let missing_items_msg = missing_items
604         .iter()
605         .map(|trait_item| trait_item.name.to_string())
606         .collect::<Vec<_>>()
607         .join("`, `");
608
609     let mut err = struct_span_err!(
610         tcx.sess,
611         impl_span,
612         E0046,
613         "not all trait items implemented, missing: `{missing_items_msg}`",
614     );
615     err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation"));
616
617     // `Span` before impl block closing brace.
618     let hi = full_impl_span.hi() - BytePos(1);
619     // Point at the place right before the closing brace of the relevant `impl` to suggest
620     // adding the associated item at the end of its body.
621     let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
622     // Obtain the level of indentation ending in `sugg_sp`.
623     let padding =
624         tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
625
626     for trait_item in missing_items {
627         let snippet = suggestion_signature(trait_item, tcx);
628         let code = format!("{}{}\n{}", padding, snippet, padding);
629         let msg = format!("implement the missing item: `{snippet}`");
630         let appl = Applicability::HasPlaceholders;
631         if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
632             err.span_label(span, format!("`{}` from trait", trait_item.name));
633             err.tool_only_span_suggestion(sugg_sp, &msg, code, appl);
634         } else {
635             err.span_suggestion_hidden(sugg_sp, &msg, code, appl);
636         }
637     }
638     err.emit();
639 }
640
641 fn missing_items_must_implement_one_of_err(
642     tcx: TyCtxt<'_>,
643     impl_span: Span,
644     missing_items: &[Ident],
645     annotation_span: Option<Span>,
646 ) {
647     let missing_items_msg =
648         missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `");
649
650     let mut err = struct_span_err!(
651         tcx.sess,
652         impl_span,
653         E0046,
654         "not all trait items implemented, missing one of: `{missing_items_msg}`",
655     );
656     err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation"));
657
658     if let Some(annotation_span) = annotation_span {
659         err.span_note(annotation_span, "required because of this annotation");
660     }
661
662     err.emit();
663 }
664
665 /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
666 fn bounds_from_generic_predicates<'tcx>(
667     tcx: TyCtxt<'tcx>,
668     predicates: ty::GenericPredicates<'tcx>,
669 ) -> (String, String) {
670     let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
671     let mut projections = vec![];
672     for (predicate, _) in predicates.predicates {
673         debug!("predicate {:?}", predicate);
674         let bound_predicate = predicate.kind();
675         match bound_predicate.skip_binder() {
676             ty::PredicateKind::Trait(trait_predicate) => {
677                 let entry = types.entry(trait_predicate.self_ty()).or_default();
678                 let def_id = trait_predicate.def_id();
679                 if Some(def_id) != tcx.lang_items().sized_trait() {
680                     // Type params are `Sized` by default, do not add that restriction to the list
681                     // if it is a positive requirement.
682                     entry.push(trait_predicate.def_id());
683                 }
684             }
685             ty::PredicateKind::Projection(projection_pred) => {
686                 projections.push(bound_predicate.rebind(projection_pred));
687             }
688             _ => {}
689         }
690     }
691     let generics = if types.is_empty() {
692         "".to_string()
693     } else {
694         format!(
695             "<{}>",
696             types
697                 .keys()
698                 .filter_map(|t| match t.kind() {
699                     ty::Param(_) => Some(t.to_string()),
700                     // Avoid suggesting the following:
701                     // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
702                     _ => None,
703                 })
704                 .collect::<Vec<_>>()
705                 .join(", ")
706         )
707     };
708     let mut where_clauses = vec![];
709     for (ty, bounds) in types {
710         where_clauses
711             .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))));
712     }
713     for projection in &projections {
714         let p = projection.skip_binder();
715         // FIXME: this is not currently supported syntax, we should be looking at the `types` and
716         // insert the associated types where they correspond, but for now let's be "lazy" and
717         // propose this instead of the following valid resugaring:
718         // `T: Trait, Trait::Assoc = K` â†’ `T: Trait<Assoc = K>`
719         where_clauses.push(format!(
720             "{} = {}",
721             tcx.def_path_str(p.projection_ty.item_def_id),
722             p.term,
723         ));
724     }
725     let where_clauses = if where_clauses.is_empty() {
726         String::new()
727     } else {
728         format!(" where {}", where_clauses.join(", "))
729     };
730     (generics, where_clauses)
731 }
732
733 /// Return placeholder code for the given function.
734 fn fn_sig_suggestion<'tcx>(
735     tcx: TyCtxt<'tcx>,
736     sig: ty::FnSig<'tcx>,
737     ident: Ident,
738     predicates: ty::GenericPredicates<'tcx>,
739     assoc: &ty::AssocItem,
740 ) -> String {
741     let args = sig
742         .inputs()
743         .iter()
744         .enumerate()
745         .map(|(i, ty)| {
746             Some(match ty.kind() {
747                 ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
748                 ty::Ref(reg, ref_ty, mutability) if i == 0 => {
749                     let reg = format!("{reg} ");
750                     let reg = match &reg[..] {
751                         "'_ " | " " => "",
752                         reg => reg,
753                     };
754                     if assoc.fn_has_self_parameter {
755                         match ref_ty.kind() {
756                             ty::Param(param) if param.name == kw::SelfUpper => {
757                                 format!("&{}{}self", reg, mutability.prefix_str())
758                             }
759
760                             _ => format!("self: {ty}"),
761                         }
762                     } else {
763                         format!("_: {ty}")
764                     }
765                 }
766                 _ => {
767                     if assoc.fn_has_self_parameter && i == 0 {
768                         format!("self: {ty}")
769                     } else {
770                         format!("_: {ty}")
771                     }
772                 }
773             })
774         })
775         .chain(std::iter::once(if sig.c_variadic { Some("...".to_string()) } else { None }))
776         .flatten()
777         .collect::<Vec<String>>()
778         .join(", ");
779     let output = sig.output();
780     let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
781
782     let unsafety = sig.unsafety.prefix_str();
783     let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
784
785     // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
786     // not be present in the `fn` definition, not will we account for renamed
787     // lifetimes between the `impl` and the `trait`, but this should be good enough to
788     // fill in a significant portion of the missing code, and other subsequent
789     // suggestions can help the user fix the code.
790     format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
791 }
792
793 /// Return placeholder code for the given associated item.
794 /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
795 /// structured suggestion.
796 fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
797     match assoc.kind {
798         ty::AssocKind::Fn => {
799             // We skip the binder here because the binder would deanonymize all
800             // late-bound regions, and we don't want method signatures to show up
801             // `as for<'r> fn(&'r MyType)`.  Pretty-printing handles late-bound
802             // regions just fine, showing `fn(&MyType)`.
803             fn_sig_suggestion(
804                 tcx,
805                 tcx.fn_sig(assoc.def_id).skip_binder(),
806                 assoc.ident(tcx),
807                 tcx.predicates_of(assoc.def_id),
808                 assoc,
809             )
810         }
811         ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
812         ty::AssocKind::Const => {
813             let ty = tcx.type_of(assoc.def_id);
814             let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
815             format!("const {}: {} = {};", assoc.name, ty, val)
816         }
817     }
818 }
819
820 /// Emit an error when encountering two or more variants in a transparent enum.
821 fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, did: DefId) {
822     let variant_spans: Vec<_> = adt
823         .variants()
824         .iter()
825         .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
826         .collect();
827     let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
828     let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
829     err.span_label(sp, &msg);
830     if let [start @ .., end] = &*variant_spans {
831         for variant_span in start {
832             err.span_label(*variant_span, "");
833         }
834         err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
835     }
836     err.emit();
837 }
838
839 /// Emit an error when encountering two or more non-zero-sized fields in a transparent
840 /// enum.
841 fn bad_non_zero_sized_fields<'tcx>(
842     tcx: TyCtxt<'tcx>,
843     adt: ty::AdtDef<'tcx>,
844     field_count: usize,
845     field_spans: impl Iterator<Item = Span>,
846     sp: Span,
847 ) {
848     let msg = format!("needs at most one non-zero-sized field, but has {field_count}");
849     let mut err = struct_span_err!(
850         tcx.sess,
851         sp,
852         E0690,
853         "{}transparent {} {}",
854         if adt.is_enum() { "the variant of a " } else { "" },
855         adt.descr(),
856         msg,
857     );
858     err.span_label(sp, &msg);
859     for sp in field_spans {
860         err.span_label(sp, "this field is non-zero-sized");
861     }
862     err.emit();
863 }
864
865 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
866     struct_span_err!(
867         tcx.sess,
868         span,
869         E0533,
870         "expected unit struct, unit variant or constant, found {} `{}`",
871         res.descr(),
872         rustc_hir_pretty::qpath_to_string(qpath),
873     )
874     .emit();
875 }
876
877 /// Controls whether the arguments are tupled. This is used for the call
878 /// operator.
879 ///
880 /// Tupling means that all call-side arguments are packed into a tuple and
881 /// passed as a single parameter. For example, if tupling is enabled, this
882 /// function:
883 /// ```
884 /// fn f(x: (isize, isize)) {}
885 /// ```
886 /// Can be called as:
887 /// ```ignore UNSOLVED (can this be done in user code?)
888 /// # fn f(x: (isize, isize)) {}
889 /// f(1, 2);
890 /// ```
891 /// Instead of:
892 /// ```
893 /// # fn f(x: (isize, isize)) {}
894 /// f((1, 2));
895 /// ```
896 #[derive(Clone, Eq, PartialEq)]
897 enum TupleArgumentsFlag {
898     DontTupleArguments,
899     TupleArguments,
900 }
901
902 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
903     tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
904 }
905
906 fn fatally_break_rust(sess: &Session) {
907     let handler = sess.diagnostic();
908     handler.span_bug_no_panic(
909         MultiSpan::new(),
910         "It looks like you're trying to break rust; would you like some ICE?",
911     );
912     handler.note_without_error("the compiler expectedly panicked. this is a feature.");
913     handler.note_without_error(
914         "we would appreciate a joke overview: \
915          https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
916     );
917     handler.note_without_error(&format!(
918         "rustc {} running on {}",
919         option_env!("CFG_VERSION").unwrap_or("unknown_version"),
920         config::host_triple(),
921     ));
922 }
923
924 fn potentially_plural_count(count: usize, word: &str) -> String {
925     format!("{} {}{}", count, word, pluralize!(count))
926 }
927
928 fn has_expected_num_generic_args<'tcx>(
929     tcx: TyCtxt<'tcx>,
930     trait_did: Option<DefId>,
931     expected: usize,
932 ) -> bool {
933     trait_did.map_or(true, |trait_did| {
934         let generics = tcx.generics_of(trait_did);
935         generics.count() == expected + if generics.has_self { 1 } else { 0 }
936     })
937 }
938
939 /// Suggests calling the constructor of a tuple struct or enum variant
940 ///
941 /// * `snippet` - The snippet of code that references the constructor
942 /// * `span` - The span of the snippet
943 /// * `params` - The number of parameters the constructor accepts
944 /// * `err` - A mutable diagnostic builder to add the suggestion to
945 fn suggest_call_constructor<G: EmissionGuarantee>(
946     span: Span,
947     kind: CtorOf,
948     params: usize,
949     err: &mut DiagnosticBuilder<'_, G>,
950 ) {
951     // Note: tuple-structs don't have named fields, so just use placeholders
952     let args = vec!["_"; params].join(", ");
953     let applicable = if params > 0 {
954         Applicability::HasPlaceholders
955     } else {
956         // When n = 0, it's an empty-tuple struct/enum variant
957         // so we trivially know how to construct it
958         Applicability::MachineApplicable
959     };
960     let kind = match kind {
961         CtorOf::Struct => "a struct",
962         CtorOf::Variant => "an enum variant",
963     };
964     err.span_label(span, &format!("this is the constructor of {kind}"));
965     err.multipart_suggestion(
966         "call the constructor",
967         vec![(span.shrink_to_lo(), "(".to_string()), (span.shrink_to_hi(), format!(")({args})"))],
968         applicable,
969     );
970 }