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