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