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