]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/mod.rs
Rollup merge of #94022 - jongiddy:cow-into-owned-docs, r=Dylan-DPC
[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 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 pub mod method;
85 mod op;
86 mod pat;
87 mod place_op;
88 mod regionck;
89 mod upvar;
90 mod wfcheck;
91 pub mod writeback;
92
93 use check::{
94     check_abi, check_fn, check_impl_item_well_formed, check_item_well_formed, check_mod_item_types,
95     check_trait_item_well_formed,
96 };
97 pub use check::{check_item_type, check_wf_new};
98 pub use diverges::Diverges;
99 pub use expectation::Expectation;
100 pub use fn_ctxt::*;
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::{pluralize, struct_span_err, Applicability, MultiSpan};
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::itemlikevisit::ItemLikeVisitor;
112 use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
113 use rustc_index::bit_set::BitSet;
114 use rustc_index::vec::Idx;
115 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
116 use rustc_middle::ty::query::Providers;
117 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
118 use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
119 use rustc_session::config;
120 use rustc_session::parse::feature_err;
121 use rustc_session::Session;
122 use rustc_span::source_map::DUMMY_SP;
123 use rustc_span::symbol::{kw, Ident};
124 use rustc_span::{self, BytePos, Span};
125 use rustc_target::abi::VariantIdx;
126 use rustc_target::spec::abi::Abi;
127 use rustc_trait_selection::traits;
128 use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
129 use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
130
131 use std::cell::{Ref, RefCell, RefMut};
132
133 use crate::require_c_abi_if_c_variadic;
134 use crate::util::common::indenter;
135
136 use self::coercion::DynamicCoerceMany;
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     *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_item_well_formed,
251         check_trait_item_well_formed,
252         check_impl_item_well_formed,
253         check_mod_item_types,
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, wf_tys) = 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(
374                     &fcx,
375                     id,
376                     header.unsafety,
377                     header.abi,
378                     decl,
379                     &hir::Generics::empty(),
380                     None,
381                     None,
382                 )
383             } else {
384                 tcx.fn_sig(def_id)
385             };
386
387             check_abi(tcx, id, span, fn_sig.abi());
388
389             // When normalizing the function signature, we assume all types are
390             // well-formed. So, we don't need to worry about the obligations
391             // from normalization. We could just discard these, but to align with
392             // compare_method and elsewhere, we just add implied bounds for
393             // these types.
394             let mut wf_tys = FxHashSet::default();
395             // Compute the fty from point of view of inside the fn.
396             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
397             let fn_sig = inh.normalize_associated_types_in(
398                 body.value.span,
399                 body_id.hir_id,
400                 param_env,
401                 fn_sig,
402             );
403             wf_tys.extend(fn_sig.inputs_and_output.iter());
404
405             let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0;
406             (fcx, wf_tys)
407         } else {
408             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
409             let expected_type = body_ty
410                 .and_then(|ty| match ty.kind {
411                     hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
412                     _ => None,
413                 })
414                 .unwrap_or_else(|| match tcx.hir().get(id) {
415                     Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
416                         Node::Expr(&hir::Expr {
417                             kind: hir::ExprKind::ConstBlock(ref anon_const),
418                             ..
419                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
420                             kind: TypeVariableOriginKind::TypeInference,
421                             span,
422                         }),
423                         Node::Ty(&hir::Ty {
424                             kind: hir::TyKind::Typeof(ref anon_const), ..
425                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
426                             kind: TypeVariableOriginKind::TypeInference,
427                             span,
428                         }),
429                         Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
430                         | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
431                             let operand_ty = asm
432                                 .operands
433                                 .iter()
434                                 .filter_map(|(op, _op_sp)| match op {
435                                     hir::InlineAsmOperand::Const { anon_const }
436                                         if anon_const.hir_id == id =>
437                                     {
438                                         // Inline assembly constants must be integers.
439                                         Some(fcx.next_int_var())
440                                     }
441                                     hir::InlineAsmOperand::SymFn { anon_const }
442                                         if anon_const.hir_id == id =>
443                                     {
444                                         Some(fcx.next_ty_var(TypeVariableOrigin {
445                                             kind: TypeVariableOriginKind::MiscVariable,
446                                             span,
447                                         }))
448                                     }
449                                     _ => None,
450                                 })
451                                 .next();
452                             operand_ty.unwrap_or_else(fallback)
453                         }
454                         _ => fallback(),
455                     },
456                     _ => fallback(),
457                 });
458
459             let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
460             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
461
462             // Gather locals in statics (because of block expressions).
463             GatherLocalsVisitor::new(&fcx).visit_body(body);
464
465             fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
466
467             fcx.write_ty(id, expected_type);
468
469             (fcx, FxHashSet::default())
470         };
471
472         let fallback_has_occurred = fcx.type_inference_fallback();
473
474         // Even though coercion casts provide type hints, we check casts after fallback for
475         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
476         fcx.check_casts();
477         fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
478
479         // Closure and generator analysis may run after fallback
480         // because they don't constrain other type variables.
481         fcx.closure_analyze(body);
482         assert!(fcx.deferred_call_resolutions.borrow().is_empty());
483         fcx.resolve_generator_interiors(def_id.to_def_id());
484
485         for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
486             let ty = fcx.normalize_ty(span, ty);
487             fcx.require_type_is_sized(ty, span, code);
488         }
489
490         fcx.select_all_obligations_or_error();
491
492         if fn_sig.is_some() {
493             fcx.regionck_fn(id, body, span, wf_tys);
494         } else {
495             fcx.regionck_expr(body);
496         }
497
498         fcx.resolve_type_vars_in_body(body)
499     });
500
501     // Consistency check our TypeckResults instance can hold all ItemLocalIds
502     // it will need to hold.
503     assert_eq!(typeck_results.hir_owner, id.owner);
504
505     typeck_results
506 }
507
508 /// When `check_fn` is invoked on a generator (i.e., a body that
509 /// includes yield), it returns back some information about the yield
510 /// points.
511 struct GeneratorTypes<'tcx> {
512     /// Type of generator argument / values returned by `yield`.
513     resume_ty: Ty<'tcx>,
514
515     /// Type of value that is yielded.
516     yield_ty: Ty<'tcx>,
517
518     /// Types that are captured (see `GeneratorInterior` for more).
519     interior: Ty<'tcx>,
520
521     /// Indicates if the generator is movable or static (immovable).
522     movability: hir::Movability,
523 }
524
525 /// Given a `DefId` for an opaque type in return position, find its parent item's return
526 /// expressions.
527 fn get_owner_return_paths<'tcx>(
528     tcx: TyCtxt<'tcx>,
529     def_id: LocalDefId,
530 ) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> {
531     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
532     let parent_id = tcx.hir().get_parent_item(hir_id);
533     tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| {
534         let body = tcx.hir().body(body_id);
535         let mut visitor = ReturnsVisitor::default();
536         visitor.visit_body(body);
537         (parent_id, visitor)
538     })
539 }
540
541 // Forbid defining intrinsics in Rust code,
542 // as they must always be defined by the compiler.
543 fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
544     if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
545         tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
546     }
547 }
548
549 fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) {
550     // Only restricted on wasm target for now
551     if !tcx.sess.target.is_like_wasm {
552         return;
553     }
554
555     // If `#[link_section]` is missing, then nothing to verify
556     let attrs = tcx.codegen_fn_attrs(id);
557     if attrs.link_section.is_none() {
558         return;
559     }
560
561     // For the wasm32 target statics with `#[link_section]` are placed into custom
562     // sections of the final output file, but this isn't link custom sections of
563     // other executable formats. Namely we can only embed a list of bytes,
564     // nothing with pointers to anything else or relocations. If any relocation
565     // show up, reject them here.
566     // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
567     // the consumer's responsibility to ensure all bytes that have been read
568     // have defined values.
569     if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
570         && alloc.inner().relocations().len() != 0
571     {
572         let msg = "statics with a custom `#[link_section]` must be a \
573                         simple list of bytes on the wasm target with no \
574                         extra levels of indirection such as references";
575         tcx.sess.span_err(span, msg);
576     }
577 }
578
579 fn report_forbidden_specialization(
580     tcx: TyCtxt<'_>,
581     impl_item: &hir::ImplItemRef,
582     parent_impl: DefId,
583 ) {
584     let mut err = struct_span_err!(
585         tcx.sess,
586         impl_item.span,
587         E0520,
588         "`{}` specializes an item from a parent `impl`, but \
589          that item is not marked `default`",
590         impl_item.ident
591     );
592     err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
593
594     match tcx.span_of_impl(parent_impl) {
595         Ok(span) => {
596             err.span_label(span, "parent `impl` is here");
597             err.note(&format!(
598                 "to specialize, `{}` in the parent `impl` must be marked `default`",
599                 impl_item.ident
600             ));
601         }
602         Err(cname) => {
603             err.note(&format!("parent implementation is in crate `{cname}`"));
604         }
605     }
606
607     err.emit();
608 }
609
610 fn missing_items_err(
611     tcx: TyCtxt<'_>,
612     impl_span: Span,
613     missing_items: &[&ty::AssocItem],
614     full_impl_span: Span,
615 ) {
616     let missing_items_msg = missing_items
617         .iter()
618         .map(|trait_item| trait_item.name.to_string())
619         .collect::<Vec<_>>()
620         .join("`, `");
621
622     let mut err = struct_span_err!(
623         tcx.sess,
624         impl_span,
625         E0046,
626         "not all trait items implemented, missing: `{missing_items_msg}`",
627     );
628     err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation"));
629
630     // `Span` before impl block closing brace.
631     let hi = full_impl_span.hi() - BytePos(1);
632     // Point at the place right before the closing brace of the relevant `impl` to suggest
633     // adding the associated item at the end of its body.
634     let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
635     // Obtain the level of indentation ending in `sugg_sp`.
636     let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0);
637     // Make the whitespace that will make the suggestion have the right indentation.
638     let padding: String = " ".repeat(indentation);
639
640     for trait_item in missing_items {
641         let snippet = suggestion_signature(trait_item, tcx);
642         let code = format!("{}{}\n{}", padding, snippet, padding);
643         let msg = format!("implement the missing item: `{snippet}`");
644         let appl = Applicability::HasPlaceholders;
645         if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
646             err.span_label(span, format!("`{}` from trait", trait_item.name));
647             err.tool_only_span_suggestion(sugg_sp, &msg, code, appl);
648         } else {
649             err.span_suggestion_hidden(sugg_sp, &msg, code, appl);
650         }
651     }
652     err.emit();
653 }
654
655 fn missing_items_must_implement_one_of_err(
656     tcx: TyCtxt<'_>,
657     impl_span: Span,
658     missing_items: &[Ident],
659     annotation_span: Option<Span>,
660 ) {
661     let missing_items_msg =
662         missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `");
663
664     let mut err = struct_span_err!(
665         tcx.sess,
666         impl_span,
667         E0046,
668         "not all trait items implemented, missing one of: `{missing_items_msg}`",
669     );
670     err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation"));
671
672     if let Some(annotation_span) = annotation_span {
673         err.span_note(annotation_span, "required because of this annotation");
674     }
675
676     err.emit();
677 }
678
679 /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
680 fn bounds_from_generic_predicates<'tcx>(
681     tcx: TyCtxt<'tcx>,
682     predicates: ty::GenericPredicates<'tcx>,
683 ) -> (String, String) {
684     let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
685     let mut projections = vec![];
686     for (predicate, _) in predicates.predicates {
687         debug!("predicate {:?}", predicate);
688         let bound_predicate = predicate.kind();
689         match bound_predicate.skip_binder() {
690             ty::PredicateKind::Trait(trait_predicate) => {
691                 let entry = types.entry(trait_predicate.self_ty()).or_default();
692                 let def_id = trait_predicate.def_id();
693                 if Some(def_id) != tcx.lang_items().sized_trait() {
694                     // Type params are `Sized` by default, do not add that restriction to the list
695                     // if it is a positive requirement.
696                     entry.push(trait_predicate.def_id());
697                 }
698             }
699             ty::PredicateKind::Projection(projection_pred) => {
700                 projections.push(bound_predicate.rebind(projection_pred));
701             }
702             _ => {}
703         }
704     }
705     let generics = if types.is_empty() {
706         "".to_string()
707     } else {
708         format!(
709             "<{}>",
710             types
711                 .keys()
712                 .filter_map(|t| match t.kind() {
713                     ty::Param(_) => Some(t.to_string()),
714                     // Avoid suggesting the following:
715                     // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
716                     _ => None,
717                 })
718                 .collect::<Vec<_>>()
719                 .join(", ")
720         )
721     };
722     let mut where_clauses = vec![];
723     for (ty, bounds) in types {
724         where_clauses
725             .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))));
726     }
727     for projection in &projections {
728         let p = projection.skip_binder();
729         // FIXME: this is not currently supported syntax, we should be looking at the `types` and
730         // insert the associated types where they correspond, but for now let's be "lazy" and
731         // propose this instead of the following valid resugaring:
732         // `T: Trait, Trait::Assoc = K` â†’ `T: Trait<Assoc = K>`
733         where_clauses.push(format!(
734             "{} = {}",
735             tcx.def_path_str(p.projection_ty.item_def_id),
736             p.term,
737         ));
738     }
739     let where_clauses = if where_clauses.is_empty() {
740         String::new()
741     } else {
742         format!(" where {}", where_clauses.join(", "))
743     };
744     (generics, where_clauses)
745 }
746
747 /// Return placeholder code for the given function.
748 fn fn_sig_suggestion<'tcx>(
749     tcx: TyCtxt<'tcx>,
750     sig: ty::FnSig<'tcx>,
751     ident: Ident,
752     predicates: ty::GenericPredicates<'tcx>,
753     assoc: &ty::AssocItem,
754 ) -> String {
755     let args = sig
756         .inputs()
757         .iter()
758         .enumerate()
759         .map(|(i, ty)| {
760             Some(match ty.kind() {
761                 ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
762                 ty::Ref(reg, ref_ty, mutability) if i == 0 => {
763                     let reg = format!("{reg} ");
764                     let reg = match &reg[..] {
765                         "'_ " | " " => "",
766                         reg => reg,
767                     };
768                     if assoc.fn_has_self_parameter {
769                         match ref_ty.kind() {
770                             ty::Param(param) if param.name == kw::SelfUpper => {
771                                 format!("&{}{}self", reg, mutability.prefix_str())
772                             }
773
774                             _ => format!("self: {ty}"),
775                         }
776                     } else {
777                         format!("_: {ty}")
778                     }
779                 }
780                 _ => {
781                     if assoc.fn_has_self_parameter && i == 0 {
782                         format!("self: {ty}")
783                     } else {
784                         format!("_: {ty}")
785                     }
786                 }
787             })
788         })
789         .chain(std::iter::once(if sig.c_variadic { Some("...".to_string()) } else { None }))
790         .flatten()
791         .collect::<Vec<String>>()
792         .join(", ");
793     let output = sig.output();
794     let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
795
796     let unsafety = sig.unsafety.prefix_str();
797     let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
798
799     // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
800     // not be present in the `fn` definition, not will we account for renamed
801     // lifetimes between the `impl` and the `trait`, but this should be good enough to
802     // fill in a significant portion of the missing code, and other subsequent
803     // suggestions can help the user fix the code.
804     format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
805 }
806
807 /// Return placeholder code for the given associated item.
808 /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
809 /// structured suggestion.
810 fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
811     match assoc.kind {
812         ty::AssocKind::Fn => {
813             // We skip the binder here because the binder would deanonymize all
814             // late-bound regions, and we don't want method signatures to show up
815             // `as for<'r> fn(&'r MyType)`.  Pretty-printing handles late-bound
816             // regions just fine, showing `fn(&MyType)`.
817             fn_sig_suggestion(
818                 tcx,
819                 tcx.fn_sig(assoc.def_id).skip_binder(),
820                 assoc.ident(tcx),
821                 tcx.predicates_of(assoc.def_id),
822                 assoc,
823             )
824         }
825         ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
826         ty::AssocKind::Const => {
827             let ty = tcx.type_of(assoc.def_id);
828             let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
829             format!("const {}: {} = {};", assoc.name, ty, val)
830         }
831     }
832 }
833
834 /// Emit an error when encountering two or more variants in a transparent enum.
835 fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, did: DefId) {
836     let variant_spans: Vec<_> = adt
837         .variants()
838         .iter()
839         .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
840         .collect();
841     let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
842     let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
843     err.span_label(sp, &msg);
844     if let [start @ .., end] = &*variant_spans {
845         for variant_span in start {
846             err.span_label(*variant_span, "");
847         }
848         err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
849     }
850     err.emit();
851 }
852
853 /// Emit an error when encountering two or more non-zero-sized fields in a transparent
854 /// enum.
855 fn bad_non_zero_sized_fields<'tcx>(
856     tcx: TyCtxt<'tcx>,
857     adt: ty::AdtDef<'tcx>,
858     field_count: usize,
859     field_spans: impl Iterator<Item = Span>,
860     sp: Span,
861 ) {
862     let msg = format!("needs at most one non-zero-sized field, but has {field_count}");
863     let mut err = struct_span_err!(
864         tcx.sess,
865         sp,
866         E0690,
867         "{}transparent {} {}",
868         if adt.is_enum() { "the variant of a " } else { "" },
869         adt.descr(),
870         msg,
871     );
872     err.span_label(sp, &msg);
873     for sp in field_spans {
874         err.span_label(sp, "this field is non-zero-sized");
875     }
876     err.emit();
877 }
878
879 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
880     struct_span_err!(
881         tcx.sess,
882         span,
883         E0533,
884         "expected unit struct, unit variant or constant, found {}{}",
885         res.descr(),
886         tcx.sess
887             .source_map()
888             .span_to_snippet(span)
889             .map_or_else(|_| String::new(), |s| format!(" `{s}`",)),
890     )
891     .emit();
892 }
893
894 /// Controls whether the arguments are tupled. This is used for the call
895 /// operator.
896 ///
897 /// Tupling means that all call-side arguments are packed into a tuple and
898 /// passed as a single parameter. For example, if tupling is enabled, this
899 /// function:
900 ///
901 ///     fn f(x: (isize, isize))
902 ///
903 /// Can be called as:
904 ///
905 ///     f(1, 2);
906 ///
907 /// Instead of:
908 ///
909 ///     f((1, 2));
910 #[derive(Clone, Eq, PartialEq)]
911 enum TupleArgumentsFlag {
912     DontTupleArguments,
913     TupleArguments,
914 }
915
916 /// A wrapper for `InferCtxt`'s `in_progress_typeck_results` field.
917 #[derive(Copy, Clone)]
918 struct MaybeInProgressTables<'a, 'tcx> {
919     maybe_typeck_results: Option<&'a RefCell<ty::TypeckResults<'tcx>>>,
920 }
921
922 impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> {
923     fn borrow(self) -> Ref<'a, ty::TypeckResults<'tcx>> {
924         match self.maybe_typeck_results {
925             Some(typeck_results) => typeck_results.borrow(),
926             None => bug!(
927                 "MaybeInProgressTables: inh/fcx.typeck_results.borrow() with no typeck results"
928             ),
929         }
930     }
931
932     fn borrow_mut(self) -> RefMut<'a, ty::TypeckResults<'tcx>> {
933         match self.maybe_typeck_results {
934             Some(typeck_results) => typeck_results.borrow_mut(),
935             None => bug!(
936                 "MaybeInProgressTables: inh/fcx.typeck_results.borrow_mut() with no typeck results"
937             ),
938         }
939     }
940 }
941
942 struct CheckItemTypesVisitor<'tcx> {
943     tcx: TyCtxt<'tcx>,
944 }
945
946 impl<'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
947     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
948         check_item_type(self.tcx, i);
949     }
950     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
951     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
952     fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
953 }
954
955 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
956     tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
957 }
958
959 fn fatally_break_rust(sess: &Session) {
960     let handler = sess.diagnostic();
961     handler.span_bug_no_panic(
962         MultiSpan::new(),
963         "It looks like you're trying to break rust; would you like some ICE?",
964     );
965     handler.note_without_error("the compiler expectedly panicked. this is a feature.");
966     handler.note_without_error(
967         "we would appreciate a joke overview: \
968          https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
969     );
970     handler.note_without_error(&format!(
971         "rustc {} running on {}",
972         option_env!("CFG_VERSION").unwrap_or("unknown_version"),
973         config::host_triple(),
974     ));
975 }
976
977 fn potentially_plural_count(count: usize, word: &str) -> String {
978     format!("{} {}{}", count, word, pluralize!(count))
979 }
980
981 fn has_expected_num_generic_args<'tcx>(
982     tcx: TyCtxt<'tcx>,
983     trait_did: Option<DefId>,
984     expected: usize,
985 ) -> bool {
986     trait_did.map_or(true, |trait_did| {
987         let generics = tcx.generics_of(trait_did);
988         generics.count() == expected + if generics.has_self { 1 } else { 0 }
989     })
990 }