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