1 /*!
2
3 # typeck
4
5 The type checker is responsible for:
6
7 1. Determining the type of each expression.
8 2. Resolving methods and traits.
9 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
10 Well, dear reader, read on.)
11
12 The main entry point is [`check_crate()`]. Type checking operates in
13 several major phases:
14
15 1. The collect phase first passes over all items and determines their
16 type, without examining their "innards".
17
18 2. Variance inference then runs to compute the variance of each parameter.
19
20 3. Coherence checks for overlapping or orphaned impls.
21
22 4. Finally, the check phase then checks function bodies and so forth.
23 Within the check phase, we check each function body one at a time
24 (bodies of function expressions are checked as part of the
25 containing function). Inference is used to supply types wherever
26 they are unknown. The actual checking of a function itself has
27 several phases (check, regionck, writeback), as discussed in the
28 documentation for the [`check`] module.
29
30 The type checker is defined into various submodules which are documented
31 independently:
32
33 - astconv: converts the AST representation of types
34 into the `ty` representation.
35
36 - collect: computes the types of each top-level item and enters them into
37 the `tcx.types` table for later use.
38
39 - coherence: enforces coherence rules, builds some tables.
40
41 - variance: variance inference
42
43 - outlives: outlives inference
44
45 - check: walks over function bodies and type checks them, inferring types for
46 local variables, type parameters, etc as necessary.
47
48 - infer: finds the types to use for each type variable such that
49 all subtyping and assignment constraints are met. In essence, the check
50 module specifies the constraints, and the infer module solves them.
51
52 ## Note
53
54 This API is completely unstable and subject to change.
55
56 */
57
58 #![allow(rustc::potential_query_instability)]
59 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
60 #![feature(box_patterns)]
61 #![feature(control_flow_enum)]
62 #![feature(if_let_guard)]
63 #![feature(is_sorted)]
64 #![feature(iter_intersperse)]
65 #![feature(let_chains)]
66 #![feature(min_specialization)]
67 #![feature(never_type)]
68 #![feature(lazy_cell)]
69 #![feature(slice_partition_dedup)]
70 #![feature(try_blocks)]
71 #![feature(type_alias_impl_trait)]
72 #![recursion_limit = "256"]
73
74 #[macro_use]
75 extern crate tracing;
76
77 #[macro_use]
78 extern crate rustc_middle;
79
80 // These are used by Clippy.
81 pub mod check;
82
83 pub mod astconv;
84 pub mod autoderef;
85 mod bounds;
86 mod check_unused;
87 mod coherence;
88 // FIXME: This module shouldn't be public.
89 pub mod collect;
90 mod constrained_generic_params;
91 mod errors;
92 pub mod hir_wf_check;
93 mod impl_wf_check;
94 mod outlives;
95 pub mod structured_errors;
96 mod variance;
97
98 use rustc_errors::ErrorGuaranteed;
99 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
100 use rustc_fluent_macro::fluent_messages;
101 use rustc_hir as hir;
102 use rustc_hir::Node;
103 use rustc_infer::infer::TyCtxtInferExt;
104 use rustc_middle::middle;
105 use rustc_middle::query::Providers;
106 use rustc_middle::ty::{self, Ty, TyCtxt};
107 use rustc_middle::util;
108 use rustc_session::{config::EntryFnType, parse::feature_err};
109 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
110 use rustc_span::{symbol::sym, Span, DUMMY_SP};
111 use rustc_target::spec::abi::Abi;
112 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
113 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
114
115 use std::ops::Not;
116
117 use astconv::{AstConv, OnlySelfBounds};
118 use bounds::Bounds;
119
120 fluent_messages! { "../messages.ftl" }
121
require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span)122 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
123 const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
124 const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
125 const UNSTABLE_EXPLAIN: &str =
126 "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
127
128 if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) {
129 return;
130 }
131
132 let extended_abi_support = tcx.features().extended_varargs_abi_support;
133 let conventions = match (extended_abi_support, abi.supports_varargs()) {
134 // User enabled additional ABI support for varargs and function ABI matches those ones.
135 (true, true) => return,
136
137 // Using this ABI would be ok, if the feature for additional ABI support was enabled.
138 // Return CONVENTIONS_STABLE, because we want the other error to look the same.
139 (false, true) => {
140 feature_err(
141 &tcx.sess.parse_sess,
142 sym::extended_varargs_abi_support,
143 span,
144 UNSTABLE_EXPLAIN,
145 )
146 .emit();
147 CONVENTIONS_STABLE
148 }
149
150 (false, false) => CONVENTIONS_STABLE,
151 (true, false) => CONVENTIONS_UNSTABLE,
152 };
153
154 tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
155 }
156
require_same_types<'tcx>( tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, )157 fn require_same_types<'tcx>(
158 tcx: TyCtxt<'tcx>,
159 cause: &ObligationCause<'tcx>,
160 param_env: ty::ParamEnv<'tcx>,
161 expected: Ty<'tcx>,
162 actual: Ty<'tcx>,
163 ) {
164 let infcx = &tcx.infer_ctxt().build();
165 let ocx = ObligationCtxt::new(infcx);
166 match ocx.eq(cause, param_env, expected, actual) {
167 Ok(()) => {
168 let errors = ocx.select_all_or_error();
169 if !errors.is_empty() {
170 infcx.err_ctxt().report_fulfillment_errors(&errors);
171 }
172 }
173 Err(err) => {
174 infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
175 }
176 }
177 }
178
check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId)179 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
180 let main_fnsig = tcx.fn_sig(main_def_id).subst_identity();
181 let main_span = tcx.def_span(main_def_id);
182
183 fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
184 if let Some(local_def_id) = def_id.as_local() {
185 let hir_type = tcx.type_of(local_def_id).subst_identity();
186 if !matches!(hir_type.kind(), ty::FnDef(..)) {
187 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
188 }
189 local_def_id
190 } else {
191 CRATE_DEF_ID
192 }
193 }
194
195 fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
196 if !def_id.is_local() {
197 return None;
198 }
199 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
200 match tcx.hir().find(hir_id) {
201 Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
202 generics.params.is_empty().not().then_some(generics.span)
203 }
204 _ => {
205 span_bug!(tcx.def_span(def_id), "main has a non-function type");
206 }
207 }
208 }
209
210 fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
211 if !def_id.is_local() {
212 return None;
213 }
214 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
215 match tcx.hir().find(hir_id) {
216 Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
217 Some(generics.where_clause_span)
218 }
219 _ => {
220 span_bug!(tcx.def_span(def_id), "main has a non-function type");
221 }
222 }
223 }
224
225 fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
226 if !def_id.is_local() {
227 return None;
228 }
229 Some(tcx.def_span(def_id))
230 }
231
232 fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
233 if !def_id.is_local() {
234 return None;
235 }
236 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
237 match tcx.hir().find(hir_id) {
238 Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
239 Some(fn_sig.decl.output.span())
240 }
241 _ => {
242 span_bug!(tcx.def_span(def_id), "main has a non-function type");
243 }
244 }
245 }
246
247 let mut error = false;
248 let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
249 let main_fn_generics = tcx.generics_of(main_def_id);
250 let main_fn_predicates = tcx.predicates_of(main_def_id);
251 if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
252 let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
253 tcx.sess.emit_err(errors::MainFunctionGenericParameters {
254 span: generics_param_span.unwrap_or(main_span),
255 label_span: generics_param_span,
256 });
257 error = true;
258 } else if !main_fn_predicates.predicates.is_empty() {
259 // generics may bring in implicit predicates, so we skip this check if generics is present.
260 let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
261 tcx.sess.emit_err(errors::WhereClauseOnMain {
262 span: generics_where_clauses_span.unwrap_or(main_span),
263 generics_span: generics_where_clauses_span,
264 });
265 error = true;
266 }
267
268 let main_asyncness = tcx.asyncness(main_def_id);
269 if let hir::IsAsync::Async = main_asyncness {
270 let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
271 tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
272 error = true;
273 }
274
275 for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
276 tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
277 error = true;
278 }
279
280 if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
281 // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
282 && !tcx.sess.target.is_like_wasm
283 && !tcx.sess.opts.actually_rustdoc
284 {
285 tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
286 error = true;
287 }
288
289 if error {
290 return;
291 }
292
293 // Main should have no WC, so empty param env is OK here.
294 let param_env = ty::ParamEnv::empty();
295 let expected_return_type;
296 if let Some(term_did) = tcx.lang_items().termination() {
297 let return_ty = main_fnsig.output();
298 let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
299 if !return_ty.bound_vars().is_empty() {
300 tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
301 error = true;
302 }
303 let return_ty = return_ty.skip_binder();
304 let infcx = tcx.infer_ctxt().build();
305 let cause = traits::ObligationCause::new(
306 return_ty_span,
307 main_diagnostics_def_id,
308 ObligationCauseCode::MainFunctionType,
309 );
310 let ocx = traits::ObligationCtxt::new(&infcx);
311 let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
312 ocx.register_bound(cause, param_env, norm_return_ty, term_did);
313 let errors = ocx.select_all_or_error();
314 if !errors.is_empty() {
315 infcx.err_ctxt().report_fulfillment_errors(&errors);
316 error = true;
317 }
318 // now we can take the return type of the given main function
319 expected_return_type = main_fnsig.output();
320 } else {
321 // standard () main return type
322 expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
323 }
324
325 if error {
326 return;
327 }
328
329 let se_ty = Ty::new_fn_ptr(
330 tcx,
331 expected_return_type.map_bound(|expected_return_type| {
332 tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
333 }),
334 );
335
336 require_same_types(
337 tcx,
338 &ObligationCause::new(
339 main_span,
340 main_diagnostics_def_id,
341 ObligationCauseCode::MainFunctionType,
342 ),
343 param_env,
344 se_ty,
345 Ty::new_fn_ptr(tcx, main_fnsig),
346 );
347 }
check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId)348 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
349 let start_def_id = start_def_id.expect_local();
350 let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
351 let start_span = tcx.def_span(start_def_id);
352 let start_t = tcx.type_of(start_def_id).subst_identity();
353 match start_t.kind() {
354 ty::FnDef(..) => {
355 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
356 if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
357 let mut error = false;
358 if !generics.params.is_empty() {
359 tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
360 error = true;
361 }
362 if generics.has_where_clause_predicates {
363 tcx.sess.emit_err(errors::StartFunctionWhere {
364 span: generics.where_clause_span,
365 });
366 error = true;
367 }
368 if let hir::IsAsync::Async = sig.header.asyncness {
369 let span = tcx.def_span(it.owner_id);
370 tcx.sess.emit_err(errors::StartAsync { span: span });
371 error = true;
372 }
373
374 let attrs = tcx.hir().attrs(start_id);
375 for attr in attrs {
376 if attr.has_name(sym::track_caller) {
377 tcx.sess.emit_err(errors::StartTrackCaller {
378 span: attr.span,
379 start: start_span,
380 });
381 error = true;
382 }
383 if attr.has_name(sym::target_feature)
384 // Calling functions with `#[target_feature]` is
385 // not unsafe on WASM, see #84988
386 && !tcx.sess.target.is_like_wasm
387 && !tcx.sess.opts.actually_rustdoc
388 {
389 tcx.sess.emit_err(errors::StartTargetFeature {
390 span: attr.span,
391 start: start_span,
392 });
393 error = true;
394 }
395 }
396
397 if error {
398 return;
399 }
400 }
401 }
402
403 let se_ty = Ty::new_fn_ptr(
404 tcx,
405 ty::Binder::dummy(tcx.mk_fn_sig(
406 [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
407 tcx.types.isize,
408 false,
409 hir::Unsafety::Normal,
410 Abi::Rust,
411 )),
412 );
413
414 require_same_types(
415 tcx,
416 &ObligationCause::new(
417 start_span,
418 start_def_id,
419 ObligationCauseCode::StartFunctionType,
420 ),
421 ty::ParamEnv::empty(), // start should not have any where bounds.
422 se_ty,
423 Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()),
424 );
425 }
426 _ => {
427 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
428 }
429 }
430 }
431
check_for_entry_fn(tcx: TyCtxt<'_>)432 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
433 match tcx.entry_fn(()) {
434 Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
435 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
436 _ => {}
437 }
438 }
439
provide(providers: &mut Providers)440 pub fn provide(providers: &mut Providers) {
441 collect::provide(providers);
442 coherence::provide(providers);
443 check::provide(providers);
444 variance::provide(providers);
445 outlives::provide(providers);
446 impl_wf_check::provide(providers);
447 hir_wf_check::provide(providers);
448 }
449
check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed>450 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
451 let _prof_timer = tcx.sess.timer("type_check_crate");
452
453 // this ensures that later parts of type checking can assume that items
454 // have valid types and not error
455 // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
456 tcx.sess.track_errors(|| {
457 tcx.sess.time("type_collecting", || {
458 tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
459 });
460 })?;
461
462 if tcx.features().rustc_attrs {
463 tcx.sess.track_errors(|| {
464 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
465 })?;
466 }
467
468 tcx.sess.track_errors(|| {
469 tcx.sess.time("impl_wf_inference", || {
470 tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
471 });
472 })?;
473
474 tcx.sess.track_errors(|| {
475 tcx.sess.time("coherence_checking", || {
476 for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
477 tcx.ensure().coherent_trait(trait_def_id);
478 }
479
480 // these queries are executed for side-effects (error reporting):
481 tcx.ensure().crate_inherent_impls(());
482 tcx.ensure().crate_inherent_impls_overlap_check(());
483 });
484 })?;
485
486 if tcx.features().rustc_attrs {
487 tcx.sess.track_errors(|| {
488 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
489 })?;
490 }
491
492 tcx.sess.track_errors(|| {
493 tcx.sess.time("wf_checking", || {
494 tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
495 });
496 })?;
497
498 // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
499 tcx.sess.time("item_types_checking", || {
500 tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
501 });
502
503 check_unused::check_crate(tcx);
504 check_for_entry_fn(tcx);
505
506 if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
507 }
508
509 /// A quasi-deprecated helper used in rustdoc and clippy to get
510 /// the type from a HIR node.
hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx>511 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
512 // In case there are any projections, etc., find the "environment"
513 // def-ID that will be used to determine the traits/predicates in
514 // scope. This is derived from the enclosing item-like thing.
515 let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
516 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
517 item_cx.astconv().ast_ty_to_ty(hir_ty)
518 }
519
hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, hir_trait: &hir::TraitRef<'_>, self_ty: Ty<'tcx>, ) -> Bounds<'tcx>520 pub fn hir_trait_to_predicates<'tcx>(
521 tcx: TyCtxt<'tcx>,
522 hir_trait: &hir::TraitRef<'_>,
523 self_ty: Ty<'tcx>,
524 ) -> Bounds<'tcx> {
525 // In case there are any projections, etc., find the "environment"
526 // def-ID that will be used to determine the traits/predicates in
527 // scope. This is derived from the enclosing item-like thing.
528 let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
529 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
530 let mut bounds = Bounds::default();
531 let _ = &item_cx.astconv().instantiate_poly_trait_ref(
532 hir_trait,
533 DUMMY_SP,
534 ty::BoundConstness::NotConst,
535 ty::ImplPolarity::Positive,
536 self_ty,
537 &mut bounds,
538 true,
539 OnlySelfBounds(false),
540 );
541
542 bounds
543 }
544