]>
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 | |
47 | the `cx.tcache` table for later use | |
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/")] |
7453a54e | 73 | #![cfg_attr(not(stage0), deny(warnings))] |
1a4d82fc | 74 | |
85aaf69f SL |
75 | #![allow(non_camel_case_types)] |
76 | ||
77 | #![feature(box_patterns)] | |
1a4d82fc | 78 | #![feature(box_syntax)] |
62682a34 | 79 | #![feature(iter_arith)] |
85aaf69f | 80 | #![feature(quote)] |
1a4d82fc | 81 | #![feature(rustc_diagnostic_macros)] |
85aaf69f | 82 | #![feature(rustc_private)] |
85aaf69f | 83 | #![feature(staged_api)] |
54a0048b | 84 | #![feature(question_mark)] |
1a4d82fc JJ |
85 | |
86 | #[macro_use] extern crate log; | |
87 | #[macro_use] extern crate syntax; | |
88 | ||
89 | extern crate arena; | |
85aaf69f | 90 | extern crate fmt_macros; |
54a0048b | 91 | #[macro_use] extern crate rustc; |
e9174d1e | 92 | extern crate rustc_platform_intrinsics as intrinsics; |
b039eaaf | 93 | extern crate rustc_back; |
54a0048b SL |
94 | extern crate rustc_const_math; |
95 | extern crate rustc_const_eval; | |
1a4d82fc | 96 | |
9cc50fc6 | 97 | pub use rustc::dep_graph; |
54a0048b | 98 | pub use rustc::hir; |
1a4d82fc | 99 | pub use rustc::lint; |
1a4d82fc JJ |
100 | pub use rustc::middle; |
101 | pub use rustc::session; | |
102 | pub use rustc::util; | |
103 | ||
7453a54e | 104 | use dep_graph::DepNode; |
54a0048b SL |
105 | use hir::map as hir_map; |
106 | use hir::def::Def; | |
107 | use rustc::infer::{self, TypeOrigin}; | |
108 | use rustc::ty::subst::Substs; | |
109 | use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; | |
110 | use rustc::traits::ProjectionMode; | |
7453a54e | 111 | use session::{config, CompileResult}; |
1a4d82fc | 112 | use util::common::time; |
1a4d82fc JJ |
113 | |
114 | use syntax::codemap::Span; | |
7453a54e SL |
115 | use syntax::ast; |
116 | use syntax::abi::Abi; | |
1a4d82fc | 117 | |
85aaf69f SL |
118 | use std::cell::RefCell; |
119 | ||
120 | // NB: This module needs to be declared first so diagnostics are | |
121 | // registered before they are used. | |
122 | pub mod diagnostics; | |
123 | ||
62682a34 | 124 | pub mod check; |
1a4d82fc JJ |
125 | mod rscope; |
126 | mod astconv; | |
62682a34 | 127 | pub mod collect; |
85aaf69f | 128 | mod constrained_type_params; |
62682a34 SL |
129 | pub mod coherence; |
130 | pub mod variance; | |
1a4d82fc | 131 | |
c34b1796 | 132 | pub struct TypeAndSubsts<'tcx> { |
54a0048b | 133 | pub substs: Substs<'tcx>, |
1a4d82fc JJ |
134 | pub ty: Ty<'tcx>, |
135 | } | |
136 | ||
c34b1796 | 137 | pub struct CrateCtxt<'a, 'tcx: 'a> { |
1a4d82fc | 138 | // A mapping from method call sites to traits that have that method. |
54a0048b | 139 | pub trait_map: hir::TraitMap, |
85aaf69f SL |
140 | /// A vector of every trait accessible in the whole crate |
141 | /// (i.e. including those from subcrates). This is used only for | |
142 | /// error reporting, and so is lazily initialised and generally | |
143 | /// shouldn't taint the common path (hence the RefCell). | |
62682a34 | 144 | pub all_traits: RefCell<Option<check::method::AllTraitsVec>>, |
54a0048b | 145 | pub tcx: &'a TyCtxt<'tcx>, |
1a4d82fc JJ |
146 | } |
147 | ||
148 | // Functions that write types into the node type table | |
54a0048b | 149 | fn write_ty_to_tcx<'tcx>(tcx: &TyCtxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) { |
62682a34 | 150 | debug!("write_ty_to_tcx({}, {:?})", node_id, ty); |
c1a9b12d | 151 | assert!(!ty.needs_infer()); |
c34b1796 | 152 | tcx.node_type_insert(node_id, ty); |
1a4d82fc JJ |
153 | } |
154 | ||
54a0048b | 155 | fn write_substs_to_tcx<'tcx>(tcx: &TyCtxt<'tcx>, |
1a4d82fc JJ |
156 | node_id: ast::NodeId, |
157 | item_substs: ty::ItemSubsts<'tcx>) { | |
158 | if !item_substs.is_noop() { | |
62682a34 | 159 | debug!("write_substs_to_tcx({}, {:?})", |
1a4d82fc | 160 | node_id, |
62682a34 | 161 | item_substs); |
1a4d82fc | 162 | |
c1a9b12d | 163 | assert!(!item_substs.substs.types.needs_infer()); |
1a4d82fc | 164 | |
c1a9b12d | 165 | tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs); |
1a4d82fc JJ |
166 | } |
167 | } | |
c34b1796 | 168 | |
54a0048b | 169 | fn lookup_full_def(tcx: &TyCtxt, sp: Span, id: ast::NodeId) -> Def { |
1a4d82fc | 170 | match tcx.def_map.borrow().get(&id) { |
c34b1796 AL |
171 | Some(x) => x.full_def(), |
172 | None => { | |
85aaf69f | 173 | span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") |
1a4d82fc JJ |
174 | } |
175 | } | |
176 | } | |
177 | ||
54a0048b | 178 | fn require_c_abi_if_variadic(tcx: &TyCtxt, |
e9174d1e | 179 | decl: &hir::FnDecl, |
7453a54e | 180 | abi: Abi, |
c1a9b12d | 181 | span: Span) { |
7453a54e | 182 | if decl.variadic && abi != Abi::C { |
c1a9b12d SL |
183 | span_err!(tcx.sess, span, E0045, |
184 | "variadic function must have C calling convention"); | |
185 | } | |
186 | } | |
187 | ||
54a0048b | 188 | fn require_same_types<'a, 'tcx, M>(tcx: &TyCtxt<'tcx>, |
1a4d82fc JJ |
189 | maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>, |
190 | t1_is_expected: bool, | |
191 | span: Span, | |
192 | t1: Ty<'tcx>, | |
193 | t2: Ty<'tcx>, | |
194 | msg: M) | |
195 | -> bool where | |
196 | M: FnOnce() -> String, | |
197 | { | |
198 | let result = match maybe_infcx { | |
199 | None => { | |
54a0048b | 200 | let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::AnyFinal); |
92a42be0 | 201 | infer::mk_eqty(&infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2) |
1a4d82fc JJ |
202 | } |
203 | Some(infcx) => { | |
92a42be0 | 204 | infer::mk_eqty(infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2) |
1a4d82fc JJ |
205 | } |
206 | }; | |
207 | ||
208 | match result { | |
209 | Ok(_) => true, | |
210 | Err(ref terr) => { | |
9cc50fc6 SL |
211 | let mut err = struct_span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr); |
212 | tcx.note_and_explain_type_err(&mut err, terr, span); | |
213 | err.emit(); | |
1a4d82fc JJ |
214 | false |
215 | } | |
216 | } | |
217 | } | |
218 | ||
219 | fn check_main_fn_ty(ccx: &CrateCtxt, | |
220 | main_id: ast::NodeId, | |
221 | main_span: Span) { | |
222 | let tcx = ccx.tcx; | |
c1a9b12d | 223 | let main_t = tcx.node_id_to_type(main_id); |
1a4d82fc | 224 | match main_t.sty { |
54a0048b | 225 | ty::TyFnDef(..) => { |
1a4d82fc | 226 | match tcx.map.find(main_id) { |
e9174d1e | 227 | Some(hir_map::NodeItem(it)) => { |
1a4d82fc | 228 | match it.node { |
e9174d1e | 229 | hir::ItemFn(_, _, _, _, ref ps, _) |
1a4d82fc JJ |
230 | if ps.is_parameterized() => { |
231 | span_err!(ccx.tcx.sess, main_span, E0131, | |
232 | "main function is not allowed to have type parameters"); | |
233 | return; | |
234 | } | |
235 | _ => () | |
236 | } | |
237 | } | |
238 | _ => () | |
239 | } | |
b039eaaf | 240 | let main_def_id = tcx.map.local_def_id(main_id); |
54a0048b SL |
241 | let substs = tcx.mk_substs(Substs::empty()); |
242 | let se_ty = tcx.mk_fn_def(main_def_id, substs, ty::BareFnTy { | |
e9174d1e | 243 | unsafety: hir::Unsafety::Normal, |
7453a54e | 244 | abi: Abi::Rust, |
1a4d82fc JJ |
245 | sig: ty::Binder(ty::FnSig { |
246 | inputs: Vec::new(), | |
c1a9b12d | 247 | output: ty::FnConverging(tcx.mk_nil()), |
1a4d82fc JJ |
248 | variadic: false |
249 | }) | |
54a0048b | 250 | }); |
1a4d82fc JJ |
251 | |
252 | require_same_types(tcx, None, false, main_span, main_t, se_ty, | |
253 | || { | |
254 | format!("main function expects type: `{}`", | |
62682a34 | 255 | se_ty) |
1a4d82fc JJ |
256 | }); |
257 | } | |
258 | _ => { | |
54a0048b SL |
259 | span_bug!(main_span, |
260 | "main has a non-function type: found `{}`", | |
261 | main_t); | |
1a4d82fc JJ |
262 | } |
263 | } | |
264 | } | |
265 | ||
266 | fn check_start_fn_ty(ccx: &CrateCtxt, | |
267 | start_id: ast::NodeId, | |
268 | start_span: Span) { | |
269 | let tcx = ccx.tcx; | |
c1a9b12d | 270 | let start_t = tcx.node_id_to_type(start_id); |
1a4d82fc | 271 | match start_t.sty { |
54a0048b | 272 | ty::TyFnDef(..) => { |
1a4d82fc | 273 | match tcx.map.find(start_id) { |
e9174d1e | 274 | Some(hir_map::NodeItem(it)) => { |
1a4d82fc | 275 | match it.node { |
e9174d1e | 276 | hir::ItemFn(_,_,_,_,ref ps,_) |
1a4d82fc JJ |
277 | if ps.is_parameterized() => { |
278 | span_err!(tcx.sess, start_span, E0132, | |
279 | "start function is not allowed to have type parameters"); | |
280 | return; | |
281 | } | |
282 | _ => () | |
283 | } | |
284 | } | |
285 | _ => () | |
286 | } | |
287 | ||
54a0048b SL |
288 | let start_def_id = ccx.tcx.map.local_def_id(start_id); |
289 | let substs = tcx.mk_substs(Substs::empty()); | |
290 | let se_ty = tcx.mk_fn_def(start_def_id, substs, ty::BareFnTy { | |
e9174d1e | 291 | unsafety: hir::Unsafety::Normal, |
7453a54e | 292 | abi: Abi::Rust, |
1a4d82fc JJ |
293 | sig: ty::Binder(ty::FnSig { |
294 | inputs: vec!( | |
c34b1796 | 295 | tcx.types.isize, |
c1a9b12d | 296 | tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) |
1a4d82fc | 297 | ), |
c34b1796 | 298 | output: ty::FnConverging(tcx.types.isize), |
1a4d82fc JJ |
299 | variadic: false, |
300 | }), | |
54a0048b | 301 | }); |
1a4d82fc JJ |
302 | |
303 | require_same_types(tcx, None, false, start_span, start_t, se_ty, | |
304 | || { | |
305 | format!("start function expects type: `{}`", | |
62682a34 | 306 | se_ty) |
1a4d82fc JJ |
307 | }); |
308 | ||
309 | } | |
310 | _ => { | |
54a0048b SL |
311 | span_bug!(start_span, |
312 | "start has a non-function type: found `{}`", | |
313 | start_t); | |
1a4d82fc JJ |
314 | } |
315 | } | |
316 | } | |
317 | ||
318 | fn check_for_entry_fn(ccx: &CrateCtxt) { | |
319 | let tcx = ccx.tcx; | |
7453a54e | 320 | let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn); |
1a4d82fc JJ |
321 | match *tcx.sess.entry_fn.borrow() { |
322 | Some((id, sp)) => match tcx.sess.entry_type.get() { | |
323 | Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp), | |
324 | Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp), | |
325 | Some(config::EntryNone) => {} | |
54a0048b | 326 | None => bug!("entry function without a type") |
1a4d82fc JJ |
327 | }, |
328 | None => {} | |
329 | } | |
330 | } | |
331 | ||
54a0048b | 332 | pub fn check_crate(tcx: &TyCtxt, trait_map: hir::TraitMap) -> CompileResult { |
1a4d82fc JJ |
333 | let time_passes = tcx.sess.time_passes(); |
334 | let ccx = CrateCtxt { | |
335 | trait_map: trait_map, | |
85aaf69f | 336 | all_traits: RefCell::new(None), |
1a4d82fc JJ |
337 | tcx: tcx |
338 | }; | |
339 | ||
1a4d82fc JJ |
340 | // this ensures that later parts of type checking can assume that items |
341 | // have valid types and not error | |
54a0048b | 342 | tcx.sess.track_errors(|| { |
9cc50fc6 SL |
343 | time(time_passes, "type collecting", || |
344 | collect::collect_item_types(tcx)); | |
345 | ||
54a0048b | 346 | })?; |
1a4d82fc | 347 | |
e9174d1e | 348 | time(time_passes, "variance inference", || |
1a4d82fc JJ |
349 | variance::infer_variance(tcx)); |
350 | ||
54a0048b | 351 | tcx.sess.track_errors(|| { |
9cc50fc6 SL |
352 | time(time_passes, "coherence checking", || |
353 | coherence::check_coherence(&ccx)); | |
54a0048b | 354 | })?; |
1a4d82fc | 355 | |
54a0048b | 356 | time(time_passes, "wf checking", || check::check_wf_new(&ccx))?; |
e9174d1e | 357 | |
54a0048b | 358 | time(time_passes, "item-types checking", || check::check_item_types(&ccx))?; |
1a4d82fc | 359 | |
54a0048b | 360 | time(time_passes, "item-bodies checking", || check::check_item_bodies(&ccx))?; |
e9174d1e | 361 | |
54a0048b | 362 | time(time_passes, "drop-impl checking", || check::check_drop_impls(&ccx))?; |
e9174d1e | 363 | |
1a4d82fc | 364 | check_for_entry_fn(&ccx); |
7453a54e SL |
365 | |
366 | let err_count = tcx.sess.err_count(); | |
367 | if err_count == 0 { | |
368 | Ok(()) | |
369 | } else { | |
370 | Err(err_count) | |
371 | } | |
1a4d82fc | 372 | } |
d9579d0f | 373 | |
d9579d0f | 374 | __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS } |