]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/lib.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_typeck / lib.rs
CommitLineData
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
13typeck.rs, an introduction
14
15The type checker is responsible for:
16
171. Determining the type of each expression
182. Resolving methods and traits
193. Guaranteeing that most type rules are met ("most?", you say, "why most?"
20 Well, dear reader, read on)
21
22The main entry point is `check_crate()`. Type checking operates in
23several major phases:
24
251. The collect phase first passes over all items and determines their
26 type, without examining their "innards".
27
282. Variance inference then runs to compute the variance of each parameter
29
303. Coherence checks for overlapping or orphaned impls
31
324. 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
40The type checker is defined into various submodules which are documented
41independently:
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
62This 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
89extern crate arena;
85aaf69f 90extern crate fmt_macros;
54a0048b 91#[macro_use] extern crate rustc;
e9174d1e 92extern crate rustc_platform_intrinsics as intrinsics;
b039eaaf 93extern crate rustc_back;
54a0048b
SL
94extern crate rustc_const_math;
95extern crate rustc_const_eval;
1a4d82fc 96
9cc50fc6 97pub use rustc::dep_graph;
54a0048b 98pub use rustc::hir;
1a4d82fc 99pub use rustc::lint;
1a4d82fc
JJ
100pub use rustc::middle;
101pub use rustc::session;
102pub use rustc::util;
103
7453a54e 104use dep_graph::DepNode;
54a0048b
SL
105use hir::map as hir_map;
106use hir::def::Def;
107use rustc::infer::{self, TypeOrigin};
108use rustc::ty::subst::Substs;
109use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
110use rustc::traits::ProjectionMode;
7453a54e 111use session::{config, CompileResult};
1a4d82fc 112use util::common::time;
1a4d82fc
JJ
113
114use syntax::codemap::Span;
7453a54e
SL
115use syntax::ast;
116use syntax::abi::Abi;
1a4d82fc 117
85aaf69f
SL
118use std::cell::RefCell;
119
120// NB: This module needs to be declared first so diagnostics are
121// registered before they are used.
122pub mod diagnostics;
123
62682a34 124pub mod check;
1a4d82fc
JJ
125mod rscope;
126mod astconv;
62682a34 127pub mod collect;
85aaf69f 128mod constrained_type_params;
62682a34
SL
129pub mod coherence;
130pub mod variance;
1a4d82fc 131
c34b1796 132pub struct TypeAndSubsts<'tcx> {
54a0048b 133 pub substs: Substs<'tcx>,
1a4d82fc
JJ
134 pub ty: Ty<'tcx>,
135}
136
c34b1796 137pub 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 149fn 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 155fn 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 169fn 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 178fn 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 188fn 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
219fn 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
266fn 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
318fn 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 332pub 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 }