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