]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | /*! | |
12 | ||
13 | typeck.rs, an introduction | |
14 | ||
15 | The type checker is responsible for: | |
16 | ||
17 | 1. Determining the type of each expression | |
18 | 2. Resolving methods and traits | |
19 | 3. Guaranteeing that most type rules are met ("most?", you say, "why most?" | |
20 | Well, dear reader, read on) | |
21 | ||
22 | The main entry point is `check_crate()`. Type checking operates in | |
23 | several major phases: | |
24 | ||
25 | 1. The collect phase first passes over all items and determines their | |
26 | type, without examining their "innards". | |
27 | ||
28 | 2. Variance inference then runs to compute the variance of each parameter | |
29 | ||
30 | 3. Coherence checks for overlapping or orphaned impls | |
31 | ||
32 | 4. Finally, the check phase then checks function bodies and so forth. | |
33 | Within the check phase, we check each function body one at a time | |
34 | (bodies of function expressions are checked as part of the | |
35 | containing function). Inference is used to supply types wherever | |
36 | they are unknown. The actual checking of a function itself has | |
37 | several phases (check, regionck, writeback), as discussed in the | |
38 | documentation for the `check` module. | |
39 | ||
40 | The type checker is defined into various submodules which are documented | |
41 | independently: | |
42 | ||
43 | - astconv: converts the AST representation of types | |
44 | into the `ty` representation | |
45 | ||
46 | - collect: computes the types of each top-level item and enters them into | |
476ff2be | 47 | the `tcx.types` table for later use |
1a4d82fc JJ |
48 | |
49 | - coherence: enforces coherence rules, builds some tables | |
50 | ||
51 | - variance: variance inference | |
52 | ||
53 | - check: walks over function bodies and type checks them, inferring types for | |
54 | local variables, type parameters, etc as necessary. | |
55 | ||
56 | - infer: finds the types to use for each type variable such that | |
57 | all subtyping and assignment constraints are met. In essence, the check | |
58 | module specifies the constraints, and the infer module solves them. | |
59 | ||
60 | # Note | |
61 | ||
62 | This API is completely unstable and subject to change. | |
63 | ||
64 | */ | |
9cc50fc6 | 65 | |
1a4d82fc | 66 | #![crate_name = "rustc_typeck"] |
e9174d1e | 67 | #![unstable(feature = "rustc_private", issue = "27812")] |
1a4d82fc JJ |
68 | #![crate_type = "dylib"] |
69 | #![crate_type = "rlib"] | |
e9174d1e | 70 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", |
62682a34 | 71 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", |
e9174d1e | 72 | html_root_url = "https://doc.rust-lang.org/nightly/")] |
32a655c1 | 73 | #![deny(warnings)] |
1a4d82fc | 74 | |
85aaf69f SL |
75 | #![allow(non_camel_case_types)] |
76 | ||
77 | #![feature(box_patterns)] | |
1a4d82fc | 78 | #![feature(box_syntax)] |
9e0c209e | 79 | #![feature(conservative_impl_trait)] |
32a655c1 | 80 | #![feature(loop_break_value)] |
85aaf69f | 81 | #![feature(quote)] |
1a4d82fc | 82 | #![feature(rustc_diagnostic_macros)] |
85aaf69f | 83 | #![feature(rustc_private)] |
85aaf69f | 84 | #![feature(staged_api)] |
1a4d82fc JJ |
85 | |
86 | #[macro_use] extern crate log; | |
87 | #[macro_use] extern crate syntax; | |
3157f602 | 88 | extern crate syntax_pos; |
1a4d82fc JJ |
89 | |
90 | extern crate arena; | |
85aaf69f | 91 | extern crate fmt_macros; |
54a0048b | 92 | #[macro_use] extern crate rustc; |
e9174d1e | 93 | extern crate rustc_platform_intrinsics as intrinsics; |
b039eaaf | 94 | extern crate rustc_back; |
54a0048b SL |
95 | extern crate rustc_const_math; |
96 | extern crate rustc_const_eval; | |
476ff2be | 97 | extern crate rustc_data_structures; |
3157f602 | 98 | extern crate rustc_errors as errors; |
1a4d82fc | 99 | |
9cc50fc6 | 100 | pub use rustc::dep_graph; |
54a0048b | 101 | pub use rustc::hir; |
1a4d82fc | 102 | pub use rustc::lint; |
1a4d82fc JJ |
103 | pub use rustc::middle; |
104 | pub use rustc::session; | |
105 | pub use rustc::util; | |
106 | ||
7453a54e | 107 | use dep_graph::DepNode; |
54a0048b | 108 | use hir::map as hir_map; |
476ff2be | 109 | use rustc::infer::InferOk; |
54a0048b | 110 | use rustc::ty::subst::Substs; |
476ff2be SL |
111 | use rustc::ty::{self, Ty, TyCtxt}; |
112 | use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; | |
113 | use session::config; | |
1a4d82fc | 114 | use util::common::time; |
1a4d82fc | 115 | |
7453a54e SL |
116 | use syntax::ast; |
117 | use syntax::abi::Abi; | |
3157f602 | 118 | use syntax_pos::Span; |
1a4d82fc | 119 | |
476ff2be | 120 | use std::iter; |
85aaf69f | 121 | use std::cell::RefCell; |
a7813a04 | 122 | use util::nodemap::NodeMap; |
85aaf69f SL |
123 | |
124 | // NB: This module needs to be declared first so diagnostics are | |
125 | // registered before they are used. | |
126 | pub mod diagnostics; | |
127 | ||
62682a34 | 128 | pub mod check; |
a7813a04 | 129 | pub mod check_unused; |
1a4d82fc | 130 | mod astconv; |
62682a34 | 131 | pub mod collect; |
85aaf69f | 132 | mod constrained_type_params; |
476ff2be | 133 | mod impl_wf_check; |
62682a34 SL |
134 | pub mod coherence; |
135 | pub mod variance; | |
1a4d82fc | 136 | |
c34b1796 | 137 | pub struct TypeAndSubsts<'tcx> { |
9e0c209e | 138 | pub substs: &'tcx Substs<'tcx>, |
1a4d82fc JJ |
139 | pub ty: Ty<'tcx>, |
140 | } | |
141 | ||
c34b1796 | 142 | pub struct CrateCtxt<'a, 'tcx: 'a> { |
a7813a04 XL |
143 | ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, |
144 | ||
85aaf69f SL |
145 | /// A vector of every trait accessible in the whole crate |
146 | /// (i.e. including those from subcrates). This is used only for | |
147 | /// error reporting, and so is lazily initialised and generally | |
148 | /// shouldn't taint the common path (hence the RefCell). | |
62682a34 | 149 | pub all_traits: RefCell<Option<check::method::AllTraitsVec>>, |
a7813a04 XL |
150 | |
151 | /// This stack is used to identify cycles in the user's source. | |
152 | /// Note that these cycles can cross multiple items. | |
153 | pub stack: RefCell<Vec<collect::AstConvRequest>>, | |
154 | ||
155 | pub tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
5bcae85e SL |
156 | |
157 | /// Obligations which will have to be checked at the end of | |
158 | /// type-checking, after all functions have been inferred. | |
159 | /// The key is the NodeId of the item the obligations were from. | |
160 | pub deferred_obligations: RefCell<NodeMap<Vec<traits::DeferredObligation<'tcx>>>>, | |
1a4d82fc JJ |
161 | } |
162 | ||
a7813a04 | 163 | fn require_c_abi_if_variadic(tcx: TyCtxt, |
e9174d1e | 164 | decl: &hir::FnDecl, |
7453a54e | 165 | abi: Abi, |
c1a9b12d | 166 | span: Span) { |
7453a54e | 167 | if decl.variadic && abi != Abi::C { |
5bcae85e | 168 | let mut err = struct_span_err!(tcx.sess, span, E0045, |
c1a9b12d | 169 | "variadic function must have C calling convention"); |
5bcae85e SL |
170 | err.span_label(span, &("variadics require C calling conventions").to_string()) |
171 | .emit(); | |
c1a9b12d SL |
172 | } |
173 | } | |
174 | ||
a7813a04 | 175 | fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, |
476ff2be | 176 | cause: &ObligationCause<'tcx>, |
c30ab7b3 SL |
177 | expected: Ty<'tcx>, |
178 | actual: Ty<'tcx>) | |
a7813a04 | 179 | -> bool { |
32a655c1 | 180 | ccx.tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { |
476ff2be | 181 | match infcx.eq_types(false, &cause, expected, actual) { |
c30ab7b3 SL |
182 | Ok(InferOk { obligations, .. }) => { |
183 | // FIXME(#32730) propagate obligations | |
184 | assert!(obligations.is_empty()); | |
185 | true | |
186 | } | |
187 | Err(err) => { | |
32a655c1 | 188 | infcx.report_mismatched_types(cause, expected, actual, err).emit(); |
c30ab7b3 SL |
189 | false |
190 | } | |
1a4d82fc | 191 | } |
a7813a04 | 192 | }) |
1a4d82fc JJ |
193 | } |
194 | ||
195 | fn check_main_fn_ty(ccx: &CrateCtxt, | |
196 | main_id: ast::NodeId, | |
197 | main_span: Span) { | |
198 | let tcx = ccx.tcx; | |
32a655c1 | 199 | let main_def_id = tcx.hir.local_def_id(main_id); |
476ff2be | 200 | let main_t = tcx.item_type(main_def_id); |
1a4d82fc | 201 | match main_t.sty { |
54a0048b | 202 | ty::TyFnDef(..) => { |
32a655c1 | 203 | match tcx.hir.find(main_id) { |
e9174d1e | 204 | Some(hir_map::NodeItem(it)) => { |
1a4d82fc | 205 | match it.node { |
9e0c209e SL |
206 | hir::ItemFn(.., ref generics, _) => { |
207 | if generics.is_parameterized() { | |
208 | struct_span_err!(ccx.tcx.sess, generics.span, E0131, | |
5bcae85e | 209 | "main function is not allowed to have type parameters") |
9e0c209e | 210 | .span_label(generics.span, |
5bcae85e SL |
211 | &format!("main cannot have type parameters")) |
212 | .emit(); | |
213 | return; | |
214 | } | |
1a4d82fc JJ |
215 | } |
216 | _ => () | |
217 | } | |
218 | } | |
219 | _ => () | |
220 | } | |
c30ab7b3 | 221 | let substs = tcx.intern_substs(&[]); |
a7813a04 XL |
222 | let se_ty = tcx.mk_fn_def(main_def_id, substs, |
223 | tcx.mk_bare_fn(ty::BareFnTy { | |
e9174d1e | 224 | unsafety: hir::Unsafety::Normal, |
7453a54e | 225 | abi: Abi::Rust, |
476ff2be | 226 | sig: ty::Binder(tcx.mk_fn_sig(iter::empty(), tcx.mk_nil(), false)) |
a7813a04 | 227 | })); |
1a4d82fc | 228 | |
5bcae85e SL |
229 | require_same_types( |
230 | ccx, | |
476ff2be | 231 | &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), |
c30ab7b3 SL |
232 | se_ty, |
233 | main_t); | |
1a4d82fc JJ |
234 | } |
235 | _ => { | |
54a0048b SL |
236 | span_bug!(main_span, |
237 | "main has a non-function type: found `{}`", | |
238 | main_t); | |
1a4d82fc JJ |
239 | } |
240 | } | |
241 | } | |
242 | ||
243 | fn check_start_fn_ty(ccx: &CrateCtxt, | |
244 | start_id: ast::NodeId, | |
245 | start_span: Span) { | |
246 | let tcx = ccx.tcx; | |
32a655c1 | 247 | let start_def_id = ccx.tcx.hir.local_def_id(start_id); |
476ff2be | 248 | let start_t = tcx.item_type(start_def_id); |
1a4d82fc | 249 | match start_t.sty { |
54a0048b | 250 | ty::TyFnDef(..) => { |
32a655c1 | 251 | match tcx.hir.find(start_id) { |
e9174d1e | 252 | Some(hir_map::NodeItem(it)) => { |
1a4d82fc | 253 | match it.node { |
9e0c209e | 254 | hir::ItemFn(..,ref ps,_) |
1a4d82fc | 255 | if ps.is_parameterized() => { |
9e0c209e | 256 | struct_span_err!(tcx.sess, ps.span, E0132, |
5bcae85e | 257 | "start function is not allowed to have type parameters") |
9e0c209e | 258 | .span_label(ps.span, |
5bcae85e SL |
259 | &format!("start function cannot have type parameters")) |
260 | .emit(); | |
1a4d82fc JJ |
261 | return; |
262 | } | |
263 | _ => () | |
264 | } | |
265 | } | |
266 | _ => () | |
267 | } | |
268 | ||
c30ab7b3 | 269 | let substs = tcx.intern_substs(&[]); |
a7813a04 XL |
270 | let se_ty = tcx.mk_fn_def(start_def_id, substs, |
271 | tcx.mk_bare_fn(ty::BareFnTy { | |
e9174d1e | 272 | unsafety: hir::Unsafety::Normal, |
7453a54e | 273 | abi: Abi::Rust, |
476ff2be SL |
274 | sig: ty::Binder(tcx.mk_fn_sig( |
275 | [ | |
c34b1796 | 276 | tcx.types.isize, |
c1a9b12d | 277 | tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) |
476ff2be SL |
278 | ].iter().cloned(), |
279 | tcx.types.isize, | |
280 | false, | |
281 | )), | |
a7813a04 | 282 | })); |
1a4d82fc | 283 | |
5bcae85e SL |
284 | require_same_types( |
285 | ccx, | |
476ff2be | 286 | &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), |
c30ab7b3 SL |
287 | se_ty, |
288 | start_t); | |
1a4d82fc JJ |
289 | } |
290 | _ => { | |
54a0048b SL |
291 | span_bug!(start_span, |
292 | "start has a non-function type: found `{}`", | |
293 | start_t); | |
1a4d82fc JJ |
294 | } |
295 | } | |
296 | } | |
297 | ||
298 | fn check_for_entry_fn(ccx: &CrateCtxt) { | |
299 | let tcx = ccx.tcx; | |
7453a54e | 300 | let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn); |
3157f602 XL |
301 | if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() { |
302 | match tcx.sess.entry_type.get() { | |
1a4d82fc JJ |
303 | Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp), |
304 | Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp), | |
305 | Some(config::EntryNone) => {} | |
54a0048b | 306 | None => bug!("entry function without a type") |
3157f602 | 307 | } |
1a4d82fc JJ |
308 | } |
309 | } | |
310 | ||
5bcae85e | 311 | pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) |
476ff2be | 312 | -> Result<NodeMap<Ty<'tcx>>, usize> { |
1a4d82fc JJ |
313 | let time_passes = tcx.sess.time_passes(); |
314 | let ccx = CrateCtxt { | |
a7813a04 | 315 | ast_ty_to_ty_cache: RefCell::new(NodeMap()), |
85aaf69f | 316 | all_traits: RefCell::new(None), |
a7813a04 | 317 | stack: RefCell::new(Vec::new()), |
5bcae85e SL |
318 | tcx: tcx, |
319 | deferred_obligations: RefCell::new(NodeMap()), | |
1a4d82fc JJ |
320 | }; |
321 | ||
1a4d82fc JJ |
322 | // this ensures that later parts of type checking can assume that items |
323 | // have valid types and not error | |
54a0048b | 324 | tcx.sess.track_errors(|| { |
9cc50fc6 | 325 | time(time_passes, "type collecting", || |
a7813a04 | 326 | collect::collect_item_types(&ccx)); |
9cc50fc6 | 327 | |
54a0048b | 328 | })?; |
1a4d82fc | 329 | |
e9174d1e | 330 | time(time_passes, "variance inference", || |
1a4d82fc JJ |
331 | variance::infer_variance(tcx)); |
332 | ||
476ff2be SL |
333 | tcx.sess.track_errors(|| { |
334 | time(time_passes, "impl wf inference", || | |
335 | impl_wf_check::impl_wf_check(&ccx)); | |
336 | })?; | |
337 | ||
54a0048b | 338 | tcx.sess.track_errors(|| { |
9cc50fc6 SL |
339 | time(time_passes, "coherence checking", || |
340 | coherence::check_coherence(&ccx)); | |
54a0048b | 341 | })?; |
1a4d82fc | 342 | |
54a0048b | 343 | time(time_passes, "wf checking", || check::check_wf_new(&ccx))?; |
e9174d1e | 344 | |
54a0048b | 345 | time(time_passes, "item-types checking", || check::check_item_types(&ccx))?; |
1a4d82fc | 346 | |
54a0048b | 347 | time(time_passes, "item-bodies checking", || check::check_item_bodies(&ccx))?; |
e9174d1e | 348 | |
54a0048b | 349 | time(time_passes, "drop-impl checking", || check::check_drop_impls(&ccx))?; |
e9174d1e | 350 | |
a7813a04 | 351 | check_unused::check_crate(tcx); |
1a4d82fc | 352 | check_for_entry_fn(&ccx); |
7453a54e SL |
353 | |
354 | let err_count = tcx.sess.err_count(); | |
355 | if err_count == 0 { | |
476ff2be | 356 | Ok(ccx.ast_ty_to_ty_cache.into_inner()) |
7453a54e SL |
357 | } else { |
358 | Err(err_count) | |
359 | } | |
1a4d82fc | 360 | } |
d9579d0f | 361 | |
d9579d0f | 362 | __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS } |