]>
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?" | |
1a4d82fc JJ |
10 | Well, dear reader, read on) |
11 | ||
0731742a | 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 | |
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 | |
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 | |
1b1a35ee | 58 | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] |
29967ef6 | 59 | #![feature(array_value_iter)] |
60c5eb7d | 60 | #![feature(bool_to_option)] |
1a4d82fc | 61 | #![feature(box_syntax)] |
2c00a5a8 | 62 | #![feature(crate_visibility_modifier)] |
dc9dc135 | 63 | #![feature(in_band_lifetimes)] |
fc512014 | 64 | #![feature(is_sorted)] |
0bf4aa26 | 65 | #![feature(nll)] |
ba9703b0 | 66 | #![feature(or_patterns)] |
dfeec247 | 67 | #![feature(try_blocks)] |
0531ce1d | 68 | #![feature(never_type)] |
ba9703b0 | 69 | #![feature(slice_partition_dedup)] |
29967ef6 | 70 | #![feature(control_flow_enum)] |
dfeec247 | 71 | #![recursion_limit = "256"] |
7cac9316 | 72 | |
dfeec247 | 73 | #[macro_use] |
3dfed10e | 74 | extern crate tracing; |
94b46f34 | 75 | |
dfeec247 | 76 | #[macro_use] |
ba9703b0 | 77 | extern crate rustc_middle; |
1a4d82fc | 78 | |
3dfed10e XL |
79 | // These are used by Clippy. |
80 | pub mod check; | |
60c5eb7d | 81 | pub mod expr_use_visitor; |
85aaf69f | 82 | |
2c00a5a8 | 83 | mod astconv; |
3dfed10e | 84 | mod bounds; |
7cac9316 | 85 | mod check_unused; |
2c00a5a8 | 86 | mod coherence; |
7cac9316 | 87 | mod collect; |
532ac7d7 | 88 | mod constrained_generic_params; |
1b1a35ee | 89 | mod errors; |
476ff2be | 90 | mod impl_wf_check; |
60c5eb7d | 91 | mod mem_categorization; |
abe05a73 | 92 | mod outlives; |
dfeec247 | 93 | mod structured_errors; |
7cac9316 | 94 | mod variance; |
1a4d82fc | 95 | |
ba9703b0 | 96 | use rustc_errors::{struct_span_err, ErrorReported}; |
dfeec247 | 97 | use rustc_hir as hir; |
f9f354fc | 98 | use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; |
dfeec247 | 99 | use rustc_hir::Node; |
74b04a01 | 100 | use rustc_infer::infer::{InferOk, TyCtxtInferExt}; |
ba9703b0 XL |
101 | use rustc_infer::traits::TraitEngineExt as _; |
102 | use rustc_middle::middle; | |
103 | use rustc_middle::ty::query::Providers; | |
104 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
105 | use rustc_middle::util; | |
106 | use rustc_session::config::EntryFnType; | |
f9652781 | 107 | use rustc_span::{symbol::sym, Span, DUMMY_SP}; |
dfeec247 | 108 | use rustc_target::spec::abi::Abi; |
ba9703b0 XL |
109 | use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; |
110 | use rustc_trait_selection::traits::{ | |
111 | ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, | |
112 | }; | |
60c5eb7d | 113 | |
0731742a XL |
114 | use std::iter; |
115 | ||
3dfed10e XL |
116 | use astconv::AstConv; |
117 | use bounds::Bounds; | |
1a4d82fc | 118 | |
dfeec247 | 119 | fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { |
532ac7d7 | 120 | if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) { |
dfeec247 XL |
121 | let mut err = struct_span_err!( |
122 | tcx.sess, | |
123 | span, | |
124 | E0045, | |
125 | "C-variadic function must have C or cdecl calling convention" | |
126 | ); | |
532ac7d7 | 127 | err.span_label(span, "C-variadics require C or cdecl calling convention").emit(); |
c1a9b12d SL |
128 | } |
129 | } | |
130 | ||
dc9dc135 XL |
131 | fn require_same_types<'tcx>( |
132 | tcx: TyCtxt<'tcx>, | |
133 | cause: &ObligationCause<'tcx>, | |
134 | expected: Ty<'tcx>, | |
135 | actual: Ty<'tcx>, | |
136 | ) -> bool { | |
041b39d2 | 137 | tcx.infer_ctxt().enter(|ref infcx| { |
0531ce1d XL |
138 | let param_env = ty::ParamEnv::empty(); |
139 | let mut fulfill_cx = TraitEngine::new(infcx.tcx); | |
7cac9316 | 140 | match infcx.at(&cause, param_env).eq(expected, actual) { |
c30ab7b3 | 141 | Ok(InferOk { obligations, .. }) => { |
cc61c64b | 142 | fulfill_cx.register_predicate_obligations(infcx, obligations); |
c30ab7b3 SL |
143 | } |
144 | Err(err) => { | |
32a655c1 | 145 | infcx.report_mismatched_types(cause, expected, actual, err).emit(); |
cc61c64b XL |
146 | return false; |
147 | } | |
148 | } | |
149 | ||
150 | match fulfill_cx.select_all_or_error(infcx) { | |
151 | Ok(()) => true, | |
152 | Err(errors) => { | |
0531ce1d | 153 | infcx.report_fulfillment_errors(&errors, None, false); |
c30ab7b3 SL |
154 | false |
155 | } | |
1a4d82fc | 156 | } |
a7813a04 | 157 | }) |
1a4d82fc JJ |
158 | } |
159 | ||
f9f354fc | 160 | fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) { |
3dfed10e | 161 | let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id); |
9fa01778 | 162 | let main_span = tcx.def_span(main_def_id); |
7cac9316 | 163 | let main_t = tcx.type_of(main_def_id); |
1b1a35ee | 164 | match main_t.kind() { |
b7449926 | 165 | ty::FnDef(..) => { |
dc9dc135 | 166 | if let Some(Node::Item(it)) = tcx.hir().find(main_id) { |
ba9703b0 | 167 | if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { |
0bf4aa26 XL |
168 | let mut error = false; |
169 | if !generics.params.is_empty() { | |
170 | let msg = "`main` function is not allowed to have generic \ | |
dfeec247 XL |
171 | parameters" |
172 | .to_owned(); | |
0bf4aa26 XL |
173 | let label = "`main` cannot have generic parameters".to_string(); |
174 | struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) | |
175 | .span_label(generics.span, label) | |
176 | .emit(); | |
177 | error = true; | |
178 | } | |
179 | if let Some(sp) = generics.where_clause.span() { | |
dfeec247 XL |
180 | struct_span_err!( |
181 | tcx.sess, | |
182 | sp, | |
183 | E0646, | |
184 | "`main` function is not allowed to have a `where` clause" | |
185 | ) | |
186 | .span_label(sp, "`main` cannot have a `where` clause") | |
187 | .emit(); | |
0bf4aa26 XL |
188 | error = true; |
189 | } | |
ba9703b0 XL |
190 | if let hir::IsAsync::Async = sig.header.asyncness { |
191 | let span = tcx.sess.source_map().guess_head_span(it.span); | |
192 | struct_span_err!( | |
193 | tcx.sess, | |
194 | span, | |
195 | E0752, | |
196 | "`main` function is not allowed to be `async`" | |
197 | ) | |
198 | .span_label(span, "`main` function is not allowed to be `async`") | |
199 | .emit(); | |
200 | error = true; | |
201 | } | |
f9652781 XL |
202 | |
203 | for attr in it.attrs { | |
3dfed10e | 204 | if tcx.sess.check_name(attr, sym::track_caller) { |
f9652781 XL |
205 | tcx.sess |
206 | .struct_span_err( | |
207 | attr.span, | |
208 | "`main` function is not allowed to be `#[track_caller]`", | |
209 | ) | |
210 | .span_label( | |
211 | main_span, | |
212 | "`main` function is not allowed to be `#[track_caller]`", | |
213 | ) | |
214 | .emit(); | |
215 | error = true; | |
216 | } | |
217 | } | |
218 | ||
0bf4aa26 XL |
219 | if error { |
220 | return; | |
1a4d82fc JJ |
221 | } |
222 | } | |
1a4d82fc | 223 | } |
ff7c6d11 XL |
224 | |
225 | let actual = tcx.fn_sig(main_def_id); | |
0531ce1d | 226 | let expected_return_type = if tcx.lang_items().termination().is_some() { |
ff7c6d11 XL |
227 | // we take the return type of the given main function, the real check is done |
228 | // in `check_fn` | |
fc512014 | 229 | actual.output() |
ff7c6d11 XL |
230 | } else { |
231 | // standard () main return type | |
fc512014 | 232 | ty::Binder::dummy(tcx.mk_unit()) |
ff7c6d11 XL |
233 | }; |
234 | ||
fc512014 XL |
235 | let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { |
236 | tcx.mk_fn_sig( | |
237 | iter::empty(), | |
238 | expected_return_type, | |
239 | false, | |
240 | hir::Unsafety::Normal, | |
241 | Abi::Rust, | |
242 | ) | |
243 | })); | |
1a4d82fc | 244 | |
5bcae85e | 245 | require_same_types( |
8bb4bdeb | 246 | tcx, |
476ff2be | 247 | &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), |
c30ab7b3 | 248 | se_ty, |
dfeec247 XL |
249 | tcx.mk_fn_ptr(actual), |
250 | ); | |
1a4d82fc JJ |
251 | } |
252 | _ => { | |
dfeec247 | 253 | span_bug!(main_span, "main has a non-function type: found `{}`", main_t); |
1a4d82fc JJ |
254 | } |
255 | } | |
256 | } | |
257 | ||
f9f354fc | 258 | fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) { |
3dfed10e | 259 | let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); |
9fa01778 | 260 | let start_span = tcx.def_span(start_def_id); |
7cac9316 | 261 | let start_t = tcx.type_of(start_def_id); |
1b1a35ee | 262 | match start_t.kind() { |
b7449926 | 263 | ty::FnDef(..) => { |
dc9dc135 | 264 | if let Some(Node::Item(it)) = tcx.hir().find(start_id) { |
ba9703b0 | 265 | if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { |
0bf4aa26 XL |
266 | let mut error = false; |
267 | if !generics.params.is_empty() { | |
dfeec247 XL |
268 | struct_span_err!( |
269 | tcx.sess, | |
270 | generics.span, | |
271 | E0132, | |
272 | "start function is not allowed to have type parameters" | |
273 | ) | |
274 | .span_label(generics.span, "start function cannot have type parameters") | |
275 | .emit(); | |
0bf4aa26 XL |
276 | error = true; |
277 | } | |
278 | if let Some(sp) = generics.where_clause.span() { | |
dfeec247 XL |
279 | struct_span_err!( |
280 | tcx.sess, | |
281 | sp, | |
282 | E0647, | |
283 | "start function is not allowed to have a `where` clause" | |
284 | ) | |
285 | .span_label(sp, "start function cannot have a `where` clause") | |
286 | .emit(); | |
0bf4aa26 XL |
287 | error = true; |
288 | } | |
ba9703b0 XL |
289 | if let hir::IsAsync::Async = sig.header.asyncness { |
290 | let span = tcx.sess.source_map().guess_head_span(it.span); | |
291 | struct_span_err!( | |
292 | tcx.sess, | |
293 | span, | |
294 | E0752, | |
f9652781 | 295 | "`start` is not allowed to be `async`" |
ba9703b0 | 296 | ) |
f9652781 | 297 | .span_label(span, "`start` is not allowed to be `async`") |
ba9703b0 XL |
298 | .emit(); |
299 | error = true; | |
300 | } | |
f9652781 XL |
301 | |
302 | for attr in it.attrs { | |
3dfed10e | 303 | if tcx.sess.check_name(attr, sym::track_caller) { |
f9652781 XL |
304 | tcx.sess |
305 | .struct_span_err( | |
306 | attr.span, | |
307 | "`start` is not allowed to be `#[track_caller]`", | |
308 | ) | |
309 | .span_label( | |
310 | start_span, | |
311 | "`start` is not allowed to be `#[track_caller]`", | |
312 | ) | |
313 | .emit(); | |
314 | error = true; | |
315 | } | |
316 | } | |
317 | ||
0bf4aa26 XL |
318 | if error { |
319 | return; | |
1a4d82fc JJ |
320 | } |
321 | } | |
1a4d82fc JJ |
322 | } |
323 | ||
29967ef6 | 324 | let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( |
dfeec247 XL |
325 | [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(), |
326 | tcx.types.isize, | |
327 | false, | |
328 | hir::Unsafety::Normal, | |
329 | Abi::Rust, | |
330 | ))); | |
1a4d82fc | 331 | |
5bcae85e | 332 | require_same_types( |
8bb4bdeb | 333 | tcx, |
476ff2be | 334 | &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), |
c30ab7b3 | 335 | se_ty, |
dfeec247 XL |
336 | tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)), |
337 | ); | |
1a4d82fc JJ |
338 | } |
339 | _ => { | |
dfeec247 | 340 | span_bug!(start_span, "start has a non-function type: found `{}`", start_t); |
1a4d82fc JJ |
341 | } |
342 | } | |
343 | } | |
344 | ||
416331ca | 345 | fn check_for_entry_fn(tcx: TyCtxt<'_>) { |
9fa01778 XL |
346 | match tcx.entry_fn(LOCAL_CRATE) { |
347 | Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id), | |
348 | Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), | |
349 | _ => {} | |
1a4d82fc JJ |
350 | } |
351 | } | |
352 | ||
f035d41b | 353 | pub fn provide(providers: &mut Providers) { |
8bb4bdeb XL |
354 | collect::provide(providers); |
355 | coherence::provide(providers); | |
356 | check::provide(providers); | |
7cac9316 | 357 | variance::provide(providers); |
abe05a73 | 358 | outlives::provide(providers); |
9fa01778 | 359 | impl_wf_check::provide(providers); |
8bb4bdeb XL |
360 | } |
361 | ||
416331ca | 362 | pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { |
dfeec247 | 363 | let _prof_timer = tcx.sess.timer("type_check_crate"); |
b7449926 | 364 | |
1a4d82fc JJ |
365 | // this ensures that later parts of type checking can assume that items |
366 | // have valid types and not error | |
1b1a35ee | 367 | // FIXME(matthewjasper) We shouldn't need to use `track_errors`. |
54a0048b | 368 | tcx.sess.track_errors(|| { |
dfeec247 | 369 | tcx.sess.time("type_collecting", || { |
532ac7d7 | 370 | for &module in tcx.hir().krate().modules.keys() { |
e74abb32 | 371 | tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module)); |
532ac7d7 XL |
372 | } |
373 | }); | |
54a0048b | 374 | })?; |
1a4d82fc | 375 | |
9fa01778 XL |
376 | if tcx.features().rustc_attrs { |
377 | tcx.sess.track_errors(|| { | |
dfeec247 | 378 | tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); |
9fa01778 XL |
379 | })?; |
380 | } | |
abe05a73 | 381 | |
476ff2be | 382 | tcx.sess.track_errors(|| { |
dfeec247 | 383 | tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx)); |
476ff2be SL |
384 | })?; |
385 | ||
54a0048b | 386 | tcx.sess.track_errors(|| { |
dfeec247 | 387 | tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx)); |
54a0048b | 388 | })?; |
1a4d82fc | 389 | |
9fa01778 XL |
390 | if tcx.features().rustc_attrs { |
391 | tcx.sess.track_errors(|| { | |
dfeec247 | 392 | tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); |
9fa01778 XL |
393 | })?; |
394 | } | |
7cac9316 | 395 | |
dc9dc135 | 396 | tcx.sess.track_errors(|| { |
dfeec247 | 397 | tcx.sess.time("wf_checking", || check::check_wf_new(tcx)); |
dc9dc135 | 398 | })?; |
1a4d82fc | 399 | |
3dfed10e | 400 | // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. |
dfeec247 | 401 | tcx.sess.time("item_types_checking", || { |
48663c56 | 402 | for &module in tcx.hir().krate().modules.keys() { |
e74abb32 | 403 | tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); |
48663c56 XL |
404 | } |
405 | }); | |
e9174d1e | 406 | |
dfeec247 | 407 | tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); |
e9174d1e | 408 | |
a7813a04 | 409 | check_unused::check_crate(tcx); |
8bb4bdeb | 410 | check_for_entry_fn(tcx); |
7453a54e | 411 | |
dfeec247 | 412 | if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) } |
1a4d82fc | 413 | } |
d9579d0f | 414 | |
532ac7d7 | 415 | /// A quasi-deprecated helper used in rustdoc and clippy to get |
7cac9316 | 416 | /// the type from a HIR node. |
dfeec247 | 417 | pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { |
dc9dc135 XL |
418 | // In case there are any projections, etc., find the "environment" |
419 | // def-ID that will be used to determine the traits/predicates in | |
7cac9316 | 420 | // scope. This is derived from the enclosing item-like thing. |
532ac7d7 | 421 | let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id); |
416331ca | 422 | let env_def_id = tcx.hir().local_def_id(env_node_id); |
f9f354fc | 423 | let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); |
0bf4aa26 | 424 | |
ff7c6d11 XL |
425 | astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty) |
426 | } | |
427 | ||
dc9dc135 XL |
428 | pub fn hir_trait_to_predicates<'tcx>( |
429 | tcx: TyCtxt<'tcx>, | |
dfeec247 | 430 | hir_trait: &hir::TraitRef<'_>, |
ba9703b0 | 431 | self_ty: Ty<'tcx>, |
416331ca | 432 | ) -> Bounds<'tcx> { |
dc9dc135 XL |
433 | // In case there are any projections, etc., find the "environment" |
434 | // def-ID that will be used to determine the traits/predicates in | |
ff7c6d11 | 435 | // scope. This is derived from the enclosing item-like thing. |
532ac7d7 | 436 | let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id); |
416331ca | 437 | let env_def_id = tcx.hir().local_def_id(env_hir_id); |
f9f354fc | 438 | let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); |
dc9dc135 | 439 | let mut bounds = Bounds::default(); |
416331ca | 440 | let _ = AstConv::instantiate_poly_trait_ref_inner( |
dfeec247 XL |
441 | &item_cx, |
442 | hir_trait, | |
443 | DUMMY_SP, | |
74b04a01 | 444 | hir::Constness::NotConst, |
ba9703b0 | 445 | self_ty, |
dfeec247 XL |
446 | &mut bounds, |
447 | true, | |
ff7c6d11 | 448 | ); |
0bf4aa26 | 449 | |
416331ca | 450 | bounds |
7cac9316 | 451 | } |