]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Check namespaces when resolving associated items in typeck
[rust.git] / src / librustc_typeck / lib.rs
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 `tcx.types` 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 */
65
66 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
67       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
68       html_root_url = "https://doc.rust-lang.org/nightly/")]
69 #![deny(warnings)]
70
71 #![allow(non_camel_case_types)]
72
73 #![feature(advanced_slice_patterns)]
74 #![feature(box_patterns)]
75 #![feature(box_syntax)]
76 #![feature(conservative_impl_trait)]
77 #![feature(never_type)]
78 #![feature(quote)]
79 #![feature(rustc_diagnostic_macros)]
80 #![feature(slice_patterns)]
81
82 #[macro_use] extern crate log;
83 #[macro_use] extern crate syntax;
84 extern crate syntax_pos;
85
86 extern crate arena;
87 #[macro_use] extern crate rustc;
88 extern crate rustc_platform_intrinsics as intrinsics;
89 extern crate rustc_back;
90 extern crate rustc_const_math;
91 extern crate rustc_data_structures;
92 extern crate rustc_errors as errors;
93
94 use rustc::hir;
95 use rustc::lint;
96 use rustc::middle;
97 use rustc::session;
98 use rustc::util;
99
100 use hir::map as hir_map;
101 use rustc::infer::InferOk;
102 use rustc::ty::subst::Substs;
103 use rustc::ty::{self, Ty, TyCtxt};
104 use rustc::ty::maps::Providers;
105 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
106 use session::{CompileIncomplete, config};
107 use util::common::time;
108
109 use syntax::ast;
110 use syntax::abi::Abi;
111 use syntax_pos::Span;
112
113 use std::iter;
114 // NB: This module needs to be declared first so diagnostics are
115 // registered before they are used.
116 mod diagnostics;
117
118 mod check;
119 mod check_unused;
120 mod astconv;
121 mod collect;
122 mod constrained_type_params;
123 mod impl_wf_check;
124 mod coherence;
125 mod variance;
126 mod namespace;
127
128 pub struct TypeAndSubsts<'tcx> {
129     substs: &'tcx Substs<'tcx>,
130     ty: Ty<'tcx>,
131 }
132
133 fn require_c_abi_if_variadic(tcx: TyCtxt,
134                              decl: &hir::FnDecl,
135                              abi: Abi,
136                              span: Span) {
137     if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
138         let mut err = struct_span_err!(tcx.sess, span, E0045,
139                   "variadic function must have C or cdecl calling convention");
140         err.span_label(span, "variadics require C or cdecl calling convention").emit();
141     }
142 }
143
144 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
145                                 cause: &ObligationCause<'tcx>,
146                                 expected: Ty<'tcx>,
147                                 actual: Ty<'tcx>)
148                                 -> bool {
149     tcx.infer_ctxt().enter(|ref infcx| {
150         let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
151         let mut fulfill_cx = FulfillmentContext::new();
152         match infcx.at(&cause, param_env).eq(expected, actual) {
153             Ok(InferOk { obligations, .. }) => {
154                 fulfill_cx.register_predicate_obligations(infcx, obligations);
155             }
156             Err(err) => {
157                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
158                 return false;
159             }
160         }
161
162         match fulfill_cx.select_all_or_error(infcx) {
163             Ok(()) => true,
164             Err(errors) => {
165                 infcx.report_fulfillment_errors(&errors, None);
166                 false
167             }
168         }
169     })
170 }
171
172 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
173                               main_id: ast::NodeId,
174                               main_span: Span) {
175     let main_def_id = tcx.hir.local_def_id(main_id);
176     let main_t = tcx.type_of(main_def_id);
177     match main_t.sty {
178         ty::TyFnDef(..) => {
179             match tcx.hir.find(main_id) {
180                 Some(hir_map::NodeItem(it)) => {
181                     match it.node {
182                         hir::ItemFn(.., ref generics, _) => {
183                             if generics.is_parameterized() {
184                                 struct_span_err!(tcx.sess, generics.span, E0131,
185                                          "main function is not allowed to have type parameters")
186                                     .span_label(generics.span,
187                                                 "main cannot have type parameters")
188                                     .emit();
189                                 return;
190                             }
191                         }
192                         _ => ()
193                     }
194                 }
195                 _ => ()
196             }
197             let se_ty = tcx.mk_fn_ptr(ty::Binder(
198                 tcx.mk_fn_sig(
199                     iter::empty(),
200                     tcx.mk_nil(),
201                     false,
202                     hir::Unsafety::Normal,
203                     Abi::Rust
204                 )
205             ));
206
207             require_same_types(
208                 tcx,
209                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
210                 se_ty,
211                 tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
212         }
213         _ => {
214             span_bug!(main_span,
215                       "main has a non-function type: found `{}`",
216                       main_t);
217         }
218     }
219 }
220
221 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
222                                start_id: ast::NodeId,
223                                start_span: Span) {
224     let start_def_id = tcx.hir.local_def_id(start_id);
225     let start_t = tcx.type_of(start_def_id);
226     match start_t.sty {
227         ty::TyFnDef(..) => {
228             match tcx.hir.find(start_id) {
229                 Some(hir_map::NodeItem(it)) => {
230                     match it.node {
231                         hir::ItemFn(..,ref ps,_)
232                         if ps.is_parameterized() => {
233                             struct_span_err!(tcx.sess, ps.span, E0132,
234                                 "start function is not allowed to have type parameters")
235                                 .span_label(ps.span,
236                                             "start function cannot have type parameters")
237                                 .emit();
238                             return;
239                         }
240                         _ => ()
241                     }
242                 }
243                 _ => ()
244             }
245
246             let se_ty = tcx.mk_fn_ptr(ty::Binder(
247                 tcx.mk_fn_sig(
248                     [
249                         tcx.types.isize,
250                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
251                     ].iter().cloned(),
252                     tcx.types.isize,
253                     false,
254                     hir::Unsafety::Normal,
255                     Abi::Rust
256                 )
257             ));
258
259             require_same_types(
260                 tcx,
261                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
262                 se_ty,
263                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
264         }
265         _ => {
266             span_bug!(start_span,
267                       "start has a non-function type: found `{}`",
268                       start_t);
269         }
270     }
271 }
272
273 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
274     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
275         match tcx.sess.entry_type.get() {
276             Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
277             Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
278             Some(config::EntryNone) => {}
279             None => bug!("entry function without a type")
280         }
281     }
282 }
283
284 pub fn provide(providers: &mut Providers) {
285     collect::provide(providers);
286     coherence::provide(providers);
287     check::provide(providers);
288     variance::provide(providers);
289 }
290
291 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
292                              -> Result<(), CompileIncomplete>
293 {
294     let time_passes = tcx.sess.time_passes();
295
296     // this ensures that later parts of type checking can assume that items
297     // have valid types and not error
298     tcx.sess.track_errors(|| {
299         time(time_passes, "type collecting", ||
300              collect::collect_item_types(tcx));
301
302     })?;
303
304     tcx.sess.track_errors(|| {
305         time(time_passes, "impl wf inference", ||
306              impl_wf_check::impl_wf_check(tcx));
307     })?;
308
309     tcx.sess.track_errors(|| {
310       time(time_passes, "coherence checking", ||
311           coherence::check_coherence(tcx));
312     })?;
313
314     tcx.sess.track_errors(|| {
315         time(time_passes, "variance testing", ||
316              variance::test::test_variance(tcx));
317     })?;
318
319     time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
320
321     time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
322
323     time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
324
325     check_unused::check_crate(tcx);
326     check_for_entry_fn(tcx);
327
328     tcx.sess.compile_status()
329 }
330
331 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
332 /// the type from a HIR node.
333 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
334     // In case there are any projections etc, find the "environment"
335     // def-id that will be used to determine the traits/predicates in
336     // scope.  This is derived from the enclosing item-like thing.
337     let env_node_id = tcx.hir.get_parent(hir_ty.id);
338     let env_def_id = tcx.hir.local_def_id(env_node_id);
339     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
340     item_cx.to_ty(hir_ty)
341 }
342
343 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }