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