]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | /*! |
2 | ||
9fa01778 | 3 | # typeck |
1a4d82fc JJ |
4 | |
5 | The type checker is responsible for: | |
6 | ||
0731742a XL |
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?" | |
5869c6ff | 10 | Well, dear reader, read on.) |
1a4d82fc | 11 | |
5869c6ff | 12 | The main entry point is [`check_crate()`]. Type checking operates in |
1a4d82fc JJ |
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 | ||
0731742a | 18 | 2. Variance inference then runs to compute the variance of each parameter. |
1a4d82fc | 19 | |
0731742a | 20 | 3. Coherence checks for overlapping or orphaned impls. |
1a4d82fc JJ |
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 | |
5869c6ff | 28 | documentation for the [`check`] module. |
1a4d82fc JJ |
29 | |
30 | The type checker is defined into various submodules which are documented | |
31 | independently: | |
32 | ||
33 | - astconv: converts the AST representation of types | |
0731742a | 34 | into the `ty` representation. |
1a4d82fc JJ |
35 | |
36 | - collect: computes the types of each top-level item and enters them into | |
0731742a | 37 | the `tcx.types` table for later use. |
1a4d82fc | 38 | |
0731742a | 39 | - coherence: enforces coherence rules, builds some tables. |
1a4d82fc JJ |
40 | |
41 | - variance: variance inference | |
42 | ||
abe05a73 XL |
43 | - outlives: outlives inference |
44 | ||
1a4d82fc JJ |
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 | ||
0731742a | 52 | ## Note |
1a4d82fc JJ |
53 | |
54 | This API is completely unstable and subject to change. | |
55 | ||
56 | */ | |
9cc50fc6 | 57 | |
5e7ed085 | 58 | #![allow(rustc::potential_query_instability)] |
1b1a35ee | 59 | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] |
5e7ed085 FG |
60 | #![feature(box_patterns)] |
61 | #![feature(control_flow_enum)] | |
04454e1e | 62 | #![feature(drain_filter)] |
5e7ed085 | 63 | #![feature(hash_drain_filter)] |
94222f64 | 64 | #![feature(if_let_guard)] |
fc512014 | 65 | #![feature(is_sorted)] |
923072b8 | 66 | #![feature(iter_intersperse)] |
5e7ed085 | 67 | #![feature(let_chains)] |
c295e0f8 | 68 | #![feature(min_specialization)] |
0531ce1d | 69 | #![feature(never_type)] |
5e7ed085 | 70 | #![feature(once_cell)] |
ba9703b0 | 71 | #![feature(slice_partition_dedup)] |
5e7ed085 | 72 | #![feature(try_blocks)] |
2b03887a | 73 | #![feature(is_some_and)] |
f2b60f7d | 74 | #![feature(type_alias_impl_trait)] |
dfeec247 | 75 | #![recursion_limit = "256"] |
7cac9316 | 76 | |
dfeec247 | 77 | #[macro_use] |
3dfed10e | 78 | extern crate tracing; |
94b46f34 | 79 | |
dfeec247 | 80 | #[macro_use] |
ba9703b0 | 81 | extern crate rustc_middle; |
1a4d82fc | 82 | |
3dfed10e XL |
83 | // These are used by Clippy. |
84 | pub mod check; | |
85aaf69f | 85 | |
2b03887a | 86 | pub mod astconv; |
3dfed10e | 87 | mod bounds; |
7cac9316 | 88 | mod check_unused; |
2c00a5a8 | 89 | mod coherence; |
2b03887a FG |
90 | // FIXME: This module shouldn't be public. |
91 | pub mod collect; | |
532ac7d7 | 92 | mod constrained_generic_params; |
1b1a35ee | 93 | mod errors; |
136023e0 | 94 | pub mod hir_wf_check; |
476ff2be | 95 | mod impl_wf_check; |
abe05a73 | 96 | mod outlives; |
2b03887a | 97 | pub mod structured_errors; |
7cac9316 | 98 | mod variance; |
1a4d82fc | 99 | |
5e7ed085 | 100 | use rustc_errors::{struct_span_err, ErrorGuaranteed}; |
dfeec247 | 101 | use rustc_hir as hir; |
17df50a5 | 102 | use rustc_hir::def_id::DefId; |
cdc7bbd5 | 103 | use rustc_hir::{Node, CRATE_HIR_ID}; |
74b04a01 | 104 | use rustc_infer::infer::{InferOk, TyCtxtInferExt}; |
ba9703b0 XL |
105 | use rustc_middle::middle; |
106 | use rustc_middle::ty::query::Providers; | |
107 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
108 | use rustc_middle::util; | |
487cf647 | 109 | use rustc_session::{config::EntryFnType, parse::feature_err}; |
f9652781 | 110 | use rustc_span::{symbol::sym, Span, DUMMY_SP}; |
dfeec247 | 111 | use rustc_target::spec::abi::Abi; |
2b03887a | 112 | use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; |
f2b60f7d | 113 | use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; |
60c5eb7d | 114 | |
0731742a XL |
115 | use std::iter; |
116 | ||
3dfed10e XL |
117 | use astconv::AstConv; |
118 | use bounds::Bounds; | |
1a4d82fc | 119 | |
dfeec247 | 120 | fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { |
487cf647 FG |
121 | const ERROR_HEAD: &str = "C-variadic function must have a compatible calling convention"; |
122 | const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`"; | |
123 | const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; | |
124 | const UNSTABLE_EXPLAIN: &str = | |
125 | "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; | |
126 | ||
127 | if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) { | |
128 | return; | |
129 | } | |
130 | ||
131 | let extended_abi_support = tcx.features().extended_varargs_abi_support; | |
132 | let conventions = match (extended_abi_support, abi.supports_varargs()) { | |
133 | // User enabled additional ABI support for varargs and function ABI matches those ones. | |
134 | (true, true) => return, | |
135 | ||
136 | // Using this ABI would be ok, if the feature for additional ABI support was enabled. | |
137 | // Return CONVENTIONS_STABLE, because we want the other error to look the same. | |
138 | (false, true) => { | |
139 | feature_err( | |
140 | &tcx.sess.parse_sess, | |
141 | sym::extended_varargs_abi_support, | |
6a06907d | 142 | span, |
487cf647 FG |
143 | UNSTABLE_EXPLAIN, |
144 | ) | |
145 | .emit(); | |
146 | CONVENTIONS_STABLE | |
6a06907d | 147 | } |
487cf647 FG |
148 | |
149 | (false, false) => CONVENTIONS_STABLE, | |
150 | (true, false) => CONVENTIONS_UNSTABLE, | |
151 | }; | |
152 | ||
153 | let mut err = struct_span_err!(tcx.sess, span, E0045, "{}, like {}", ERROR_HEAD, conventions); | |
154 | err.span_label(span, ERROR_HEAD).emit(); | |
c1a9b12d SL |
155 | } |
156 | ||
dc9dc135 XL |
157 | fn require_same_types<'tcx>( |
158 | tcx: TyCtxt<'tcx>, | |
159 | cause: &ObligationCause<'tcx>, | |
160 | expected: Ty<'tcx>, | |
161 | actual: Ty<'tcx>, | |
162 | ) -> bool { | |
2b03887a FG |
163 | let infcx = &tcx.infer_ctxt().build(); |
164 | let param_env = ty::ParamEnv::empty(); | |
165 | let errors = match infcx.at(cause, param_env).eq(expected, actual) { | |
166 | Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), | |
167 | Err(err) => { | |
168 | infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); | |
169 | return false; | |
170 | } | |
171 | }; | |
cc61c64b | 172 | |
2b03887a FG |
173 | match &errors[..] { |
174 | [] => true, | |
175 | errors => { | |
487cf647 | 176 | infcx.err_ctxt().report_fulfillment_errors(errors, None); |
2b03887a | 177 | false |
1a4d82fc | 178 | } |
2b03887a | 179 | } |
1a4d82fc JJ |
180 | } |
181 | ||
cdc7bbd5 XL |
182 | fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { |
183 | let main_fnsig = tcx.fn_sig(main_def_id); | |
9fa01778 | 184 | let main_span = tcx.def_span(main_def_id); |
f9652781 | 185 | |
cdc7bbd5 XL |
186 | fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId { |
187 | if let Some(local_def_id) = def_id.as_local() { | |
188 | let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); | |
189 | let hir_type = tcx.type_of(local_def_id); | |
190 | if !matches!(hir_type.kind(), ty::FnDef(..)) { | |
191 | span_bug!(sp, "main has a non-function type: found `{}`", hir_type); | |
192 | } | |
193 | hir_id | |
194 | } else { | |
195 | CRATE_HIR_ID | |
196 | } | |
197 | } | |
f9652781 | 198 | |
cdc7bbd5 XL |
199 | fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { |
200 | if !def_id.is_local() { | |
201 | return None; | |
202 | } | |
203 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
204 | match tcx.hir().find(hir_id) { | |
205 | Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { | |
c295e0f8 XL |
206 | if !generics.params.is_empty() { |
207 | Some(generics.span) | |
208 | } else { | |
209 | None | |
210 | } | |
cdc7bbd5 XL |
211 | } |
212 | _ => { | |
213 | span_bug!(tcx.def_span(def_id), "main has a non-function type"); | |
1a4d82fc | 214 | } |
cdc7bbd5 XL |
215 | } |
216 | } | |
ff7c6d11 | 217 | |
cdc7bbd5 XL |
218 | fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { |
219 | if !def_id.is_local() { | |
220 | return None; | |
221 | } | |
222 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
223 | match tcx.hir().find(hir_id) { | |
224 | Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { | |
923072b8 | 225 | Some(generics.where_clause_span) |
cdc7bbd5 XL |
226 | } |
227 | _ => { | |
228 | span_bug!(tcx.def_span(def_id), "main has a non-function type"); | |
229 | } | |
230 | } | |
231 | } | |
1a4d82fc | 232 | |
cdc7bbd5 XL |
233 | fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { |
234 | if !def_id.is_local() { | |
235 | return None; | |
1a4d82fc | 236 | } |
064997fb | 237 | Some(tcx.def_span(def_id)) |
1a4d82fc | 238 | } |
1a4d82fc | 239 | |
cdc7bbd5 XL |
240 | fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { |
241 | if !def_id.is_local() { | |
242 | return None; | |
243 | } | |
244 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
245 | match tcx.hir().find(hir_id) { | |
246 | Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => { | |
247 | Some(fn_sig.decl.output.span()) | |
248 | } | |
249 | _ => { | |
250 | span_bug!(tcx.def_span(def_id), "main has a non-function type"); | |
251 | } | |
252 | } | |
253 | } | |
254 | ||
255 | let mut error = false; | |
256 | let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span); | |
257 | let main_fn_generics = tcx.generics_of(main_def_id); | |
258 | let main_fn_predicates = tcx.predicates_of(main_def_id); | |
259 | if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { | |
260 | let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); | |
261 | let msg = "`main` function is not allowed to have generic \ | |
262 | parameters"; | |
263 | let mut diag = | |
264 | struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg); | |
265 | if let Some(generics_param_span) = generics_param_span { | |
064997fb | 266 | let label = "`main` cannot have generic parameters"; |
cdc7bbd5 XL |
267 | diag.span_label(generics_param_span, label); |
268 | } | |
269 | diag.emit(); | |
270 | error = true; | |
271 | } else if !main_fn_predicates.predicates.is_empty() { | |
272 | // generics may bring in implicit predicates, so we skip this check if generics is present. | |
273 | let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); | |
274 | let mut diag = struct_span_err!( | |
275 | tcx.sess, | |
276 | generics_where_clauses_span.unwrap_or(main_span), | |
277 | E0646, | |
278 | "`main` function is not allowed to have a `where` clause" | |
279 | ); | |
280 | if let Some(generics_where_clauses_span) = generics_where_clauses_span { | |
281 | diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause"); | |
282 | } | |
283 | diag.emit(); | |
284 | error = true; | |
285 | } | |
286 | ||
287 | let main_asyncness = tcx.asyncness(main_def_id); | |
288 | if let hir::IsAsync::Async = main_asyncness { | |
289 | let mut diag = struct_span_err!( | |
290 | tcx.sess, | |
291 | main_span, | |
292 | E0752, | |
293 | "`main` function is not allowed to be `async`" | |
294 | ); | |
295 | let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); | |
296 | if let Some(asyncness_span) = asyncness_span { | |
297 | diag.span_label(asyncness_span, "`main` function is not allowed to be `async`"); | |
298 | } | |
299 | diag.emit(); | |
300 | error = true; | |
301 | } | |
302 | ||
04454e1e FG |
303 | for attr in tcx.get_attrs(main_def_id, sym::track_caller) { |
304 | tcx.sess | |
305 | .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`") | |
306 | .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`") | |
307 | .emit(); | |
308 | error = true; | |
cdc7bbd5 XL |
309 | } |
310 | ||
311 | if error { | |
312 | return; | |
313 | } | |
314 | ||
315 | let expected_return_type; | |
f2b60f7d | 316 | if let Some(term_did) = tcx.lang_items().termination() { |
cdc7bbd5 XL |
317 | let return_ty = main_fnsig.output(); |
318 | let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); | |
319 | if !return_ty.bound_vars().is_empty() { | |
320 | let msg = "`main` function return type is not allowed to have generic \ | |
064997fb | 321 | parameters"; |
cdc7bbd5 XL |
322 | struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit(); |
323 | error = true; | |
324 | } | |
325 | let return_ty = return_ty.skip_binder(); | |
2b03887a FG |
326 | let infcx = tcx.infer_ctxt().build(); |
327 | // Main should have no WC, so empty param env is OK here. | |
328 | let param_env = ty::ParamEnv::empty(); | |
329 | let cause = traits::ObligationCause::new( | |
330 | return_ty_span, | |
331 | main_diagnostics_hir_id, | |
332 | ObligationCauseCode::MainFunctionType, | |
333 | ); | |
334 | let ocx = traits::ObligationCtxt::new(&infcx); | |
487cf647 | 335 | let norm_return_ty = ocx.normalize(&cause, param_env, return_ty); |
2b03887a FG |
336 | ocx.register_bound(cause, param_env, norm_return_ty, term_did); |
337 | let errors = ocx.select_all_or_error(); | |
338 | if !errors.is_empty() { | |
487cf647 | 339 | infcx.err_ctxt().report_fulfillment_errors(&errors, None); |
2b03887a FG |
340 | error = true; |
341 | } | |
cdc7bbd5 XL |
342 | // now we can take the return type of the given main function |
343 | expected_return_type = main_fnsig.output(); | |
344 | } else { | |
345 | // standard () main return type | |
346 | expected_return_type = ty::Binder::dummy(tcx.mk_unit()); | |
347 | } | |
348 | ||
349 | if error { | |
350 | return; | |
351 | } | |
352 | ||
353 | let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { | |
354 | tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) | |
355 | })); | |
356 | ||
357 | require_same_types( | |
358 | tcx, | |
359 | &ObligationCause::new( | |
360 | main_span, | |
361 | main_diagnostics_hir_id, | |
362 | ObligationCauseCode::MainFunctionType, | |
363 | ), | |
364 | se_ty, | |
365 | tcx.mk_fn_ptr(main_fnsig), | |
366 | ); | |
367 | } | |
368 | fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { | |
369 | let start_def_id = start_def_id.expect_local(); | |
3dfed10e | 370 | let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); |
9fa01778 | 371 | let start_span = tcx.def_span(start_def_id); |
7cac9316 | 372 | let start_t = tcx.type_of(start_def_id); |
1b1a35ee | 373 | match start_t.kind() { |
b7449926 | 374 | ty::FnDef(..) => { |
dc9dc135 | 375 | if let Some(Node::Item(it)) = tcx.hir().find(start_id) { |
ba9703b0 | 376 | if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { |
0bf4aa26 XL |
377 | let mut error = false; |
378 | if !generics.params.is_empty() { | |
dfeec247 XL |
379 | struct_span_err!( |
380 | tcx.sess, | |
381 | generics.span, | |
382 | E0132, | |
383 | "start function is not allowed to have type parameters" | |
384 | ) | |
385 | .span_label(generics.span, "start function cannot have type parameters") | |
386 | .emit(); | |
0bf4aa26 XL |
387 | error = true; |
388 | } | |
923072b8 | 389 | if generics.has_where_clause_predicates { |
dfeec247 XL |
390 | struct_span_err!( |
391 | tcx.sess, | |
923072b8 | 392 | generics.where_clause_span, |
dfeec247 XL |
393 | E0647, |
394 | "start function is not allowed to have a `where` clause" | |
395 | ) | |
923072b8 FG |
396 | .span_label( |
397 | generics.where_clause_span, | |
398 | "start function cannot have a `where` clause", | |
399 | ) | |
dfeec247 | 400 | .emit(); |
0bf4aa26 XL |
401 | error = true; |
402 | } | |
ba9703b0 | 403 | if let hir::IsAsync::Async = sig.header.asyncness { |
2b03887a | 404 | let span = tcx.def_span(it.owner_id); |
ba9703b0 XL |
405 | struct_span_err!( |
406 | tcx.sess, | |
407 | span, | |
408 | E0752, | |
f9652781 | 409 | "`start` is not allowed to be `async`" |
ba9703b0 | 410 | ) |
f9652781 | 411 | .span_label(span, "`start` is not allowed to be `async`") |
ba9703b0 XL |
412 | .emit(); |
413 | error = true; | |
414 | } | |
f9652781 | 415 | |
6a06907d XL |
416 | let attrs = tcx.hir().attrs(start_id); |
417 | for attr in attrs { | |
94222f64 | 418 | if attr.has_name(sym::track_caller) { |
f9652781 XL |
419 | tcx.sess |
420 | .struct_span_err( | |
421 | attr.span, | |
422 | "`start` is not allowed to be `#[track_caller]`", | |
423 | ) | |
424 | .span_label( | |
425 | start_span, | |
426 | "`start` is not allowed to be `#[track_caller]`", | |
427 | ) | |
428 | .emit(); | |
429 | error = true; | |
430 | } | |
431 | } | |
432 | ||
0bf4aa26 XL |
433 | if error { |
434 | return; | |
1a4d82fc JJ |
435 | } |
436 | } | |
1a4d82fc JJ |
437 | } |
438 | ||
29967ef6 | 439 | let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( |
dfeec247 XL |
440 | [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(), |
441 | tcx.types.isize, | |
442 | false, | |
443 | hir::Unsafety::Normal, | |
444 | Abi::Rust, | |
445 | ))); | |
1a4d82fc | 446 | |
5bcae85e | 447 | require_same_types( |
8bb4bdeb | 448 | tcx, |
476ff2be | 449 | &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), |
c30ab7b3 | 450 | se_ty, |
dfeec247 XL |
451 | tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)), |
452 | ); | |
1a4d82fc JJ |
453 | } |
454 | _ => { | |
dfeec247 | 455 | span_bug!(start_span, "start has a non-function type: found `{}`", start_t); |
1a4d82fc JJ |
456 | } |
457 | } | |
458 | } | |
459 | ||
416331ca | 460 | fn check_for_entry_fn(tcx: TyCtxt<'_>) { |
17df50a5 | 461 | match tcx.entry_fn(()) { |
f2b60f7d | 462 | Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id), |
9fa01778 XL |
463 | Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), |
464 | _ => {} | |
1a4d82fc JJ |
465 | } |
466 | } | |
467 | ||
f035d41b | 468 | pub fn provide(providers: &mut Providers) { |
8bb4bdeb XL |
469 | collect::provide(providers); |
470 | coherence::provide(providers); | |
471 | check::provide(providers); | |
7cac9316 | 472 | variance::provide(providers); |
abe05a73 | 473 | outlives::provide(providers); |
9fa01778 | 474 | impl_wf_check::provide(providers); |
136023e0 | 475 | hir_wf_check::provide(providers); |
8bb4bdeb XL |
476 | } |
477 | ||
5e7ed085 | 478 | pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { |
dfeec247 | 479 | let _prof_timer = tcx.sess.timer("type_check_crate"); |
b7449926 | 480 | |
1a4d82fc JJ |
481 | // this ensures that later parts of type checking can assume that items |
482 | // have valid types and not error | |
1b1a35ee | 483 | // FIXME(matthewjasper) We shouldn't need to use `track_errors`. |
54a0048b | 484 | tcx.sess.track_errors(|| { |
dfeec247 | 485 | tcx.sess.time("type_collecting", || { |
c295e0f8 | 486 | tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) |
532ac7d7 | 487 | }); |
54a0048b | 488 | })?; |
1a4d82fc | 489 | |
9fa01778 XL |
490 | if tcx.features().rustc_attrs { |
491 | tcx.sess.track_errors(|| { | |
dfeec247 | 492 | tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); |
9fa01778 XL |
493 | })?; |
494 | } | |
abe05a73 | 495 | |
476ff2be | 496 | tcx.sess.track_errors(|| { |
064997fb FG |
497 | tcx.sess.time("impl_wf_inference", || { |
498 | tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) | |
499 | }); | |
476ff2be SL |
500 | })?; |
501 | ||
54a0048b | 502 | tcx.sess.track_errors(|| { |
064997fb FG |
503 | tcx.sess.time("coherence_checking", || { |
504 | for &trait_def_id in tcx.all_local_trait_impls(()).keys() { | |
505 | tcx.ensure().coherent_trait(trait_def_id); | |
506 | } | |
507 | ||
508 | // these queries are executed for side-effects (error reporting): | |
509 | tcx.ensure().crate_inherent_impls(()); | |
510 | tcx.ensure().crate_inherent_impls_overlap_check(()); | |
511 | }); | |
54a0048b | 512 | })?; |
1a4d82fc | 513 | |
9fa01778 XL |
514 | if tcx.features().rustc_attrs { |
515 | tcx.sess.track_errors(|| { | |
dfeec247 | 516 | tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); |
9fa01778 XL |
517 | })?; |
518 | } | |
7cac9316 | 519 | |
dc9dc135 | 520 | tcx.sess.track_errors(|| { |
064997fb FG |
521 | tcx.sess.time("wf_checking", || { |
522 | tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module)) | |
523 | }); | |
dc9dc135 | 524 | })?; |
1a4d82fc | 525 | |
3dfed10e | 526 | // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. |
dfeec247 | 527 | tcx.sess.time("item_types_checking", || { |
c295e0f8 | 528 | tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) |
48663c56 | 529 | }); |
e9174d1e | 530 | |
17df50a5 | 531 | tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(())); |
e9174d1e | 532 | |
a7813a04 | 533 | check_unused::check_crate(tcx); |
8bb4bdeb | 534 | check_for_entry_fn(tcx); |
7453a54e | 535 | |
5e7ed085 | 536 | if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) } |
1a4d82fc | 537 | } |
d9579d0f | 538 | |
532ac7d7 | 539 | /// A quasi-deprecated helper used in rustdoc and clippy to get |
7cac9316 | 540 | /// the type from a HIR node. |
dfeec247 | 541 | pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { |
dc9dc135 XL |
542 | // In case there are any projections, etc., find the "environment" |
543 | // def-ID that will be used to determine the traits/predicates in | |
7cac9316 | 544 | // scope. This is derived from the enclosing item-like thing. |
5099ac24 | 545 | let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id); |
f9f354fc | 546 | let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); |
cdc7bbd5 | 547 | <dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty) |
ff7c6d11 XL |
548 | } |
549 | ||
dc9dc135 XL |
550 | pub fn hir_trait_to_predicates<'tcx>( |
551 | tcx: TyCtxt<'tcx>, | |
dfeec247 | 552 | hir_trait: &hir::TraitRef<'_>, |
ba9703b0 | 553 | self_ty: Ty<'tcx>, |
416331ca | 554 | ) -> Bounds<'tcx> { |
dc9dc135 XL |
555 | // In case there are any projections, etc., find the "environment" |
556 | // def-ID that will be used to determine the traits/predicates in | |
ff7c6d11 | 557 | // scope. This is derived from the enclosing item-like thing. |
5099ac24 | 558 | let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id); |
f9f354fc | 559 | let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); |
dc9dc135 | 560 | let mut bounds = Bounds::default(); |
cdc7bbd5 | 561 | let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref( |
dfeec247 XL |
562 | &item_cx, |
563 | hir_trait, | |
564 | DUMMY_SP, | |
94222f64 | 565 | ty::BoundConstness::NotConst, |
ba9703b0 | 566 | self_ty, |
dfeec247 XL |
567 | &mut bounds, |
568 | true, | |
ff7c6d11 | 569 | ); |
0bf4aa26 | 570 | |
416331ca | 571 | bounds |
7cac9316 | 572 | } |