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.
9 By far the most complex case is checking the body of a function. This
10 can be broken down into several distinct phases:
12 - gather: creates type variables to represent the type of each local
13 variable and pattern binding.
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.
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.
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
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.
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`.
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.
51 The types of top-level items, which never contain unbound type
52 variables, are stored directly into the `tcx` typeck_results.
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
80 mod generator_interior;
93 check_abi, check_fn, check_impl_item_well_formed, check_item_well_formed, check_mod_item_types,
94 check_trait_item_well_formed,
96 pub use check::{check_item_type, check_wf_new};
97 pub use diverges::Diverges;
98 pub use expectation::Expectation;
100 pub use inherited::{Inherited, InheritedBuilder};
102 use crate::astconv::AstConv;
103 use crate::check::gather_locals::GatherLocalsVisitor;
104 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
105 use rustc_errors::{pluralize, struct_span_err, Applicability};
106 use rustc_hir as hir;
107 use rustc_hir::def::Res;
108 use rustc_hir::def_id::{DefId, LocalDefId};
109 use rustc_hir::intravisit::Visitor;
110 use rustc_hir::itemlikevisit::ItemLikeVisitor;
111 use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
112 use rustc_index::bit_set::BitSet;
113 use rustc_index::vec::Idx;
114 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
115 use rustc_middle::ty::query::Providers;
116 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
117 use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
118 use rustc_session::config;
119 use rustc_session::parse::feature_err;
120 use rustc_session::Session;
121 use rustc_span::symbol::{kw, Ident};
122 use rustc_span::{self, BytePos, MultiSpan, Span};
123 use rustc_span::{source_map::DUMMY_SP, sym};
124 use rustc_target::abi::VariantIdx;
125 use rustc_target::spec::abi::Abi;
126 use rustc_trait_selection::traits;
127 use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
128 use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
130 use std::cell::{Ref, RefCell, RefMut};
132 use crate::require_c_abi_if_c_variadic;
133 use crate::util::common::indenter;
135 use self::coercion::DynamicCoerceMany;
136 pub use self::Expectation::*;
139 macro_rules! type_error_struct {
140 ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
141 if $typ.references_error() {
142 $session.diagnostic().struct_dummy()
144 rustc_errors::struct_span_err!($session, $span, $code, $($message)*)
149 /// The type of a local binding, including the revealed type for anon types.
150 #[derive(Copy, Clone, Debug)]
151 pub struct LocalTy<'tcx> {
153 revealed_ty: Ty<'tcx>,
156 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
163 fn maybe_mut_place(m: hir::Mutability) -> Self {
165 hir::Mutability::Mut => Needs::MutPlace,
166 hir::Mutability::Not => Needs::None,
171 #[derive(Copy, Clone)]
172 pub struct UnsafetyState {
174 pub unsafety: hir::Unsafety,
179 pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
180 UnsafetyState { def, unsafety, from_fn: true }
183 pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
184 use hir::BlockCheckMode;
185 match self.unsafety {
186 // If this unsafe, then if the outer function was already marked as
187 // unsafe we shouldn't attribute the unsafe'ness to the block. This
188 // way the block can be warned about instead of ignoring this
189 // extraneous block (functions are never warned about).
190 hir::Unsafety::Unsafe if self.from_fn => self,
193 let (unsafety, def) = match blk.rules {
194 BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
195 BlockCheckMode::DefaultBlock => (unsafety, self.def),
197 UnsafetyState { def, unsafety, from_fn: false }
203 #[derive(Debug, Copy, Clone)]
209 pub struct BreakableCtxt<'tcx> {
212 // this is `null` for loops where break with a value is illegal,
213 // such as `while`, `for`, and `while let`
214 coerce: Option<DynamicCoerceMany<'tcx>>,
217 pub struct EnclosingBreakables<'tcx> {
218 stack: Vec<BreakableCtxt<'tcx>>,
219 by_id: HirIdMap<usize>,
222 impl<'tcx> EnclosingBreakables<'tcx> {
223 fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
224 self.opt_find_breakable(target_id).unwrap_or_else(|| {
225 bug!("could not find enclosing breakable with id {}", target_id);
229 fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
230 match self.by_id.get(&target_id) {
231 Some(ix) => Some(&mut self.stack[*ix]),
237 pub fn provide(providers: &mut Providers) {
238 method::provide(providers);
239 *providers = Providers {
243 diagnostic_only_typeck,
247 check_item_well_formed,
248 check_trait_item_well_formed,
249 check_impl_item_well_formed,
250 check_mod_item_types,
255 fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
256 tcx.calculate_dtor(def_id, dropck::check_drop_impl)
259 /// If this `DefId` is a "primary tables entry", returns
260 /// `Some((body_id, header, decl))` with information about
261 /// its body-id, fn-header and fn-decl (if any). Otherwise,
264 /// If this function returns `Some`, then `typeck_results(def_id)` will
265 /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
266 /// may not succeed. In some cases where this function returns `None`
267 /// (notably closures), `typeck_results(def_id)` would wind up
268 /// redirecting to the owning function.
272 ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnHeader>, Option<&hir::FnDecl<'_>>)> {
273 match tcx.hir().get(id) {
274 Node::Item(item) => match item.kind {
275 hir::ItemKind::Const(ref ty, body) | hir::ItemKind::Static(ref ty, _, body) => {
276 Some((body, Some(ty), None, None))
278 hir::ItemKind::Fn(ref sig, .., body) => {
279 Some((body, None, Some(&sig.header), Some(&sig.decl)))
283 Node::TraitItem(item) => match item.kind {
284 hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)),
285 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
286 Some((body, None, Some(&sig.header), Some(&sig.decl)))
290 Node::ImplItem(item) => match item.kind {
291 hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None, None)),
292 hir::ImplItemKind::Fn(ref sig, body) => {
293 Some((body, None, Some(&sig.header), Some(&sig.decl)))
297 Node::AnonConst(constant) => Some((constant.body, None, None, None)),
302 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
303 // Closures' typeck results come from their outermost function,
304 // as they are part of the same "inference environment".
305 let outer_def_id = tcx.closure_base_def_id(def_id);
306 if outer_def_id != def_id {
307 return tcx.has_typeck_results(outer_def_id);
310 if let Some(def_id) = def_id.as_local() {
311 let id = tcx.hir().local_def_id_to_hir_id(def_id);
312 primary_body_of(tcx, id).is_some()
318 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
319 &*tcx.typeck(def_id).used_trait_imports
322 fn typeck_const_arg<'tcx>(
324 (did, param_did): (LocalDefId, DefId),
325 ) -> &ty::TypeckResults<'tcx> {
326 let fallback = move || tcx.type_of(param_did);
327 typeck_with_fallback(tcx, did, fallback)
330 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
331 if let Some(param_did) = tcx.opt_const_param_of(def_id) {
332 tcx.typeck_const_arg((def_id, param_did))
334 let fallback = move || tcx.type_of(def_id.to_def_id());
335 typeck_with_fallback(tcx, def_id, fallback)
339 /// Used only to get `TypeckResults` for type inference during error recovery.
340 /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
341 fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
342 let fallback = move || {
343 let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
344 tcx.ty_error_with_message(span, "diagnostic only typeck table used")
346 typeck_with_fallback(tcx, def_id, fallback)
349 fn typeck_with_fallback<'tcx>(
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 outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
357 if outer_def_id != def_id {
358 return tcx.typeck(outer_def_id);
361 let id = tcx.hir().local_def_id_to_hir_id(def_id);
362 let span = tcx.hir().span(id);
364 // Figure out what primary body this item has.
365 let (body_id, body_ty, fn_header, fn_decl) = primary_body_of(tcx, id).unwrap_or_else(|| {
366 span_bug!(span, "can't type-check body of {:?}", def_id);
368 let body = tcx.hir().body(body_id);
370 let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
371 let param_env = tcx.param_env(def_id);
372 let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) {
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(
381 &hir::Generics::empty(),
389 check_abi(tcx, id, span, fn_sig.abi());
391 // Compute the fty from point of view of inside the fn.
392 let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
393 let fn_sig = inh.normalize_associated_types_in(
400 let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
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)),
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),
414 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
415 kind: TypeVariableOriginKind::TypeInference,
419 kind: hir::TyKind::Typeof(ref anon_const), ..
420 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
421 kind: TypeVariableOriginKind::TypeInference,
424 Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
425 | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. })
426 if asm.operands.iter().any(|(op, _op_sp)| match op {
427 hir::InlineAsmOperand::Const { anon_const } => {
428 anon_const.hir_id == id
433 // Inline assembly constants must be integers.
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);
444 let revealed_ty = fcx.instantiate_opaque_types_from_value(
448 Some(sym::impl_trait_in_bindings),
451 // Gather locals in statics (because of block expressions).
452 GatherLocalsVisitor::new(&fcx, id).visit_body(body);
454 fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
456 fcx.write_ty(id, revealed_ty);
461 // All type checking constraints were added, try to fallback unsolved variables.
462 fcx.select_obligations_where_possible(false, |_| {});
463 let mut fallback_has_occurred = false;
465 // We do fallback in two passes, to try to generate
466 // better error messages.
467 // The first time, we do *not* replace opaque types.
468 for ty in &fcx.unsolved_variables() {
469 fallback_has_occurred |= fcx.fallback_if_possible(ty, FallbackMode::NoOpaque);
471 // We now see if we can make progress. This might
472 // cause us to unify inference variables for opaque types,
473 // since we may have unified some other type variables
474 // during the first phase of fallback.
475 // This means that we only replace inference variables with their underlying
476 // opaque types as a last resort.
478 // In code like this:
481 // type MyType = impl Copy;
482 // fn produce() -> MyType { true }
483 // fn bad_produce() -> MyType { panic!() }
486 // we want to unify the opaque inference variable in `bad_produce`
487 // with the diverging fallback for `panic!` (e.g. `()` or `!`).
488 // This will produce a nice error message about conflicting concrete
489 // types for `MyType`.
491 // If we had tried to fallback the opaque inference variable to `MyType`,
492 // we will generate a confusing type-check error that does not explicitly
493 // refer to opaque types.
494 fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
496 // We now run fallback again, but this time we allow it to replace
497 // unconstrained opaque type variables, in addition to performing
498 // other kinds of fallback.
499 for ty in &fcx.unsolved_variables() {
500 fallback_has_occurred |= fcx.fallback_if_possible(ty, FallbackMode::All);
503 // See if we can make any more progress.
504 fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
506 // Even though coercion casts provide type hints, we check casts after fallback for
507 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
510 // Closure and generator analysis may run after fallback
511 // because they don't constrain other type variables.
512 fcx.closure_analyze(body);
513 assert!(fcx.deferred_call_resolutions.borrow().is_empty());
514 fcx.resolve_generator_interiors(def_id.to_def_id());
516 for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
517 let ty = fcx.normalize_ty(span, ty);
518 fcx.require_type_is_sized(ty, span, code);
521 fcx.select_all_obligations_or_error();
523 if fn_decl.is_some() {
524 fcx.regionck_fn(id, body);
526 fcx.regionck_expr(body);
529 fcx.resolve_type_vars_in_body(body)
532 // Consistency check our TypeckResults instance can hold all ItemLocalIds
533 // it will need to hold.
534 assert_eq!(typeck_results.hir_owner, id.owner);
539 /// When `check_fn` is invoked on a generator (i.e., a body that
540 /// includes yield), it returns back some information about the yield
542 struct GeneratorTypes<'tcx> {
543 /// Type of generator argument / values returned by `yield`.
546 /// Type of value that is yielded.
549 /// Types that are captured (see `GeneratorInterior` for more).
552 /// Indicates if the generator is movable or static (immovable).
553 movability: hir::Movability,
556 /// Given a `DefId` for an opaque type in return position, find its parent item's return
558 fn get_owner_return_paths(
561 ) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
562 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
563 let id = tcx.hir().get_parent_item(hir_id);
567 .and_then(|(hir_id, node)| node.body_id().map(|b| (hir_id, b)))
568 .map(|(hir_id, body_id)| {
569 let body = tcx.hir().body(body_id);
570 let mut visitor = ReturnsVisitor::default();
571 visitor.visit_body(body);
576 /// Emit an error for recursive opaque types in a `let` binding.
577 fn binding_opaque_type_cycle_error(
581 partially_expanded_type: Ty<'tcx>,
583 let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
584 err.span_label(span, "cannot resolve opaque type");
585 // Find the owner that declared this `impl Trait` type.
586 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
587 let mut prev_hir_id = hir_id;
588 let mut hir_id = tcx.hir().get_parent_node(hir_id);
589 while let Some(node) = tcx.hir().find(hir_id) {
591 hir::Node::Local(hir::Local {
595 source: hir::LocalSource::Normal,
598 err.span_label(pat.span, "this binding might not have a concrete type");
599 err.span_suggestion_verbose(
600 ty.span.shrink_to_hi(),
601 "set the binding to a value for a concrete type to be resolved",
602 " = /* value */".to_string(),
603 Applicability::HasPlaceholders,
606 hir::Node::Local(hir::Local {
608 source: hir::LocalSource::Normal,
611 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
613 tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
614 if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) {
618 "this is of type `{}`, which doesn't constrain \
619 `{}` enough to arrive to a concrete type",
620 ty, partially_expanded_type
627 if prev_hir_id == hir_id {
630 prev_hir_id = hir_id;
631 hir_id = tcx.hir().get_parent_node(hir_id);
636 // Forbid defining intrinsics in Rust code,
637 // as they must always be defined by the compiler.
638 fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
639 if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
640 tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
644 fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) {
645 // Only restricted on wasm32 target for now
646 if !tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
650 // If `#[link_section]` is missing, then nothing to verify
651 let attrs = tcx.codegen_fn_attrs(id);
652 if attrs.link_section.is_none() {
656 // For the wasm32 target statics with `#[link_section]` are placed into custom
657 // sections of the final output file, but this isn't link custom sections of
658 // other executable formats. Namely we can only embed a list of bytes,
659 // nothing with pointers to anything else or relocations. If any relocation
660 // show up, reject them here.
661 // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
662 // the consumer's responsibility to ensure all bytes that have been read
663 // have defined values.
664 match tcx.eval_static_initializer(id.to_def_id()) {
666 if alloc.relocations().len() != 0 {
667 let msg = "statics with a custom `#[link_section]` must be a \
668 simple list of bytes on the wasm target with no \
669 extra levels of indirection such as references";
670 tcx.sess.span_err(span, msg);
677 fn report_forbidden_specialization(
679 impl_item: &hir::ImplItem<'_>,
682 let mut err = struct_span_err!(
686 "`{}` specializes an item from a parent `impl`, but \
687 that item is not marked `default`",
690 err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
692 match tcx.span_of_impl(parent_impl) {
694 err.span_label(span, "parent `impl` is here");
696 "to specialize, `{}` in the parent `impl` must be marked `default`",
701 err.note(&format!("parent implementation is in crate `{}`", cname));
708 fn missing_items_err(
711 missing_items: &[ty::AssocItem],
712 full_impl_span: Span,
714 let missing_items_msg = missing_items
716 .map(|trait_item| trait_item.ident.to_string())
720 let mut err = struct_span_err!(
724 "not all trait items implemented, missing: `{}`",
727 err.span_label(impl_span, format!("missing `{}` in implementation", missing_items_msg));
729 // `Span` before impl block closing brace.
730 let hi = full_impl_span.hi() - BytePos(1);
731 // Point at the place right before the closing brace of the relevant `impl` to suggest
732 // adding the associated item at the end of its body.
733 let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
734 // Obtain the level of indentation ending in `sugg_sp`.
735 let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0);
736 // Make the whitespace that will make the suggestion have the right indentation.
737 let padding: String = " ".repeat(indentation);
739 for trait_item in missing_items {
740 let snippet = suggestion_signature(&trait_item, tcx);
741 let code = format!("{}{}\n{}", padding, snippet, padding);
742 let msg = format!("implement the missing item: `{}`", snippet);
743 let appl = Applicability::HasPlaceholders;
744 if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
745 err.span_label(span, format!("`{}` from trait", trait_item.ident));
746 err.tool_only_span_suggestion(sugg_sp, &msg, code, appl);
748 err.span_suggestion_hidden(sugg_sp, &msg, code, appl);
754 /// Resugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
755 fn bounds_from_generic_predicates<'tcx>(
757 predicates: ty::GenericPredicates<'tcx>,
758 ) -> (String, String) {
759 let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
760 let mut projections = vec![];
761 for (predicate, _) in predicates.predicates {
762 debug!("predicate {:?}", predicate);
763 let bound_predicate = predicate.kind();
764 match bound_predicate.skip_binder() {
765 ty::PredicateKind::Trait(trait_predicate, _) => {
766 let entry = types.entry(trait_predicate.self_ty()).or_default();
767 let def_id = trait_predicate.def_id();
768 if Some(def_id) != tcx.lang_items().sized_trait() {
769 // Type params are `Sized` by default, do not add that restriction to the list
770 // if it is a positive requirement.
771 entry.push(trait_predicate.def_id());
774 ty::PredicateKind::Projection(projection_pred) => {
775 projections.push(bound_predicate.rebind(projection_pred));
780 let generics = if types.is_empty() {
787 .filter_map(|t| match t.kind() {
788 ty::Param(_) => Some(t.to_string()),
789 // Avoid suggesting the following:
790 // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
797 let mut where_clauses = vec![];
798 for (ty, bounds) in types {
799 for bound in &bounds {
800 where_clauses.push(format!("{}: {}", ty, tcx.def_path_str(*bound)));
803 for projection in &projections {
804 let p = projection.skip_binder();
805 // FIXME: this is not currently supported syntax, we should be looking at the `types` and
806 // insert the associated types where they correspond, but for now let's be "lazy" and
807 // propose this instead of the following valid resugaring:
808 // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
809 where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), p.ty));
811 let where_clauses = if where_clauses.is_empty() {
814 format!(" where {}", where_clauses.join(", "))
816 (generics, where_clauses)
819 /// Return placeholder code for the given function.
820 fn fn_sig_suggestion<'tcx>(
822 sig: ty::FnSig<'tcx>,
824 predicates: ty::GenericPredicates<'tcx>,
825 assoc: &ty::AssocItem,
832 Some(match ty.kind() {
833 ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
834 ty::Ref(reg, ref_ty, mutability) if i == 0 => {
835 let reg = match &format!("{}", reg)[..] {
836 "'_" | "" => String::new(),
837 reg => format!("{} ", reg),
839 if assoc.fn_has_self_parameter {
840 match ref_ty.kind() {
841 ty::Param(param) if param.name == kw::SelfUpper => {
842 format!("&{}{}self", reg, mutability.prefix_str())
845 _ => format!("self: {}", ty),
852 if assoc.fn_has_self_parameter && i == 0 {
853 format!("self: {}", ty)
860 .chain(std::iter::once(if sig.c_variadic { Some("...".to_string()) } else { None }))
861 .filter_map(|arg| arg)
862 .collect::<Vec<String>>()
864 let output = sig.output();
865 let output = if !output.is_unit() { format!(" -> {}", output) } else { String::new() };
867 let unsafety = sig.unsafety.prefix_str();
868 let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
870 // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
871 // not be present in the `fn` definition, not will we account for renamed
872 // lifetimes between the `impl` and the `trait`, but this should be good enough to
873 // fill in a significant portion of the missing code, and other subsequent
874 // suggestions can help the user fix the code.
876 "{}fn {}{}({}){}{} {{ todo!() }}",
877 unsafety, ident, generics, args, output, where_clauses
881 /// Return placeholder code for the given associated item.
882 /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
883 /// structured suggestion.
884 fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
886 ty::AssocKind::Fn => {
887 // We skip the binder here because the binder would deanonymize all
888 // late-bound regions, and we don't want method signatures to show up
889 // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
890 // regions just fine, showing `fn(&MyType)`.
893 tcx.fn_sig(assoc.def_id).skip_binder(),
895 tcx.predicates_of(assoc.def_id),
899 ty::AssocKind::Type => format!("type {} = Type;", assoc.ident),
900 ty::AssocKind::Const => {
901 let ty = tcx.type_of(assoc.def_id);
902 let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
903 format!("const {}: {} = {};", assoc.ident, ty, val)
908 /// Emit an error when encountering two or more variants in a transparent enum.
909 fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
910 let variant_spans: Vec<_> = adt
913 .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
915 let msg = format!("needs exactly one variant, but has {}", adt.variants.len(),);
916 let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
917 err.span_label(sp, &msg);
918 if let [start @ .., end] = &*variant_spans {
919 for variant_span in start {
920 err.span_label(*variant_span, "");
922 err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
927 /// Emit an error when encountering two or more non-zero-sized fields in a transparent
929 fn bad_non_zero_sized_fields<'tcx>(
931 adt: &'tcx ty::AdtDef,
933 field_spans: impl Iterator<Item = Span>,
936 let msg = format!("needs at most one non-zero-sized field, but has {}", field_count);
937 let mut err = struct_span_err!(
941 "{}transparent {} {}",
942 if adt.is_enum() { "the variant of a " } else { "" },
946 err.span_label(sp, &msg);
947 for sp in field_spans {
948 err.span_label(sp, "this field is non-zero-sized");
953 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
958 "expected unit struct, unit variant or constant, found {}{}",
962 .span_to_snippet(span)
963 .map_or_else(|_| String::new(), |s| format!(" `{}`", s)),
968 /// Controls whether the arguments are tupled. This is used for the call
971 /// Tupling means that all call-side arguments are packed into a tuple and
972 /// passed as a single parameter. For example, if tupling is enabled, this
975 /// fn f(x: (isize, isize))
977 /// Can be called as:
984 #[derive(Clone, Eq, PartialEq)]
985 enum TupleArgumentsFlag {
990 /// Controls how we perform fallback for unconstrained
993 /// Do not fallback type variables to opaque types.
995 /// Perform all possible kinds of fallback, including
996 /// turning type variables to opaque types.
1000 /// A wrapper for `InferCtxt`'s `in_progress_typeck_results` field.
1001 #[derive(Copy, Clone)]
1002 struct MaybeInProgressTables<'a, 'tcx> {
1003 maybe_typeck_results: Option<&'a RefCell<ty::TypeckResults<'tcx>>>,
1006 impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> {
1007 fn borrow(self) -> Ref<'a, ty::TypeckResults<'tcx>> {
1008 match self.maybe_typeck_results {
1009 Some(typeck_results) => typeck_results.borrow(),
1011 "MaybeInProgressTables: inh/fcx.typeck_results.borrow() with no typeck results"
1016 fn borrow_mut(self) -> RefMut<'a, ty::TypeckResults<'tcx>> {
1017 match self.maybe_typeck_results {
1018 Some(typeck_results) => typeck_results.borrow_mut(),
1020 "MaybeInProgressTables: inh/fcx.typeck_results.borrow_mut() with no typeck results"
1026 struct CheckItemTypesVisitor<'tcx> {
1030 impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
1031 fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
1032 check_item_type(self.tcx, i);
1034 fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
1035 fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
1036 fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
1039 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
1040 tcx.par_body_owners(|body_owner_def_id| {
1041 tcx.ensure().typeck(body_owner_def_id);
1045 fn fatally_break_rust(sess: &Session) {
1046 let handler = sess.diagnostic();
1047 handler.span_bug_no_panic(
1049 "It looks like you're trying to break rust; would you like some ICE?",
1051 handler.note_without_error("the compiler expectedly panicked. this is a feature.");
1052 handler.note_without_error(
1053 "we would appreciate a joke overview: \
1054 https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
1056 handler.note_without_error(&format!(
1057 "rustc {} running on {}",
1058 option_env!("CFG_VERSION").unwrap_or("unknown_version"),
1059 config::host_triple(),
1063 fn potentially_plural_count(count: usize, word: &str) -> String {
1064 format!("{} {}{}", count, word, pluralize!(count))
1067 fn has_expected_num_generic_args<'tcx>(
1069 trait_did: Option<DefId>,
1072 trait_did.map_or(true, |trait_did| {
1073 let generics = tcx.generics_of(trait_did);
1074 generics.count() == expected + if generics.has_self { 1 } else { 0 }