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