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