]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/mod.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / librustc_typeck / check / mod.rs
CommitLineData
85aaf69f 1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
1a4d82fc
JJ
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# check.rs
14
15Within the check phase of type check, we check each item one at a time
16(bodies of function expressions are checked as part of the containing
17function). Inference is used to supply types wherever they are
18unknown.
19
20By far the most complex case is checking the body of a function. This
21can be broken down into several distinct phases:
22
23- gather: creates type variables to represent the type of each local
24 variable and pattern binding.
25
26- main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
31
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `infer` module is in charge
35 of resolving those constraints.
36
37- regionck: after main is complete, the regionck pass goes over all
38 types looking for regions and making sure that they did not escape
39 into places they are not in scope. This may also influence the
40 final assignments of the various region variables if there is some
41 flexibility.
42
43- vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
45
46- writeback: writes the final types within a function body, replacing
47 type variables with their final inferred types. These final types
48 are written into the `tcx.node_types` table, which should *never* contain
49 any reference to a type variable.
50
51## Intermediate types
52
53While type checking a function, the intermediate types for the
54expressions, blocks, and so forth contained within the function are
55stored in `fcx.node_types` and `fcx.item_substs`. These types
56may contain unresolved type variables. After type checking is
57complete, the functions in the writeback module are used to take the
58types from this table, resolve them, and then write them into their
59permanent home in the type context `ccx.tcx`.
60
61This means that during inferencing you should use `fcx.write_ty()`
62and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63nodes within the function.
64
65The types of top-level items, which never contain unbound type
66variables, are stored directly into the `tcx` tables.
67
68n.b.: A type variable is not the same thing as a type parameter. A
69type variable is rather an "instance" of a type parameter: that is,
70given a generic function `fn foo<T>(t: T)`: while checking the
71function `foo`, the type `ty_param(0)` refers to the type `T`, which
72is treated in abstract. When `foo()` is called, however, `T` will be
73substituted for a fresh type variable `N`. This variable will
74eventually be resolved to some concrete type (which might itself be
75type parameter).
76
77*/
78
79pub use self::LvaluePreference::*;
80pub use self::Expectation::*;
d9579d0f 81pub use self::compare_method::{compare_impl_method, compare_const_impl};
1a4d82fc
JJ
82use self::TupleArgumentsFlag::*;
83
c34b1796 84use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
1a4d82fc 85use check::_match::pat_ctxt;
85aaf69f 86use fmt_macros::{Parser, Piece, Position};
c34b1796
AL
87use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
88use middle::def;
1a4d82fc 89use middle::infer;
1a4d82fc
JJ
90use middle::mem_categorization as mc;
91use middle::mem_categorization::McResult;
92use middle::pat_util::{self, pat_id_map};
c34b1796 93use middle::privacy::{AllPublic, LastMod};
85aaf69f 94use middle::region::{self, CodeExtent};
1a4d82fc 95use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
d9579d0f 96use middle::traits::{self, report_fulfillment_errors};
c34b1796 97use middle::ty::{FnSig, GenericPredicates, TypeScheme};
1a4d82fc 98use middle::ty::{Disr, ParamTy, ParameterEnvironment};
c34b1796 99use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
1a4d82fc 100use middle::ty::liberate_late_bound_regions;
62682a34 101use middle::ty::{MethodCall, MethodCallee, MethodMap};
1a4d82fc
JJ
102use middle::ty_fold::{TypeFolder, TypeFoldable};
103use rscope::RegionScope;
104use session::Session;
c34b1796 105use {CrateCtxt, lookup_full_def, require_same_types};
1a4d82fc 106use TypeAndSubsts;
1a4d82fc 107use lint;
c34b1796 108use util::common::{block_query, ErrorReported, indenter, loop_query};
1a4d82fc 109use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
85aaf69f 110use util::lev_distance::lev_distance;
1a4d82fc
JJ
111
112use std::cell::{Cell, Ref, RefCell};
113use std::mem::replace;
1a4d82fc 114use std::iter::repeat;
85aaf69f 115use std::slice;
1a4d82fc 116use syntax::{self, abi, attr};
85aaf69f 117use syntax::attr::AttrMetaMethods;
c34b1796
AL
118use syntax::ast::{self, DefId, Visibility};
119use syntax::ast_util::{self, local_def};
1a4d82fc 120use syntax::codemap::{self, Span};
c34b1796 121use syntax::feature_gate;
1a4d82fc
JJ
122use syntax::owned_slice::OwnedSlice;
123use syntax::parse::token;
124use syntax::print::pprust;
125use syntax::ptr::P;
126use syntax::visit::{self, Visitor};
127
128mod assoc;
85aaf69f 129pub mod dropck;
1a4d82fc 130pub mod _match;
1a4d82fc 131pub mod writeback;
1a4d82fc 132pub mod regionck;
85aaf69f 133pub mod coercion;
1a4d82fc
JJ
134pub mod demand;
135pub mod method;
136mod upvar;
137pub mod wf;
9346a6ac 138mod cast;
1a4d82fc
JJ
139mod closure;
140mod callee;
85aaf69f 141mod compare_method;
c34b1796 142mod op;
1a4d82fc 143
1a4d82fc
JJ
144/// closures defined within the function. For example:
145///
146/// fn foo() {
147/// bar(move|| { ... })
148/// }
149///
150/// Here, the function `foo()` and the closure passed to
151/// `bar()` will each have their own `FnCtxt`, but they will
152/// share the inherited fields.
153pub struct Inherited<'a, 'tcx: 'a> {
154 infcx: infer::InferCtxt<'a, 'tcx>,
155 locals: RefCell<NodeMap<Ty<'tcx>>>,
156 param_env: ty::ParameterEnvironment<'a, 'tcx>,
157
158 // Temporary tables:
159 node_types: RefCell<NodeMap<Ty<'tcx>>>,
160 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
161 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
162 method_map: MethodMap<'tcx>,
85aaf69f
SL
163 upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
164 closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
165 closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
1a4d82fc
JJ
166
167 // A mapping from each fn's id to its signature, with all bound
168 // regions replaced with free ones. Unlike the other tables, this
169 // one is never copied into the tcx: it is only used by regionck.
170 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
171
172 // Tracks trait obligations incurred during this function body.
173 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
85aaf69f
SL
174
175 // When we process a call like `c()` where `c` is a closure type,
176 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
177 // `FnOnce` closure. In that case, we defer full resolution of the
178 // call until upvar inference can kick in and make the
179 // decision. We keep these deferred resolutions grouped by the
180 // def-id of the closure, so that once we decide, we can easily go
181 // back and process them.
182 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
c34b1796 183
9346a6ac 184 deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
85aaf69f
SL
185}
186
187trait DeferredCallResolution<'tcx> {
188 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
1a4d82fc
JJ
189}
190
85aaf69f
SL
191type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
192
1a4d82fc
JJ
193/// When type-checking an expression, we propagate downward
194/// whatever type hint we are able in the form of an `Expectation`.
62682a34 195#[derive(Copy, Clone, Debug)]
c34b1796 196pub enum Expectation<'tcx> {
1a4d82fc
JJ
197 /// We know nothing about what type this expression should have.
198 NoExpectation,
199
200 /// This expression should have the type given (or some subtype)
201 ExpectHasType(Ty<'tcx>),
202
203 /// This expression will be cast to the `Ty`
204 ExpectCastableToType(Ty<'tcx>),
205
206 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
207 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
208 ExpectRvalueLikeUnsized(Ty<'tcx>),
209}
210
211impl<'tcx> Expectation<'tcx> {
212 // Disregard "castable to" expectations because they
213 // can lead us astray. Consider for example `if cond
214 // {22} else {c} as u8` -- if we propagate the
215 // "castable to u8" constraint to 22, it will pick the
216 // type 22u8, which is overly constrained (c might not
217 // be a u8). In effect, the problem is that the
218 // "castable to" expectation is not the tightest thing
219 // we can say, so we want to drop it in this case.
220 // The tightest thing we can say is "must unify with
221 // else branch". Note that in the case of a "has type"
222 // constraint, this limitation does not hold.
223
224 // If the expected type is just a type variable, then don't use
225 // an expected type. Otherwise, we might write parts of the type
226 // when checking the 'then' block which are incompatible with the
227 // 'else' branch.
228 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
229 match *self {
230 ExpectHasType(ety) => {
231 let ety = fcx.infcx().shallow_resolve(ety);
232 if !ty::type_is_ty_var(ety) {
233 ExpectHasType(ety)
234 } else {
235 NoExpectation
236 }
237 }
238 ExpectRvalueLikeUnsized(ety) => {
239 ExpectRvalueLikeUnsized(ety)
240 }
241 _ => NoExpectation
242 }
243 }
244}
245
246#[derive(Copy, Clone)]
247pub struct UnsafetyState {
248 pub def: ast::NodeId,
249 pub unsafety: ast::Unsafety,
250 from_fn: bool
251}
252
253impl UnsafetyState {
254 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
255 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
256 }
257
258 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
259 match self.unsafety {
260 // If this unsafe, then if the outer function was already marked as
261 // unsafe we shouldn't attribute the unsafe'ness to the block. This
262 // way the block can be warned about instead of ignoring this
263 // extraneous block (functions are never warned about).
264 ast::Unsafety::Unsafe if self.from_fn => *self,
265
266 unsafety => {
267 let (unsafety, def) = match blk.rules {
268 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
269 ast::DefaultBlock => (unsafety, self.def),
270 };
271 UnsafetyState{ def: def,
272 unsafety: unsafety,
273 from_fn: false }
274 }
275 }
276 }
277}
278
1a4d82fc
JJ
279#[derive(Clone)]
280pub struct FnCtxt<'a, 'tcx: 'a> {
281 body_id: ast::NodeId,
282
283 // This flag is set to true if, during the writeback phase, we encounter
284 // a type error in this function.
285 writeback_errors: Cell<bool>,
286
287 // Number of errors that had been reported when we started
288 // checking this function. On exit, if we find that *more* errors
289 // have been reported, we will skip regionck and other work that
290 // expects the types within the function to be consistent.
c34b1796 291 err_count_on_creation: usize,
1a4d82fc
JJ
292
293 ret_ty: ty::FnOutput<'tcx>,
294
295 ps: RefCell<UnsafetyState>,
296
297 inh: &'a Inherited<'a, 'tcx>,
298
299 ccx: &'a CrateCtxt<'a, 'tcx>,
300}
301
302impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
1a4d82fc
JJ
303 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
304 let ty = self.node_ty(id);
305 self.resolve_type_vars_or_error(&ty)
306 }
307 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
308 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
309 self.resolve_type_vars_or_error(&ty)
310 }
311 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
312 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
85aaf69f 313 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
1a4d82fc
JJ
314 }
315 fn node_method_ty(&self, method_call: ty::MethodCall)
316 -> Option<Ty<'tcx>> {
317 self.inh.method_map.borrow()
318 .get(&method_call)
319 .map(|method| method.ty)
320 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
321 }
322 fn node_method_origin(&self, method_call: ty::MethodCall)
323 -> Option<ty::MethodOrigin<'tcx>>
324 {
325 self.inh.method_map.borrow()
326 .get(&method_call)
327 .map(|method| method.origin.clone())
328 }
329 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
330 &self.inh.adjustments
331 }
332 fn is_method_call(&self, id: ast::NodeId) -> bool {
333 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
334 }
335 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
336 self.param_env().temporary_scope(rvalue_id)
337 }
85aaf69f
SL
338 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
339 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
1a4d82fc
JJ
340 }
341}
342
85aaf69f 343impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
1a4d82fc
JJ
344 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
345 &self.inh.param_env
346 }
347
85aaf69f
SL
348 fn closure_kind(&self,
349 def_id: ast::DefId)
350 -> Option<ty::ClosureKind>
1a4d82fc 351 {
85aaf69f 352 self.inh.closure_kinds.borrow().get(&def_id).cloned()
1a4d82fc
JJ
353 }
354
85aaf69f
SL
355 fn closure_type(&self,
356 def_id: ast::DefId,
357 substs: &subst::Substs<'tcx>)
358 -> ty::ClosureTy<'tcx>
1a4d82fc 359 {
c34b1796 360 self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs)
1a4d82fc
JJ
361 }
362
85aaf69f
SL
363 fn closure_upvars(&self,
364 def_id: ast::DefId,
365 substs: &Substs<'tcx>)
366 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
1a4d82fc 367 {
85aaf69f 368 ty::closure_upvars(self, def_id, substs)
1a4d82fc
JJ
369 }
370}
371
372impl<'a, 'tcx> Inherited<'a, 'tcx> {
373 fn new(tcx: &'a ty::ctxt<'tcx>,
374 param_env: ty::ParameterEnvironment<'a, 'tcx>)
375 -> Inherited<'a, 'tcx> {
376 Inherited {
377 infcx: infer::new_infer_ctxt(tcx),
85aaf69f 378 locals: RefCell::new(NodeMap()),
1a4d82fc 379 param_env: param_env,
85aaf69f
SL
380 node_types: RefCell::new(NodeMap()),
381 item_substs: RefCell::new(NodeMap()),
382 adjustments: RefCell::new(NodeMap()),
383 method_map: RefCell::new(FnvHashMap()),
85aaf69f
SL
384 upvar_capture_map: RefCell::new(FnvHashMap()),
385 closure_tys: RefCell::new(DefIdMap()),
386 closure_kinds: RefCell::new(DefIdMap()),
387 fn_sig_map: RefCell::new(NodeMap()),
62682a34 388 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
85aaf69f 389 deferred_call_resolutions: RefCell::new(DefIdMap()),
c34b1796 390 deferred_cast_checks: RefCell::new(Vec::new()),
1a4d82fc
JJ
391 }
392 }
393
394 fn normalize_associated_types_in<T>(&self,
85aaf69f 395 typer: &ty::ClosureTyper<'tcx>,
1a4d82fc
JJ
396 span: Span,
397 body_id: ast::NodeId,
398 value: &T)
399 -> T
62682a34 400 where T : TypeFoldable<'tcx> + HasProjectionTypes
1a4d82fc
JJ
401 {
402 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
403 assoc::normalize_associated_types_in(&self.infcx,
404 typer,
405 &mut *fulfillment_cx, span,
406 body_id,
407 value)
408 }
409
410}
411
412// Used by check_const and check_enum_variants
413pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
414 inh: &'a Inherited<'a, 'tcx>,
415 rty: ty::FnOutput<'tcx>,
416 body_id: ast::NodeId)
417 -> FnCtxt<'a, 'tcx> {
418 FnCtxt {
419 body_id: body_id,
420 writeback_errors: Cell::new(false),
421 err_count_on_creation: ccx.tcx.sess.err_count(),
422 ret_ty: rty,
423 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
424 inh: inh,
425 ccx: ccx
426 }
427}
428
429fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
430 -> Inherited<'a, 'tcx> {
431 // It's kind of a kludge to manufacture a fake function context
432 // and statement context, but we might as well do write the code only once
433 let param_env = ty::empty_parameter_environment(ccx.tcx);
434 Inherited::new(ccx.tcx, param_env)
435}
436
437struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
9346a6ac 438struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
1a4d82fc 439
85aaf69f
SL
440impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
441 fn visit_item(&mut self, i: &'tcx ast::Item) {
9346a6ac 442 check_item_type(self.ccx, i);
1a4d82fc
JJ
443 visit::walk_item(self, i);
444 }
445
85aaf69f 446 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
1a4d82fc
JJ
447 match t.node {
448 ast::TyFixedLengthVec(_, ref expr) => {
c34b1796 449 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
1a4d82fc
JJ
450 }
451 _ => {}
452 }
453
454 visit::walk_ty(self, t);
455 }
456}
457
9346a6ac
AL
458impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
459 fn visit_item(&mut self, i: &'tcx ast::Item) {
460 check_item_body(self.ccx, i);
461 visit::walk_item(self, i);
462 }
463}
464
1a4d82fc
JJ
465pub fn check_item_types(ccx: &CrateCtxt) {
466 let krate = ccx.tcx.map.krate();
467 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
468 visit::walk_crate(&mut visit, krate);
469
470 // If types are not well-formed, it leads to all manner of errors
471 // downstream, so stop reporting errors at this point.
472 ccx.tcx.sess.abort_if_errors();
473
474 let mut visit = CheckItemTypesVisitor { ccx: ccx };
475 visit::walk_crate(&mut visit, krate);
476
477 ccx.tcx.sess.abort_if_errors();
c34b1796 478
9346a6ac
AL
479 let mut visit = CheckItemBodiesVisitor { ccx: ccx };
480 visit::walk_crate(&mut visit, krate);
481
482 ccx.tcx.sess.abort_if_errors();
483
c34b1796
AL
484 for drop_method_did in ccx.tcx.destructors.borrow().iter() {
485 if drop_method_did.krate == ast::LOCAL_CRATE {
486 let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
487 match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
488 Ok(()) => {}
489 Err(()) => {
490 assert!(ccx.tcx.sess.has_errors());
491 }
492 }
493 }
494 }
495
496 ccx.tcx.sess.abort_if_errors();
1a4d82fc
JJ
497}
498
499fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
500 decl: &'tcx ast::FnDecl,
501 body: &'tcx ast::Block,
502 fn_id: ast::NodeId,
503 fn_span: Span,
1a4d82fc 504 raw_fty: Ty<'tcx>,
85aaf69f
SL
505 param_env: ty::ParameterEnvironment<'a, 'tcx>)
506{
1a4d82fc 507 match raw_fty.sty {
62682a34 508 ty::TyBareFn(_, ref fn_ty) => {
1a4d82fc
JJ
509 let inh = Inherited::new(ccx.tcx, param_env);
510
511 // Compute the fty from point of view of inside fn.
512 let fn_sig =
513 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
514 let fn_sig =
85aaf69f
SL
515 liberate_late_bound_regions(ccx.tcx,
516 region::DestructionScopeData::new(body.id),
517 &fn_sig);
1a4d82fc
JJ
518 let fn_sig =
519 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
520
85aaf69f
SL
521 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
522 decl, fn_id, body, &inh);
1a4d82fc 523
d9579d0f 524 fcx.select_all_obligations_and_apply_defaults();
85aaf69f 525 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
d9579d0f 526 fcx.select_all_obligations_or_error();
c34b1796 527 fcx.check_casts();
62682a34
SL
528
529 fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
530
85aaf69f 531 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
1a4d82fc
JJ
532 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
533 }
534 _ => ccx.tcx.sess.impossible_case(body.span,
535 "check_bare_fn: function type expected")
536 }
537}
538
539struct GatherLocalsVisitor<'a, 'tcx: 'a> {
540 fcx: &'a FnCtxt<'a, 'tcx>
541}
542
543impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
544 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
545 match ty_opt {
546 None => {
547 // infer the variable's type
548 let var_ty = self.fcx.infcx().next_ty_var();
549 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
550 var_ty
551 }
552 Some(typ) => {
553 // take type that the user specified
554 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
555 typ
556 }
557 }
558 }
559}
560
85aaf69f 561impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
1a4d82fc 562 // Add explicitly-declared locals.
85aaf69f 563 fn visit_local(&mut self, local: &'tcx ast::Local) {
1a4d82fc
JJ
564 let o_ty = match local.ty {
565 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
566 None => None
567 };
568 self.assign(local.span, local.id, o_ty);
62682a34
SL
569 debug!("Local variable {:?} is assigned type {}",
570 local.pat,
1a4d82fc 571 self.fcx.infcx().ty_to_string(
c34b1796 572 self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
1a4d82fc
JJ
573 visit::walk_local(self, local);
574 }
575
576 // Add pattern bindings.
85aaf69f 577 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
1a4d82fc
JJ
578 if let ast::PatIdent(_, ref path1, _) = p.node {
579 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
580 let var_ty = self.assign(p.span, p.id, None);
581
582 self.fcx.require_type_is_sized(var_ty, p.span,
583 traits::VariableType(p.id));
584
62682a34 585 debug!("Pattern binding {} is assigned to {} with type {:?}",
1a4d82fc
JJ
586 token::get_ident(path1.node),
587 self.fcx.infcx().ty_to_string(
c34b1796 588 self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
62682a34 589 var_ty);
1a4d82fc
JJ
590 }
591 }
592 visit::walk_pat(self, p);
593 }
594
85aaf69f 595 fn visit_block(&mut self, b: &'tcx ast::Block) {
1a4d82fc
JJ
596 // non-obvious: the `blk` variable maps to region lb, so
597 // we have to keep this up-to-date. This
598 // is... unfortunate. It'd be nice to not need this.
599 visit::walk_block(self, b);
600 }
601
602 // Since an expr occurs as part of the type fixed size arrays we
603 // need to record the type for that node
85aaf69f 604 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
1a4d82fc
JJ
605 match t.node {
606 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
607 self.visit_ty(&**ty);
c34b1796 608 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
1a4d82fc
JJ
609 }
610 _ => visit::walk_ty(self, t)
611 }
612 }
613
614 // Don't descend into fns and items
85aaf69f
SL
615 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
616 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
1a4d82fc
JJ
617 fn visit_item(&mut self, _: &ast::Item) { }
618
619}
620
621/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
622/// body and returns the function context used for that purpose, since in the case of a fn item
623/// there is still a bit more to do.
624///
625/// * ...
626/// * inherited: other fields inherited from the enclosing fn (if any)
627fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
628 unsafety: ast::Unsafety,
629 unsafety_id: ast::NodeId,
630 fn_sig: &ty::FnSig<'tcx>,
85aaf69f 631 decl: &'tcx ast::FnDecl,
1a4d82fc 632 fn_id: ast::NodeId,
85aaf69f 633 body: &'tcx ast::Block,
1a4d82fc
JJ
634 inherited: &'a Inherited<'a, 'tcx>)
635 -> FnCtxt<'a, 'tcx>
636{
637 let tcx = ccx.tcx;
638 let err_count_on_creation = tcx.sess.err_count();
639
c34b1796 640 let arg_tys = &fn_sig.inputs;
1a4d82fc
JJ
641 let ret_ty = fn_sig.output;
642
62682a34
SL
643 debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
644 arg_tys,
645 ret_ty,
1a4d82fc
JJ
646 fn_id);
647
648 // Create the function context. This is either derived from scratch or,
649 // in the case of function expressions, based on the outer context.
650 let fcx = FnCtxt {
651 body_id: body.id,
652 writeback_errors: Cell::new(false),
653 err_count_on_creation: err_count_on_creation,
654 ret_ty: ret_ty,
655 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
656 inh: inherited,
657 ccx: ccx
658 };
659
660 // Remember return type so that regionck can access it later.
661 let mut fn_sig_tys: Vec<Ty> =
662 arg_tys.iter()
85aaf69f 663 .cloned()
1a4d82fc
JJ
664 .collect();
665
666 if let ty::FnConverging(ret_ty) = ret_ty {
667 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
668 fn_sig_tys.push(ret_ty);
669 }
670
62682a34 671 debug!("fn-sig-map: fn_id={} fn_sig_tys={:?}",
1a4d82fc 672 fn_id,
62682a34 673 fn_sig_tys);
1a4d82fc
JJ
674
675 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
676
677 {
678 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
679
680 // Add formal parameters.
62682a34 681 for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
1a4d82fc
JJ
682 // Create type variables for each argument.
683 pat_util::pat_bindings(
684 &tcx.def_map,
685 &*input.pat,
686 |_bm, pat_id, sp, _path| {
687 let var_ty = visit.assign(sp, pat_id, None);
688 fcx.require_type_is_sized(var_ty, sp,
689 traits::VariableType(pat_id));
690 });
691
692 // Check the pattern.
693 let pcx = pat_ctxt {
694 fcx: &fcx,
695 map: pat_id_map(&tcx.def_map, &*input.pat),
696 };
697 _match::check_pat(&pcx, &*input.pat, *arg_ty);
698 }
699
700 visit.visit_block(body);
701 }
702
703 check_block_with_expected(&fcx, body, match ret_ty {
704 ty::FnConverging(result_type) => ExpectHasType(result_type),
705 ty::FnDiverging => NoExpectation
706 });
707
62682a34
SL
708 for (input, arg) in decl.inputs.iter().zip(arg_tys) {
709 fcx.write_ty(input.id, arg);
1a4d82fc
JJ
710 }
711
712 fcx
713}
714
715pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
716 let tcx = ccx.tcx;
717
718 check_representable(tcx, span, id, "struct");
719 check_instantiable(tcx, span, id);
720
721 if ty::lookup_simd(tcx, local_def(id)) {
722 check_simd(tcx, span, id);
723 }
724}
725
9346a6ac
AL
726pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
727 debug!("check_item_type(it.id={}, it.ident={})",
1a4d82fc
JJ
728 it.id,
729 ty::item_path_str(ccx.tcx, local_def(it.id)));
730 let _indenter = indenter();
1a4d82fc 731 match it.node {
9346a6ac 732 // Consts can play a role in type-checking, so they are included here.
1a4d82fc
JJ
733 ast::ItemStatic(_, _, ref e) |
734 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
735 ast::ItemEnum(ref enum_definition, _) => {
736 check_enum_variants(ccx,
737 it.span,
c34b1796 738 &enum_definition.variants,
1a4d82fc
JJ
739 it.id);
740 }
62682a34 741 ast::ItemFn(..) => {} // entirely within check_item_body
1a4d82fc 742 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
9346a6ac 743 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
1a4d82fc
JJ
744 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
745 Some(impl_trait_ref) => {
746 check_impl_items_against_trait(ccx,
747 it.span,
d9579d0f 748 &impl_trait_ref,
85aaf69f 749 impl_items);
1a4d82fc
JJ
750 }
751 None => { }
752 }
1a4d82fc 753 }
9346a6ac 754 ast::ItemTrait(_, ref generics, _, _) => {
85aaf69f 755 check_trait_on_unimplemented(ccx, generics, it);
1a4d82fc
JJ
756 }
757 ast::ItemStruct(..) => {
758 check_struct(ccx, it.id, it.span);
759 }
760 ast::ItemTy(ref t, ref generics) => {
761 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
762 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
763 }
764 ast::ItemForeignMod(ref m) => {
765 if m.abi == abi::RustIntrinsic {
85aaf69f 766 for item in &m.items {
1a4d82fc
JJ
767 check_intrinsic_type(ccx, &**item);
768 }
769 } else {
85aaf69f 770 for item in &m.items {
1a4d82fc
JJ
771 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
772 if !pty.generics.types.is_empty() {
773 span_err!(ccx.tcx.sess, item.span, E0044,
774 "foreign items may not have type parameters");
775 }
776
777 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
778 if fn_decl.variadic && m.abi != abi::C {
779 span_err!(ccx.tcx.sess, item.span, E0045,
780 "variadic function must have C calling convention");
781 }
782 }
783 }
784 }
785 }
786 _ => {/* nothing to do */ }
787 }
788}
789
9346a6ac
AL
790pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
791 debug!("check_item_body(it.id={}, it.ident={})",
792 it.id,
793 ty::item_path_str(ccx.tcx, local_def(it.id)));
794 let _indenter = indenter();
795 match it.node {
62682a34 796 ast::ItemFn(ref decl, _, _, _, _, ref body) => {
9346a6ac
AL
797 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
798 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
799 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
800 }
801 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
802 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
803
804 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
805
806 for impl_item in impl_items {
807 match impl_item.node {
d9579d0f
AL
808 ast::ConstImplItem(_, ref expr) => {
809 check_const(ccx, impl_item.span, &*expr, impl_item.id)
810 }
9346a6ac
AL
811 ast::MethodImplItem(ref sig, ref body) => {
812 check_method_body(ccx, &impl_pty.generics, sig, body,
813 impl_item.id, impl_item.span);
814 }
815 ast::TypeImplItem(_) |
816 ast::MacImplItem(_) => {
817 // Nothing to do here.
818 }
819 }
820 }
821 }
822 ast::ItemTrait(_, _, _, ref trait_items) => {
823 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
824 for trait_item in trait_items {
825 match trait_item.node {
d9579d0f
AL
826 ast::ConstTraitItem(_, Some(ref expr)) => {
827 check_const(ccx, trait_item.span, &*expr, trait_item.id)
9346a6ac
AL
828 }
829 ast::MethodTraitItem(ref sig, Some(ref body)) => {
62682a34
SL
830 check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
831
9346a6ac
AL
832 check_method_body(ccx, &trait_def.generics, sig, body,
833 trait_item.id, trait_item.span);
834 }
62682a34
SL
835 ast::MethodTraitItem(ref sig, None) => {
836 check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
837 }
d9579d0f 838 ast::ConstTraitItem(_, None) |
9346a6ac
AL
839 ast::TypeTraitItem(..) => {
840 // Nothing to do.
841 }
842 }
843 }
844 }
845 _ => {/* nothing to do */ }
846 }
847}
848
62682a34
SL
849fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
850 span: Span,
851 constness: ast::Constness)
852{
853 match constness {
854 ast::Constness::NotConst => {
855 // good
856 }
857 ast::Constness::Const => {
858 span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
859 }
860 }
861}
862
85aaf69f
SL
863fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
864 generics: &ast::Generics,
865 item: &ast::Item) {
866 if let Some(ref attr) = item.attrs.iter().find(|a| {
867 a.check_name("rustc_on_unimplemented")
868 }) {
869 if let Some(ref istring) = attr.value_str() {
870 let parser = Parser::new(&istring);
871 let types = &*generics.ty_params;
872 for token in parser {
873 match token {
874 Piece::String(_) => (), // Normal string, no need to check it
875 Piece::NextArgument(a) => match a.position {
876 // `{Self}` is allowed
877 Position::ArgumentNamed(s) if s == "Self" => (),
878 // So is `{A}` if A is a type parameter
879 Position::ArgumentNamed(s) => match types.iter().find(|t| {
880 t.ident.as_str() == s
881 }) {
882 Some(_) => (),
883 None => {
884 span_err!(ccx.tcx.sess, attr.span, E0230,
885 "there is no type parameter \
886 {} on trait {}",
887 s, item.ident.as_str());
888 }
889 },
890 // `{:1}` and `{}` are not to be used
891 Position::ArgumentIs(_) | Position::ArgumentNext => {
892 span_err!(ccx.tcx.sess, attr.span, E0231,
893 "only named substitution \
894 parameters are allowed");
895 }
896 }
897 }
898 }
899 } else {
900 span_err!(ccx.tcx.sess, attr.span, E0232,
901 "this attribute must have a value, \
902 eg `#[rustc_on_unimplemented = \"foo\"]`")
903 }
904 }
905}
906
1a4d82fc
JJ
907/// Type checks a method body.
908///
909/// # Parameters
910///
911/// * `item_generics`: generics defined on the impl/trait that contains
912/// the method
913/// * `self_bound`: bound for the `Self` type parameter, if any
914/// * `method`: the method definition
915fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
916 item_generics: &ty::Generics<'tcx>,
c34b1796
AL
917 sig: &'tcx ast::MethodSig,
918 body: &'tcx ast::Block,
919 id: ast::NodeId, span: Span) {
62682a34
SL
920 debug!("check_method_body(item_generics={:?}, id={})",
921 item_generics, id);
c34b1796
AL
922 let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
923
924 let fty = ty::node_id_to_type(ccx.tcx, id);
62682a34 925 debug!("check_method_body: fty={:?}", fty);
1a4d82fc 926
c34b1796 927 check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
1a4d82fc
JJ
928}
929
930fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
931 impl_span: Span,
932 impl_trait_ref: &ty::TraitRef<'tcx>,
c34b1796 933 impl_items: &[P<ast::ImplItem>]) {
1a4d82fc
JJ
934 // Locate trait methods
935 let tcx = ccx.tcx;
936 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
937
938 // Check existing impl methods to see if they are both present in trait
939 // and compatible with trait signature
85aaf69f 940 for impl_item in impl_items {
c34b1796 941 match impl_item.node {
d9579d0f
AL
942 ast::ConstImplItem(..) => {
943 let impl_const_def_id = local_def(impl_item.id);
944 let impl_const_ty = ty::impl_or_trait_item(ccx.tcx,
945 impl_const_def_id);
946
947 // Find associated const definition.
948 let opt_associated_const =
949 trait_items.iter()
950 .find(|ac| ac.name() == impl_const_ty.name());
951 match opt_associated_const {
952 Some(associated_const) => {
953 match (associated_const, &impl_const_ty) {
954 (&ty::ConstTraitItem(ref const_trait),
955 &ty::ConstTraitItem(ref const_impl)) => {
956 compare_const_impl(ccx.tcx,
957 &const_impl,
958 impl_item.span,
959 &const_trait,
960 &*impl_trait_ref);
961 }
962 _ => {
963 span_err!(tcx.sess, impl_item.span, E0323,
964 "item `{}` is an associated const, \
62682a34 965 which doesn't match its trait `{:?}`",
d9579d0f 966 token::get_name(impl_const_ty.name()),
62682a34 967 impl_trait_ref)
d9579d0f
AL
968 }
969 }
970 }
971 None => {
972 // This is `span_bug` as it should have already been
973 // caught in resolve.
974 tcx.sess.span_bug(
975 impl_item.span,
976 &format!(
977 "associated const `{}` is not a member of \
62682a34 978 trait `{:?}`",
d9579d0f 979 token::get_name(impl_const_ty.name()),
62682a34 980 impl_trait_ref));
d9579d0f
AL
981 }
982 }
983 }
62682a34
SL
984 ast::MethodImplItem(ref sig, ref body) => {
985 check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
986
c34b1796 987 let impl_method_def_id = local_def(impl_item.id);
1a4d82fc
JJ
988 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
989 impl_method_def_id);
990
991 // If this is an impl of a trait method, find the
992 // corresponding method definition in the trait.
993 let opt_trait_method_ty =
994 trait_items.iter()
995 .find(|ti| ti.name() == impl_item_ty.name());
996 match opt_trait_method_ty {
997 Some(trait_method_ty) => {
998 match (trait_method_ty, &impl_item_ty) {
999 (&ty::MethodTraitItem(ref trait_method_ty),
1000 &ty::MethodTraitItem(ref impl_method_ty)) => {
1001 compare_impl_method(ccx.tcx,
1002 &**impl_method_ty,
c34b1796
AL
1003 impl_item.span,
1004 body.id,
1a4d82fc
JJ
1005 &**trait_method_ty,
1006 &*impl_trait_ref);
1007 }
1008 _ => {
d9579d0f
AL
1009 span_err!(tcx.sess, impl_item.span, E0324,
1010 "item `{}` is an associated method, \
62682a34 1011 which doesn't match its trait `{:?}`",
d9579d0f 1012 token::get_name(impl_item_ty.name()),
62682a34 1013 impl_trait_ref)
1a4d82fc
JJ
1014 }
1015 }
1016 }
1017 None => {
1018 // This is span_bug as it should have already been
1019 // caught in resolve.
1020 tcx.sess.span_bug(
c34b1796 1021 impl_item.span,
62682a34 1022 &format!("method `{}` is not a member of trait `{:?}`",
85aaf69f 1023 token::get_name(impl_item_ty.name()),
62682a34 1024 impl_trait_ref));
1a4d82fc
JJ
1025 }
1026 }
1027 }
c34b1796
AL
1028 ast::TypeImplItem(_) => {
1029 let typedef_def_id = local_def(impl_item.id);
1a4d82fc
JJ
1030 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
1031 typedef_def_id);
1032
1033 // If this is an impl of an associated type, find the
1034 // corresponding type definition in the trait.
1035 let opt_associated_type =
1036 trait_items.iter()
1037 .find(|ti| ti.name() == typedef_ty.name());
1038 match opt_associated_type {
1039 Some(associated_type) => {
1040 match (associated_type, &typedef_ty) {
1041 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
1042 _ => {
d9579d0f
AL
1043 span_err!(tcx.sess, impl_item.span, E0325,
1044 "item `{}` is an associated type, \
62682a34 1045 which doesn't match its trait `{:?}`",
d9579d0f 1046 token::get_name(typedef_ty.name()),
62682a34 1047 impl_trait_ref)
1a4d82fc
JJ
1048 }
1049 }
1050 }
1051 None => {
1052 // This is `span_bug` as it should have already been
1053 // caught in resolve.
1054 tcx.sess.span_bug(
c34b1796 1055 impl_item.span,
85aaf69f 1056 &format!(
1a4d82fc 1057 "associated type `{}` is not a member of \
62682a34 1058 trait `{:?}`",
1a4d82fc 1059 token::get_name(typedef_ty.name()),
62682a34 1060 impl_trait_ref));
1a4d82fc
JJ
1061 }
1062 }
1063 }
c34b1796
AL
1064 ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
1065 "unexpanded macro")
1a4d82fc
JJ
1066 }
1067 }
1068
1069 // Check for missing items from trait
1070 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
d9579d0f 1071 let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
62682a34
SL
1072 let mut missing_items = Vec::new();
1073 for trait_item in trait_items.iter() {
1a4d82fc 1074 match *trait_item {
d9579d0f
AL
1075 ty::ConstTraitItem(ref associated_const) => {
1076 let is_implemented = impl_items.iter().any(|ii| {
1077 match ii.node {
1078 ast::ConstImplItem(..) => {
1079 ii.ident.name == associated_const.name
1080 }
1081 _ => false,
1082 }
1083 });
1084 let is_provided =
1085 associated_consts.iter().any(|ac| ac.default.is_some() &&
1086 ac.name == associated_const.name);
1087 if !is_implemented && !is_provided {
62682a34
SL
1088 missing_items.push(format!("`{}`",
1089 token::get_name(associated_const.name)));
d9579d0f
AL
1090 }
1091 }
1a4d82fc
JJ
1092 ty::MethodTraitItem(ref trait_method) => {
1093 let is_implemented =
1094 impl_items.iter().any(|ii| {
c34b1796
AL
1095 match ii.node {
1096 ast::MethodImplItem(..) => {
1097 ii.ident.name == trait_method.name
1a4d82fc 1098 }
d9579d0f 1099 _ => false,
1a4d82fc
JJ
1100 }
1101 });
1102 let is_provided =
1103 provided_methods.iter().any(|m| m.name == trait_method.name);
1104 if !is_implemented && !is_provided {
62682a34 1105 missing_items.push(format!("`{}`", token::get_name(trait_method.name)));
1a4d82fc
JJ
1106 }
1107 }
1108 ty::TypeTraitItem(ref associated_type) => {
1109 let is_implemented = impl_items.iter().any(|ii| {
c34b1796
AL
1110 match ii.node {
1111 ast::TypeImplItem(_) => {
1112 ii.ident.name == associated_type.name
1a4d82fc 1113 }
d9579d0f 1114 _ => false,
1a4d82fc
JJ
1115 }
1116 });
62682a34
SL
1117 let is_provided = associated_type.ty.is_some();
1118 if !is_implemented && !is_provided {
1119 missing_items.push(format!("`{}`", token::get_name(associated_type.name)));
1a4d82fc
JJ
1120 }
1121 }
1122 }
1123 }
1124
62682a34 1125 if !missing_items.is_empty() {
1a4d82fc
JJ
1126 span_err!(tcx.sess, impl_span, E0046,
1127 "not all trait items implemented, missing: {}",
62682a34 1128 missing_items.connect(", "));
1a4d82fc
JJ
1129 }
1130}
1131
85aaf69f
SL
1132fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1133 span: Span,
1134 t_span: Span,
1135 e_span: Span,
62682a34
SL
1136 t_cast: Ty<'tcx>,
1137 t_expr: Ty<'tcx>,
85aaf69f 1138 id: ast::NodeId) {
62682a34 1139 let tstr = fcx.infcx().ty_to_string(t_cast);
85aaf69f
SL
1140 fcx.type_error_message(span, |actual| {
1141 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
62682a34
SL
1142 }, t_expr, None);
1143 match t_expr.sty {
1144 ty::TyRef(_, ty::mt { mutbl: mt, .. }) => {
85aaf69f
SL
1145 let mtstr = match mt {
1146 ast::MutMutable => "mut ",
1147 ast::MutImmutable => ""
1148 };
62682a34 1149 if ty::type_is_trait(t_cast) {
d9579d0f
AL
1150 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1151 Ok(s) => {
1152 fcx.tcx().sess.span_suggestion(t_span,
1153 "try casting to a reference instead:",
1154 format!("&{}{}", mtstr, s));
1155 },
1156 Err(_) =>
1157 span_help!(fcx.tcx().sess, t_span,
1158 "did you mean `&{}{}`?", mtstr, tstr),
1159 }
85aaf69f
SL
1160 } else {
1161 span_help!(fcx.tcx().sess, span,
1162 "consider using an implicit coercion to `&{}{}` instead",
1163 mtstr, tstr);
1a4d82fc
JJ
1164 }
1165 }
62682a34 1166 ty::TyBox(..) => {
d9579d0f
AL
1167 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1168 Ok(s) => {
1169 fcx.tcx().sess.span_suggestion(t_span,
1170 "try casting to a `Box` instead:",
1171 format!("Box<{}>", s));
1172 },
1173 Err(_) =>
1174 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
1175 }
1a4d82fc 1176 }
85aaf69f
SL
1177 _ => {
1178 span_help!(fcx.tcx().sess, e_span,
1179 "consider using a box or reference as appropriate");
1a4d82fc 1180 }
1a4d82fc 1181 }
85aaf69f 1182 fcx.write_error(id);
1a4d82fc
JJ
1183}
1184
1a4d82fc 1185
1a4d82fc
JJ
1186impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1187 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1188
c34b1796
AL
1189 fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
1190 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
1191 {
1192 Ok(ty::lookup_item_type(self.tcx(), id))
1a4d82fc
JJ
1193 }
1194
c34b1796 1195 fn get_trait_def(&self, _: Span, id: ast::DefId)
d9579d0f 1196 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
c34b1796
AL
1197 {
1198 Ok(ty::lookup_trait_def(self.tcx(), id))
1199 }
1200
1201 fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
1202 // all super predicates are ensured during collect pass
1203 Ok(())
1a4d82fc
JJ
1204 }
1205
1206 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1207 Some(&self.inh.param_env.free_substs)
1208 }
1209
c34b1796
AL
1210 fn get_type_parameter_bounds(&self,
1211 _: Span,
1212 node_id: ast::NodeId)
1213 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1214 {
1215 let def = self.tcx().type_parameter_def(node_id);
1216 let r = self.inh.param_env.caller_bounds
1217 .iter()
1218 .filter_map(|predicate| {
1219 match *predicate {
1220 ty::Predicate::Trait(ref data) => {
1221 if data.0.self_ty().is_param(def.space, def.index) {
1222 Some(data.to_poly_trait_ref())
1223 } else {
1224 None
1225 }
1226 }
1227 _ => {
1228 None
1229 }
1230 }
1231 })
1232 .collect();
1233 Ok(r)
1234 }
1235
1236 fn trait_defines_associated_type_named(&self,
1237 trait_def_id: ast::DefId,
1238 assoc_name: ast::Name)
1239 -> bool
1240 {
1241 let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
1242 trait_def.associated_type_names.contains(&assoc_name)
1243 }
1244
1a4d82fc
JJ
1245 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1246 self.infcx().next_ty_var()
1247 }
1248
1249 fn projected_ty_from_poly_trait_ref(&self,
1250 span: Span,
1251 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1252 item_name: ast::Name)
1253 -> Ty<'tcx>
1254 {
1255 let (trait_ref, _) =
1256 self.infcx().replace_late_bound_regions_with_fresh_var(
1257 span,
1258 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1259 &poly_trait_ref);
1260
1261 self.normalize_associated_type(span, trait_ref, item_name)
1262 }
1263
1264 fn projected_ty(&self,
1265 span: Span,
d9579d0f 1266 trait_ref: ty::TraitRef<'tcx>,
1a4d82fc
JJ
1267 item_name: ast::Name)
1268 -> Ty<'tcx>
1269 {
1270 self.normalize_associated_type(span, trait_ref, item_name)
1271 }
1272}
1273
1274impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1275 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1276
1277 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1278 &self.inh.infcx
1279 }
1280
1281 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1282 &self.inh.param_env
1283 }
1284
1285 pub fn sess(&self) -> &Session {
1286 &self.tcx().sess
1287 }
1288
c34b1796 1289 pub fn err_count_since_creation(&self) -> usize {
1a4d82fc
JJ
1290 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1291 }
1292
85aaf69f
SL
1293 /// Resolves type variables in `ty` if possible. Unlike the infcx
1294 /// version, this version will also select obligations if it seems
1295 /// useful, in an effort to get more type information.
1296 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
62682a34 1297 debug!("resolve_type_vars_if_possible(ty={:?})", ty);
c34b1796 1298
85aaf69f
SL
1299 // No ty::infer()? Nothing needs doing.
1300 if !ty::type_has_ty_infer(ty) {
62682a34 1301 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
85aaf69f
SL
1302 return ty;
1303 }
1304
1305 // If `ty` is a type variable, see whether we already know what it is.
1306 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1307 if !ty::type_has_ty_infer(ty) {
62682a34 1308 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
85aaf69f
SL
1309 return ty;
1310 }
1311
1312 // If not, try resolving any new fcx obligations that have cropped up.
d9579d0f 1313 self.select_new_obligations();
85aaf69f
SL
1314 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1315 if !ty::type_has_ty_infer(ty) {
62682a34 1316 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
85aaf69f
SL
1317 return ty;
1318 }
1319
1320 // If not, try resolving *all* pending obligations as much as
1321 // possible. This can help substantially when there are
1322 // indirect dependencies that don't seem worth tracking
1323 // precisely.
d9579d0f 1324 self.select_obligations_where_possible();
c34b1796
AL
1325 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1326
62682a34 1327 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
c34b1796 1328 ty
85aaf69f
SL
1329 }
1330
1a4d82fc
JJ
1331 /// Resolves all type variables in `t` and then, if any were left
1332 /// unresolved, substitutes an error type. This is used after the
1333 /// main checking when doing a second pass before writeback. The
1334 /// justification is that writeback will produce an error for
1335 /// these unconstrained type variables.
1336 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1337 let t = self.infcx().resolve_type_vars_if_possible(t);
1338 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1339 }
1340
85aaf69f
SL
1341 fn record_deferred_call_resolution(&self,
1342 closure_def_id: ast::DefId,
1343 r: DeferredCallResolutionHandler<'tcx>) {
1344 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
c34b1796 1345 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
85aaf69f
SL
1346 }
1347
1348 fn remove_deferred_call_resolutions(&self,
1349 closure_def_id: ast::DefId)
1350 -> Vec<DeferredCallResolutionHandler<'tcx>>
1351 {
1352 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1353 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1354 }
1355
1a4d82fc 1356 pub fn tag(&self) -> String {
c34b1796
AL
1357 let self_ptr: *const FnCtxt = self;
1358 format!("{:?}", self_ptr)
1a4d82fc
JJ
1359 }
1360
1361 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1362 match self.inh.locals.borrow().get(&nid) {
1363 Some(&t) => t,
1364 None => {
c34b1796 1365 self.tcx().sess.span_err(
1a4d82fc 1366 span,
c34b1796
AL
1367 &format!("no type for local variable {}", nid));
1368 self.tcx().types.err
1a4d82fc
JJ
1369 }
1370 }
1371 }
1372
1373 /// Apply "fallbacks" to some types
1374 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1375 pub fn default_type_parameters(&self) {
1376 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
85aaf69f 1377 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1a4d82fc
JJ
1378 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1379 if self.infcx().type_var_diverges(resolved) {
1380 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1381 } else {
1382 match self.infcx().type_is_unconstrained_numeric(resolved) {
1383 UnconstrainedInt => {
1384 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1385 },
1386 UnconstrainedFloat => {
1387 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1388 }
1389 Neither => { }
1390 }
1391 }
1392 }
1393 }
1394
1395 #[inline]
1396 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
62682a34
SL
1397 debug!("write_ty({}, {:?}) in fcx {}",
1398 node_id, ty, self.tag());
1a4d82fc
JJ
1399 self.inh.node_types.borrow_mut().insert(node_id, ty);
1400 }
1401
1a4d82fc
JJ
1402 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1403 if !substs.substs.is_noop() {
62682a34 1404 debug!("write_substs({}, {:?}) in fcx {}",
1a4d82fc 1405 node_id,
62682a34 1406 substs,
1a4d82fc
JJ
1407 self.tag());
1408
1409 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1410 }
1411 }
1412
1413 pub fn write_autoderef_adjustment(&self,
1414 node_id: ast::NodeId,
c34b1796 1415 derefs: usize) {
1a4d82fc
JJ
1416 self.write_adjustment(
1417 node_id,
1a4d82fc
JJ
1418 ty::AdjustDerefRef(ty::AutoDerefRef {
1419 autoderefs: derefs,
9346a6ac
AL
1420 autoref: None,
1421 unsize: None
1422 })
1a4d82fc
JJ
1423 );
1424 }
1425
1426 pub fn write_adjustment(&self,
1427 node_id: ast::NodeId,
1a4d82fc 1428 adj: ty::AutoAdjustment<'tcx>) {
62682a34 1429 debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
1a4d82fc
JJ
1430
1431 if adj.is_identity() {
1432 return;
1433 }
1434
1a4d82fc
JJ
1435 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1436 }
1437
1438 /// Basically whenever we are converting from a type scheme into
1439 /// the fn body space, we always want to normalize associated
1440 /// types as well. This function combines the two.
1441 fn instantiate_type_scheme<T>(&self,
1442 span: Span,
1443 substs: &Substs<'tcx>,
1444 value: &T)
1445 -> T
62682a34 1446 where T : TypeFoldable<'tcx> + HasProjectionTypes
1a4d82fc
JJ
1447 {
1448 let value = value.subst(self.tcx(), substs);
1449 let result = self.normalize_associated_types_in(span, &value);
62682a34
SL
1450 debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
1451 value,
1452 substs,
1453 result);
1a4d82fc
JJ
1454 result
1455 }
1456
1457 /// As `instantiate_type_scheme`, but for the bounds found in a
1458 /// generic type scheme.
1459 fn instantiate_bounds(&self,
1460 span: Span,
1461 substs: &Substs<'tcx>,
85aaf69f
SL
1462 bounds: &ty::GenericPredicates<'tcx>)
1463 -> ty::InstantiatedPredicates<'tcx>
1a4d82fc 1464 {
85aaf69f
SL
1465 ty::InstantiatedPredicates {
1466 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1a4d82fc
JJ
1467 }
1468 }
1469
1470
1471 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
62682a34 1472 where T : TypeFoldable<'tcx> + HasProjectionTypes
1a4d82fc
JJ
1473 {
1474 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1475 }
1476
1477 fn normalize_associated_type(&self,
1478 span: Span,
d9579d0f 1479 trait_ref: ty::TraitRef<'tcx>,
1a4d82fc
JJ
1480 item_name: ast::Name)
1481 -> Ty<'tcx>
1482 {
1483 let cause = traits::ObligationCause::new(span,
1484 self.body_id,
1485 traits::ObligationCauseCode::MiscObligation);
1486 self.inh.fulfillment_cx
1487 .borrow_mut()
1488 .normalize_projection_type(self.infcx(),
1489 self,
1490 ty::ProjectionTy {
1491 trait_ref: trait_ref,
1492 item_name: item_name,
1493 },
1494 cause)
1495 }
1496
1a4d82fc
JJ
1497 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1498 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1499 /// Registers any trait obligations specified on `def_id` at the same time.
1500 ///
1501 /// Note that function is only intended to be used with types (notably, not fns). This is
1502 /// because it doesn't do any instantiation of late-bound regions.
1503 pub fn instantiate_type(&self,
1504 span: Span,
1505 def_id: ast::DefId)
1506 -> TypeAndSubsts<'tcx>
1507 {
1508 let type_scheme =
1509 ty::lookup_item_type(self.tcx(), def_id);
85aaf69f
SL
1510 let type_predicates =
1511 ty::lookup_predicates(self.tcx(), def_id);
1a4d82fc
JJ
1512 let substs =
1513 self.infcx().fresh_substs_for_generics(
1514 span,
1515 &type_scheme.generics);
1516 let bounds =
85aaf69f 1517 self.instantiate_bounds(span, &substs, &type_predicates);
1a4d82fc
JJ
1518 self.add_obligations_for_parameters(
1519 traits::ObligationCause::new(
1520 span,
1521 self.body_id,
1522 traits::ItemObligation(def_id)),
1523 &bounds);
1524 let monotype =
1525 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1526
1527 TypeAndSubsts {
1528 ty: monotype,
1529 substs: substs
1530 }
1531 }
1532
1533 /// Returns the type that this AST path refers to. If the path has no type
1534 /// parameters and the corresponding type has type parameters, fresh type
1535 /// and/or region variables are substituted.
1536 ///
1537 /// This is used when checking the constructor in struct literals.
1538 fn instantiate_struct_literal_ty(&self,
1539 did: ast::DefId,
1540 path: &ast::Path)
1541 -> TypeAndSubsts<'tcx>
1542 {
1543 let tcx = self.tcx();
1544
85aaf69f
SL
1545 let ty::TypeScheme { generics, ty: decl_ty } =
1546 ty::lookup_item_type(tcx, did);
1a4d82fc 1547
c34b1796
AL
1548 let substs = astconv::ast_path_substs_for_ty(self, self,
1549 path.span,
1550 PathParamMode::Optional,
1551 &generics,
1552 path.segments.last().unwrap());
1a4d82fc
JJ
1553
1554 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1555
1556 TypeAndSubsts { substs: substs, ty: ty }
1557 }
1558
1559 pub fn write_nil(&self, node_id: ast::NodeId) {
1560 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1561 }
1562 pub fn write_error(&self, node_id: ast::NodeId) {
1563 self.write_ty(node_id, self.tcx().types.err);
1564 }
1565
1566 pub fn require_type_meets(&self,
1567 ty: Ty<'tcx>,
1568 span: Span,
1569 code: traits::ObligationCauseCode<'tcx>,
1570 bound: ty::BuiltinBound)
1571 {
1572 self.register_builtin_bound(
1573 ty,
1574 bound,
1575 traits::ObligationCause::new(span, self.body_id, code));
1576 }
1577
1578 pub fn require_type_is_sized(&self,
1579 ty: Ty<'tcx>,
1580 span: Span,
1581 code: traits::ObligationCauseCode<'tcx>)
1582 {
1583 self.require_type_meets(ty, span, code, ty::BoundSized);
1584 }
1585
1586 pub fn require_expr_have_sized_type(&self,
1587 expr: &ast::Expr,
1588 code: traits::ObligationCauseCode<'tcx>)
1589 {
1590 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1591 }
1592
1593 pub fn type_is_known_to_be_sized(&self,
1594 ty: Ty<'tcx>,
1595 span: Span)
1596 -> bool
1597 {
1598 traits::type_known_to_meet_builtin_bound(self.infcx(),
1599 self.param_env(),
1600 ty,
1601 ty::BoundSized,
1602 span)
1603 }
1604
1605 pub fn register_builtin_bound(&self,
1606 ty: Ty<'tcx>,
1607 builtin_bound: ty::BuiltinBound,
1608 cause: traits::ObligationCause<'tcx>)
1609 {
1610 self.inh.fulfillment_cx.borrow_mut()
1611 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1612 }
1613
1614 pub fn register_predicate(&self,
1615 obligation: traits::PredicateObligation<'tcx>)
1616 {
62682a34
SL
1617 debug!("register_predicate({:?})",
1618 obligation);
1a4d82fc
JJ
1619 self.inh.fulfillment_cx
1620 .borrow_mut()
1621 .register_predicate_obligation(self.infcx(), obligation);
1622 }
1623
1624 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1625 let t = ast_ty_to_ty(self, self, ast_t);
1626
1627 let mut bounds_checker = wf::BoundsChecker::new(self,
85aaf69f 1628 self.body_id,
1a4d82fc 1629 None);
62682a34 1630 bounds_checker.check_ty(t, ast_t.span);
1a4d82fc
JJ
1631
1632 t
1633 }
1634
1a4d82fc
JJ
1635 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1636 match self.inh.node_types.borrow().get(&ex.id) {
1637 Some(&t) => t,
1638 None => {
1639 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
c34b1796 1640 self.tag()));
1a4d82fc
JJ
1641 }
1642 }
1643 }
1644
1645 /// Apply `adjustment` to the type of `expr`
1646 pub fn adjust_expr_ty(&self,
1647 expr: &ast::Expr,
1648 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1649 -> Ty<'tcx>
1650 {
1651 let raw_ty = self.expr_ty(expr);
1652 let raw_ty = self.infcx().shallow_resolve(raw_ty);
85aaf69f 1653 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1a4d82fc
JJ
1654 ty::adjust_ty(self.tcx(),
1655 expr.span,
1656 expr.id,
1657 raw_ty,
1658 adjustment,
1659 |method_call| self.inh.method_map.borrow()
1660 .get(&method_call)
85aaf69f 1661 .map(|method| resolve_ty(method.ty)))
1a4d82fc
JJ
1662 }
1663
1664 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1665 match self.inh.node_types.borrow().get(&id) {
1666 Some(&t) => t,
85aaf69f 1667 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1a4d82fc
JJ
1668 None => {
1669 self.tcx().sess.bug(
1670 &format!("no type for node {}: {} in fcx {}",
1671 id, self.tcx().map.node_to_string(id),
c34b1796 1672 self.tag()));
1a4d82fc
JJ
1673 }
1674 }
1675 }
1676
1677 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1678 self.inh.item_substs.borrow()
1679 }
1680
1681 pub fn opt_node_ty_substs<F>(&self,
1682 id: ast::NodeId,
1683 f: F) where
1684 F: FnOnce(&ty::ItemSubsts<'tcx>),
1685 {
1686 match self.inh.item_substs.borrow().get(&id) {
1687 Some(s) => { f(s) }
1688 None => { }
1689 }
1690 }
1691
1692 pub fn mk_subty(&self,
1693 a_is_expected: bool,
1694 origin: infer::TypeOrigin,
1695 sub: Ty<'tcx>,
1696 sup: Ty<'tcx>)
1697 -> Result<(), ty::type_err<'tcx>> {
1698 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1699 }
1700
1a4d82fc
JJ
1701 pub fn mk_eqty(&self,
1702 a_is_expected: bool,
1703 origin: infer::TypeOrigin,
1704 sub: Ty<'tcx>,
1705 sup: Ty<'tcx>)
1706 -> Result<(), ty::type_err<'tcx>> {
1707 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1708 }
1709
1710 pub fn mk_subr(&self,
1711 origin: infer::SubregionOrigin<'tcx>,
1712 sub: ty::Region,
1713 sup: ty::Region) {
1714 infer::mk_subr(self.infcx(), origin, sub, sup)
1715 }
1716
1717 pub fn type_error_message<M>(&self,
1718 sp: Span,
1719 mk_msg: M,
1720 actual_ty: Ty<'tcx>,
1721 err: Option<&ty::type_err<'tcx>>) where
1722 M: FnOnce(String) -> String,
1723 {
1724 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1725 }
1726
1727 pub fn report_mismatched_types(&self,
1728 sp: Span,
1729 e: Ty<'tcx>,
1730 a: Ty<'tcx>,
1731 err: &ty::type_err<'tcx>) {
1732 self.infcx().report_mismatched_types(sp, e, a, err)
1733 }
1734
1735 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1736 /// outlive the region `r`.
1737 pub fn register_region_obligation(&self,
1738 ty: Ty<'tcx>,
1739 region: ty::Region,
1740 cause: traits::ObligationCause<'tcx>)
1741 {
1742 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
62682a34 1743 fulfillment_cx.register_region_obligation(ty, region, cause);
1a4d82fc
JJ
1744 }
1745
1746 pub fn add_default_region_param_bounds(&self,
1747 substs: &Substs<'tcx>,
1748 expr: &ast::Expr)
1749 {
62682a34 1750 for &ty in &substs.types {
1a4d82fc
JJ
1751 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1752 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1753 traits::MiscObligation);
1754 self.register_region_obligation(ty, default_bound, cause);
1755 }
1756 }
1757
1758 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1759 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1760 /// trait/region obligations.
1761 ///
1762 /// For example, if there is a function:
1763 ///
1764 /// ```
1765 /// fn foo<'a,T:'a>(...)
1766 /// ```
1767 ///
1768 /// and a reference:
1769 ///
1770 /// ```
1771 /// let f = foo;
1772 /// ```
1773 ///
1774 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1775 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1776 pub fn add_obligations_for_parameters(&self,
1777 cause: traits::ObligationCause<'tcx>,
85aaf69f 1778 predicates: &ty::InstantiatedPredicates<'tcx>)
1a4d82fc 1779 {
85aaf69f 1780 assert!(!predicates.has_escaping_regions());
1a4d82fc 1781
62682a34
SL
1782 debug!("add_obligations_for_parameters(predicates={:?})",
1783 predicates);
1a4d82fc 1784
62682a34
SL
1785 for obligation in traits::predicates_for_generics(cause, predicates) {
1786 self.register_predicate(obligation);
1787 }
1a4d82fc 1788 }
85aaf69f
SL
1789
1790 // Only for fields! Returns <none> for methods>
1791 // Indifferent to privacy flags
1792 pub fn lookup_field_ty(&self,
1793 span: Span,
1794 class_id: ast::DefId,
1795 items: &[ty::field_ty],
1796 fieldname: ast::Name,
1797 substs: &subst::Substs<'tcx>)
1798 -> Option<Ty<'tcx>>
1799 {
1800 let o_field = items.iter().find(|f| f.name == fieldname);
1801 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1802 .map(|t| self.normalize_associated_types_in(span, &t))
1803 }
1804
1805 pub fn lookup_tup_field_ty(&self,
1806 span: Span,
1807 class_id: ast::DefId,
1808 items: &[ty::field_ty],
c34b1796 1809 idx: usize,
85aaf69f
SL
1810 substs: &subst::Substs<'tcx>)
1811 -> Option<Ty<'tcx>>
1812 {
1813 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1814 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1815 .map(|t| self.normalize_associated_types_in(span, &t))
1816 }
c34b1796
AL
1817
1818 fn check_casts(&self) {
1819 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
62682a34
SL
1820 for cast in deferred_cast_checks.drain(..) {
1821 cast.check(self);
c34b1796 1822 }
c34b1796 1823 }
d9579d0f
AL
1824
1825 fn select_all_obligations_and_apply_defaults(&self) {
1826 debug!("select_all_obligations_and_apply_defaults");
1827
1828 self.select_obligations_where_possible();
1829 self.default_type_parameters();
1830 self.select_obligations_where_possible();
1831 }
1832
1833 fn select_all_obligations_or_error(&self) {
1834 debug!("select_all_obligations_or_error");
1835
1836 // upvar inference should have ensured that all deferred call
1837 // resolutions are handled by now.
1838 assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
1839
1840 self.select_all_obligations_and_apply_defaults();
1841 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1842 match fulfillment_cx.select_all_or_error(self.infcx(), self) {
1843 Ok(()) => { }
1844 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1845 }
1846 }
1847
1848 /// Select as many obligations as we can at present.
1849 fn select_obligations_where_possible(&self) {
1850 match
1851 self.inh.fulfillment_cx
1852 .borrow_mut()
1853 .select_where_possible(self.infcx(), self)
1854 {
1855 Ok(()) => { }
1856 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1857 }
1858 }
1859
1860 /// Try to select any fcx obligation that we haven't tried yet, in an effort
1861 /// to improve inference. You could just call
1862 /// `select_obligations_where_possible` except that it leads to repeated
1863 /// work.
1864 fn select_new_obligations(&self) {
1865 match
1866 self.inh.fulfillment_cx
1867 .borrow_mut()
1868 .select_new_obligations(self.infcx(), self)
1869 {
1870 Ok(()) => { }
1871 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1872 }
1873 }
1874
1a4d82fc
JJ
1875}
1876
1877impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
85aaf69f 1878 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
62682a34
SL
1879 Some(self.base_object_lifetime_default(span))
1880 }
1881
1882 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
85aaf69f
SL
1883 // RFC #599 specifies that object lifetime defaults take
1884 // precedence over other defaults. But within a fn body we
1885 // don't have a *default* region, rather we use inference to
1886 // find the *correct* region, which is strictly more general
1887 // (and anyway, within a fn body the right region may not even
1888 // be something the user can write explicitly, since it might
1889 // be some expression).
62682a34 1890 self.infcx().next_region_var(infer::MiscVariable(span))
1a4d82fc
JJ
1891 }
1892
c34b1796
AL
1893 fn anon_regions(&self, span: Span, count: usize)
1894 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
85aaf69f 1895 Ok((0..count).map(|_| {
1a4d82fc
JJ
1896 self.infcx().next_region_var(infer::MiscVariable(span))
1897 }).collect())
1898 }
1899}
1900
c34b1796 1901#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1a4d82fc
JJ
1902pub enum LvaluePreference {
1903 PreferMutLvalue,
1904 NoPreference
1905}
1906
62682a34
SL
1907impl LvaluePreference {
1908 pub fn from_mutbl(m: ast::Mutability) -> Self {
1909 match m {
1910 ast::MutMutable => PreferMutLvalue,
1911 ast::MutImmutable => NoPreference,
1912 }
1913 }
1914}
1915
85aaf69f 1916/// Whether `autoderef` requires types to resolve.
c34b1796 1917#[derive(Copy, Clone, Debug, PartialEq, Eq)]
85aaf69f 1918pub enum UnresolvedTypeAction {
62682a34
SL
1919 /// Produce an error and return `TyError` whenever a type cannot
1920 /// be resolved (i.e. it is `TyInfer`).
85aaf69f
SL
1921 Error,
1922 /// Go on without emitting any errors, and return the unresolved
1923 /// type. Useful for probing, e.g. in coercions.
1924 Ignore
1925}
1926
1a4d82fc
JJ
1927/// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1928/// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1929///
1930/// Note: this method does not modify the adjustments table. The caller is responsible for
1931/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1932pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1933 sp: Span,
1934 base_ty: Ty<'tcx>,
1935 opt_expr: Option<&ast::Expr>,
85aaf69f 1936 unresolved_type_action: UnresolvedTypeAction,
1a4d82fc
JJ
1937 mut lvalue_pref: LvaluePreference,
1938 mut should_stop: F)
c34b1796
AL
1939 -> (Ty<'tcx>, usize, Option<T>)
1940 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
1a4d82fc 1941{
62682a34
SL
1942 debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
1943 base_ty,
1944 opt_expr,
1a4d82fc
JJ
1945 lvalue_pref);
1946
1947 let mut t = base_ty;
85aaf69f
SL
1948 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1949 let resolved_t = match unresolved_type_action {
1950 UnresolvedTypeAction::Error => {
d9579d0f 1951 structurally_resolved_type(fcx, sp, t)
85aaf69f
SL
1952 }
1953 UnresolvedTypeAction::Ignore => {
1954 // We can continue even when the type cannot be resolved
1955 // (i.e. it is an inference variable) because `ty::deref`
1956 // and `try_overloaded_deref` both simply return `None`
1957 // in such a case without producing spurious errors.
1958 fcx.resolve_type_vars_if_possible(t)
1959 }
1960 };
d9579d0f
AL
1961 if ty::type_is_error(resolved_t) {
1962 return (resolved_t, autoderefs, None);
1963 }
1a4d82fc
JJ
1964
1965 match should_stop(resolved_t, autoderefs) {
1966 Some(x) => return (resolved_t, autoderefs, Some(x)),
1967 None => {}
1968 }
1969
1970 // Otherwise, deref if type is derefable:
1971 let mt = match ty::deref(resolved_t, false) {
1972 Some(mt) => Some(mt),
1973 None => {
9346a6ac
AL
1974 let method_call =
1975 opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
1a4d82fc
JJ
1976
1977 // Super subtle: it might seem as though we should
1978 // pass `opt_expr` to `try_overloaded_deref`, so that
1979 // the (implicit) autoref of using an overloaded deref
1980 // would get added to the adjustment table. However we
1981 // do not do that, because it's kind of a
1982 // "meta-adjustment" -- instead, we just leave it
1983 // unrecorded and know that there "will be" an
1984 // autoref. regionck and other bits of the code base,
1985 // when they encounter an overloaded autoderef, have
1986 // to do some reconstructive surgery. This is a pretty
1987 // complex mess that is begging for a proper MIR.
1988 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1989 }
1990 };
1991 match mt {
1992 Some(mt) => {
1993 t = mt.ty;
1994 if mt.mutbl == ast::MutImmutable {
1995 lvalue_pref = NoPreference;
1996 }
1997 }
1998 None => return (resolved_t, autoderefs, None)
1999 }
2000 }
2001
2002 // We've reached the recursion limit, error gracefully.
2003 span_err!(fcx.tcx().sess, sp, E0055,
62682a34
SL
2004 "reached the recursion limit while auto-dereferencing {:?}",
2005 base_ty);
1a4d82fc
JJ
2006 (fcx.tcx().types.err, 0, None)
2007}
2008
2009fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2010 span: Span,
2011 method_call: Option<MethodCall>,
2012 base_expr: Option<&ast::Expr>,
2013 base_ty: Ty<'tcx>,
2014 lvalue_pref: LvaluePreference)
2015 -> Option<ty::mt<'tcx>>
2016{
2017 // Try DerefMut first, if preferred.
2018 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2019 (PreferMutLvalue, Some(trait_did)) => {
2020 method::lookup_in_trait(fcx, span, base_expr,
2021 token::intern("deref_mut"), trait_did,
2022 base_ty, None)
2023 }
2024 _ => None
2025 };
2026
2027 // Otherwise, fall back to Deref.
2028 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2029 (None, Some(trait_did)) => {
2030 method::lookup_in_trait(fcx, span, base_expr,
2031 token::intern("deref"), trait_did,
2032 base_ty, None)
2033 }
2034 (method, _) => method
2035 };
2036
2037 make_overloaded_lvalue_return_type(fcx, method_call, method)
2038}
2039
2040/// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2041/// actual type we assign to the *expression* is `T`. So this function just peels off the return
2042/// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2043fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2044 method_call: Option<MethodCall>,
2045 method: Option<MethodCallee<'tcx>>)
2046 -> Option<ty::mt<'tcx>>
2047{
2048 match method {
2049 Some(method) => {
c34b1796
AL
2050 // extract method method return type, which will be &T;
2051 // all LB regions should have been instantiated during method lookup
2052 let ret_ty = ty::ty_fn_ret(method.ty);
2053 let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap();
2054
2055 if let Some(method_call) = method_call {
2056 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1a4d82fc 2057 }
c34b1796
AL
2058
2059 // method returns &T, but the type as visible to user is T, so deref
2060 ty::deref(ret_ty, true)
1a4d82fc
JJ
2061 }
2062 None => None,
2063 }
2064}
2065
9346a6ac
AL
2066fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2067 expr: &ast::Expr,
2068 base_expr: &'tcx ast::Expr,
2069 base_ty: Ty<'tcx>,
2070 idx_ty: Ty<'tcx>,
2071 lvalue_pref: LvaluePreference)
2072 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
1a4d82fc
JJ
2073{
2074 // FIXME(#18741) -- this is almost but not quite the same as the
2075 // autoderef that normal method probing does. They could likely be
2076 // consolidated.
2077
85aaf69f
SL
2078 let (ty, autoderefs, final_mt) = autoderef(fcx,
2079 base_expr.span,
2080 base_ty,
2081 Some(base_expr),
2082 UnresolvedTypeAction::Error,
2083 lvalue_pref,
2084 |adj_ty, idx| {
9346a6ac
AL
2085 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2086 adj_ty, idx, false, lvalue_pref, idx_ty)
2087 });
1a4d82fc
JJ
2088
2089 if final_mt.is_some() {
2090 return final_mt;
2091 }
2092
62682a34 2093 // After we have fully autoderef'd, if the resulting type is [T; n], then
1a4d82fc 2094 // do a final unsized coercion to yield [T].
62682a34 2095 if let ty::TyArray(element_ty, _) = ty.sty {
9346a6ac
AL
2096 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2097 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2098 adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
2099 } else {
2100 None
1a4d82fc
JJ
2101 }
2102}
2103
2104/// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2105/// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2106/// This loop implements one step in that search; the autoderef loop is implemented by
9346a6ac 2107/// `lookup_indexing`.
1a4d82fc
JJ
2108fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2109 method_call: MethodCall,
2110 expr: &ast::Expr,
85aaf69f 2111 base_expr: &'tcx ast::Expr,
1a4d82fc 2112 adjusted_ty: Ty<'tcx>,
9346a6ac
AL
2113 autoderefs: usize,
2114 unsize: bool,
1a4d82fc
JJ
2115 lvalue_pref: LvaluePreference,
2116 index_ty: Ty<'tcx>)
2117 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2118{
2119 let tcx = fcx.tcx();
62682a34
SL
2120 debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
2121 autoderefs={}, unsize={}, index_ty={:?})",
2122 expr,
2123 base_expr,
2124 adjusted_ty,
9346a6ac
AL
2125 autoderefs,
2126 unsize,
62682a34 2127 index_ty);
1a4d82fc
JJ
2128
2129 let input_ty = fcx.infcx().next_ty_var();
2130
2131 // First, try built-in indexing.
2132 match (ty::index(adjusted_ty), &index_ty.sty) {
62682a34 2133 (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
1a4d82fc 2134 debug!("try_index_step: success, using built-in indexing");
9346a6ac
AL
2135 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2136 assert!(!unsize);
2137 fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
c34b1796 2138 return Some((tcx.types.usize, ty));
1a4d82fc
JJ
2139 }
2140 _ => {}
2141 }
2142
2143 // Try `IndexMut` first, if preferred.
2144 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2145 (PreferMutLvalue, Some(trait_did)) => {
2146 method::lookup_in_trait_adjusted(fcx,
2147 expr.span,
2148 Some(&*base_expr),
2149 token::intern("index_mut"),
2150 trait_did,
9346a6ac
AL
2151 autoderefs,
2152 unsize,
1a4d82fc
JJ
2153 adjusted_ty,
2154 Some(vec![input_ty]))
2155 }
2156 _ => None,
2157 };
2158
2159 // Otherwise, fall back to `Index`.
2160 let method = match (method, tcx.lang_items.index_trait()) {
2161 (None, Some(trait_did)) => {
2162 method::lookup_in_trait_adjusted(fcx,
2163 expr.span,
2164 Some(&*base_expr),
2165 token::intern("index"),
2166 trait_did,
9346a6ac
AL
2167 autoderefs,
2168 unsize,
1a4d82fc
JJ
2169 adjusted_ty,
2170 Some(vec![input_ty]))
2171 }
2172 (method, _) => method,
2173 };
2174
2175 // If some lookup succeeds, write callee into table and extract index/element
2176 // type from the method signature.
2177 // If some lookup succeeded, install method in table
2178 method.and_then(|method| {
2179 debug!("try_index_step: success, using overloaded indexing");
2180 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2181 map(|ret| (input_ty, ret.ty))
2182 })
2183}
2184
1a4d82fc
JJ
2185fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2186 sp: Span,
2187 method_fn_ty: Ty<'tcx>,
85aaf69f
SL
2188 callee_expr: &'tcx ast::Expr,
2189 args_no_rcvr: &'tcx [P<ast::Expr>],
85aaf69f
SL
2190 tuple_arguments: TupleArgumentsFlag,
2191 expected: Expectation<'tcx>)
1a4d82fc
JJ
2192 -> ty::FnOutput<'tcx> {
2193 if ty::type_is_error(method_fn_ty) {
2194 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2195
2196 let err_inputs = match tuple_arguments {
2197 DontTupleArguments => err_inputs,
2198 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2199 };
2200
2201 check_argument_types(fcx,
2202 sp,
85aaf69f
SL
2203 &err_inputs[..],
2204 &[],
1a4d82fc 2205 args_no_rcvr,
1a4d82fc
JJ
2206 false,
2207 tuple_arguments);
2208 ty::FnConverging(fcx.tcx().types.err)
2209 } else {
2210 match method_fn_ty.sty {
62682a34 2211 ty::TyBareFn(_, ref fty) => {
1a4d82fc 2212 // HACK(eddyb) ignore self in the definition (see above).
85aaf69f
SL
2213 let expected_arg_tys = expected_types_for_fn_args(fcx,
2214 sp,
2215 expected,
2216 fty.sig.0.output,
2217 &fty.sig.0.inputs[1..]);
1a4d82fc
JJ
2218 check_argument_types(fcx,
2219 sp,
85aaf69f
SL
2220 &fty.sig.0.inputs[1..],
2221 &expected_arg_tys[..],
1a4d82fc 2222 args_no_rcvr,
1a4d82fc
JJ
2223 fty.sig.0.variadic,
2224 tuple_arguments);
2225 fty.sig.0.output
2226 }
2227 _ => {
2228 fcx.tcx().sess.span_bug(callee_expr.span,
2229 "method without bare fn type");
2230 }
2231 }
2232 }
2233}
2234
2235/// Generic function that factors out common logic from function calls, method calls and overloaded
2236/// operators.
2237fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2238 sp: Span,
2239 fn_inputs: &[Ty<'tcx>],
85aaf69f
SL
2240 expected_arg_tys: &[Ty<'tcx>],
2241 args: &'tcx [P<ast::Expr>],
1a4d82fc
JJ
2242 variadic: bool,
2243 tuple_arguments: TupleArgumentsFlag) {
2244 let tcx = fcx.ccx.tcx;
2245
2246 // Grab the argument types, supplying fresh type variables
2247 // if the wrong number of arguments were supplied
2248 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2249 args.len()
2250 } else {
2251 1
2252 };
2253
85aaf69f 2254 let mut expected_arg_tys = expected_arg_tys;
1a4d82fc
JJ
2255 let expected_arg_count = fn_inputs.len();
2256 let formal_tys = if tuple_arguments == TupleArguments {
2257 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2258 match tuple_type.sty {
62682a34 2259 ty::TyTuple(ref arg_types) => {
1a4d82fc
JJ
2260 if arg_types.len() != args.len() {
2261 span_err!(tcx.sess, sp, E0057,
2262 "this function takes {} parameter{} but {} parameter{} supplied",
2263 arg_types.len(),
2264 if arg_types.len() == 1 {""} else {"s"},
2265 args.len(),
2266 if args.len() == 1 {" was"} else {"s were"});
c34b1796 2267 expected_arg_tys = &[];
1a4d82fc
JJ
2268 err_args(fcx.tcx(), args.len())
2269 } else {
85aaf69f
SL
2270 expected_arg_tys = match expected_arg_tys.get(0) {
2271 Some(&ty) => match ty.sty {
62682a34 2272 ty::TyTuple(ref tys) => &**tys,
85aaf69f
SL
2273 _ => &[]
2274 },
2275 None => &[]
2276 };
1a4d82fc
JJ
2277 (*arg_types).clone()
2278 }
2279 }
2280 _ => {
2281 span_err!(tcx.sess, sp, E0059,
2282 "cannot use call notation; the first type parameter \
2283 for the function trait is neither a tuple nor unit");
c34b1796 2284 expected_arg_tys = &[];
1a4d82fc
JJ
2285 err_args(fcx.tcx(), args.len())
2286 }
2287 }
2288 } else if expected_arg_count == supplied_arg_count {
85aaf69f 2289 fn_inputs.to_vec()
1a4d82fc
JJ
2290 } else if variadic {
2291 if supplied_arg_count >= expected_arg_count {
85aaf69f 2292 fn_inputs.to_vec()
1a4d82fc
JJ
2293 } else {
2294 span_err!(tcx.sess, sp, E0060,
2295 "this function takes at least {} parameter{} \
2296 but {} parameter{} supplied",
2297 expected_arg_count,
2298 if expected_arg_count == 1 {""} else {"s"},
2299 supplied_arg_count,
2300 if supplied_arg_count == 1 {" was"} else {"s were"});
c34b1796 2301 expected_arg_tys = &[];
1a4d82fc
JJ
2302 err_args(fcx.tcx(), supplied_arg_count)
2303 }
2304 } else {
2305 span_err!(tcx.sess, sp, E0061,
2306 "this function takes {} parameter{} but {} parameter{} supplied",
2307 expected_arg_count,
2308 if expected_arg_count == 1 {""} else {"s"},
2309 supplied_arg_count,
2310 if supplied_arg_count == 1 {" was"} else {"s were"});
c34b1796 2311 expected_arg_tys = &[];
1a4d82fc
JJ
2312 err_args(fcx.tcx(), supplied_arg_count)
2313 };
2314
2315 debug!("check_argument_types: formal_tys={:?}",
2316 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2317
2318 // Check the arguments.
2319 // We do this in a pretty awful way: first we typecheck any arguments
2320 // that are not anonymous functions, then we typecheck the anonymous
2321 // functions. This is so that we have more information about the types
2322 // of arguments when we typecheck the functions. This isn't really the
2323 // right way to do this.
2324 let xs = [false, true];
85aaf69f 2325 for check_blocks in &xs {
1a4d82fc
JJ
2326 let check_blocks = *check_blocks;
2327 debug!("check_blocks={}", check_blocks);
2328
85aaf69f
SL
2329 // More awful hacks: before we check argument types, try to do
2330 // an "opportunistic" vtable resolution of any trait bounds on
2331 // the call. This helps coercions.
1a4d82fc 2332 if check_blocks {
d9579d0f 2333 fcx.select_new_obligations();
1a4d82fc
JJ
2334 }
2335
2336 // For variadic functions, we don't have a declared type for all of
2337 // the arguments hence we only do our usual type checking with
2338 // the arguments who's types we do know.
2339 let t = if variadic {
2340 expected_arg_count
2341 } else if tuple_arguments == TupleArguments {
2342 args.len()
2343 } else {
2344 supplied_arg_count
2345 };
2346 for (i, arg) in args.iter().take(t).enumerate() {
2347 let is_block = match arg.node {
2348 ast::ExprClosure(..) => true,
2349 _ => false
2350 };
2351
2352 if is_block == check_blocks {
2353 debug!("checking the argument");
c34b1796 2354 let formal_ty = formal_tys[i];
1a4d82fc 2355
85aaf69f
SL
2356 // The special-cased logic below has three functions:
2357 // 1. Provide as good of an expected type as possible.
2358 let expected = expected_arg_tys.get(i).map(|&ty| {
2359 Expectation::rvalue_hint(ty)
2360 });
2361
2362 check_expr_with_unifier(fcx, &**arg,
2363 expected.unwrap_or(ExpectHasType(formal_ty)),
2364 NoPreference, || {
2365 // 2. Coerce to the most detailed type that could be coerced
2366 // to, which is `expected_ty` if `rvalue_hint` returns an
2367 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2368 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2369 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2370
2371 // 3. Relate the expected type and the formal one,
2372 // if the expected type was used for the coercion.
2373 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2374 });
1a4d82fc
JJ
2375 }
2376 }
2377 }
2378
2379 // We also need to make sure we at least write the ty of the other
2380 // arguments which we skipped above.
2381 if variadic {
2382 for arg in args.iter().skip(expected_arg_count) {
85aaf69f 2383 check_expr(fcx, &**arg);
1a4d82fc
JJ
2384
2385 // There are a few types which get autopromoted when passed via varargs
2386 // in C but we just error out instead and require explicit casts.
2387 let arg_ty = structurally_resolved_type(fcx, arg.span,
85aaf69f 2388 fcx.expr_ty(&**arg));
1a4d82fc 2389 match arg_ty.sty {
62682a34 2390 ty::TyFloat(ast::TyF32) => {
1a4d82fc
JJ
2391 fcx.type_error_message(arg.span,
2392 |t| {
2393 format!("can't pass an {} to variadic \
2394 function, cast to c_double", t)
2395 }, arg_ty, None);
2396 }
62682a34 2397 ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
1a4d82fc
JJ
2398 fcx.type_error_message(arg.span, |t| {
2399 format!("can't pass {} to variadic \
2400 function, cast to c_int",
2401 t)
2402 }, arg_ty, None);
2403 }
62682a34 2404 ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
1a4d82fc
JJ
2405 fcx.type_error_message(arg.span, |t| {
2406 format!("can't pass {} to variadic \
2407 function, cast to c_uint",
2408 t)
2409 }, arg_ty, None);
2410 }
2411 _ => {}
2412 }
2413 }
2414 }
2415}
2416
2417// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
c34b1796 2418fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
85aaf69f 2419 (0..len).map(|_| tcx.types.err).collect()
1a4d82fc
JJ
2420}
2421
2422fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2423 call_expr: &ast::Expr,
2424 output: ty::FnOutput<'tcx>) {
2425 fcx.write_ty(call_expr.id, match output {
2426 ty::FnConverging(output_ty) => output_ty,
2427 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2428 });
2429}
2430
2431// AST fragment checking
2432fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2433 lit: &ast::Lit,
2434 expected: Expectation<'tcx>)
2435 -> Ty<'tcx>
2436{
2437 let tcx = fcx.ccx.tcx;
2438
2439 match lit.node {
2440 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
c34b1796
AL
2441 ast::LitBinary(ref v) => {
2442 ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
2443 ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
2444 mutbl: ast::MutImmutable,
2445 })
1a4d82fc
JJ
2446 }
2447 ast::LitByte(_) => tcx.types.u8,
2448 ast::LitChar(_) => tcx.types.char,
2449 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2450 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2451 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
85aaf69f 2452 let opt_ty = expected.to_option(fcx).and_then(|ty| {
1a4d82fc 2453 match ty.sty {
62682a34
SL
2454 ty::TyInt(_) | ty::TyUint(_) => Some(ty),
2455 ty::TyChar => Some(tcx.types.u8),
2456 ty::TyRawPtr(..) => Some(tcx.types.usize),
2457 ty::TyBareFn(..) => Some(tcx.types.usize),
1a4d82fc
JJ
2458 _ => None
2459 }
2460 });
2461 opt_ty.unwrap_or_else(
2462 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2463 }
2464 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2465 ast::LitFloatUnsuffixed(_) => {
85aaf69f 2466 let opt_ty = expected.to_option(fcx).and_then(|ty| {
1a4d82fc 2467 match ty.sty {
62682a34 2468 ty::TyFloat(_) => Some(ty),
1a4d82fc
JJ
2469 _ => None
2470 }
2471 });
2472 opt_ty.unwrap_or_else(
2473 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2474 }
2475 ast::LitBool(_) => tcx.types.bool
2476 }
2477}
2478
1a4d82fc 2479pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 2480 expr: &'tcx ast::Expr,
1a4d82fc
JJ
2481 expected: Ty<'tcx>) {
2482 check_expr_with_unifier(
2483 fcx, expr, ExpectHasType(expected), NoPreference,
2484 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2485}
2486
2487fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 2488 expr: &'tcx ast::Expr,
1a4d82fc
JJ
2489 expected: Ty<'tcx>) {
2490 check_expr_with_unifier(
2491 fcx, expr, ExpectHasType(expected), NoPreference,
2492 || demand::coerce(fcx, expr.span, expected, expr));
2493}
2494
85aaf69f 2495fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
1a4d82fc
JJ
2496 expected: Ty<'tcx>) {
2497 check_expr_with_unifier(
2498 fcx, expr, ExpectHasType(expected), NoPreference,
2499 || ())
2500}
2501
2502fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 2503 expr: &'tcx ast::Expr,
1a4d82fc
JJ
2504 expected: Expectation<'tcx>) {
2505 check_expr_with_unifier(
2506 fcx, expr, expected, NoPreference,
2507 || ())
2508}
2509
2510fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 2511 expr: &'tcx ast::Expr,
1a4d82fc
JJ
2512 expected: Expectation<'tcx>,
2513 lvalue_pref: LvaluePreference)
2514{
2515 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2516}
2517
85aaf69f 2518fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
1a4d82fc
JJ
2519 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2520}
2521
85aaf69f
SL
2522fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2523 lvalue_pref: LvaluePreference) {
1a4d82fc
JJ
2524 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2525}
2526
2527// determine the `self` type, using fresh variables for all variables
d9579d0f 2528// declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
1a4d82fc
JJ
2529// would return ($0, $1) where $0 and $1 are freshly instantiated type
2530// variables.
2531pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2532 span: Span, // (potential) receiver for this impl
2533 did: ast::DefId)
2534 -> TypeAndSubsts<'tcx> {
2535 let tcx = fcx.tcx();
2536
2537 let ity = ty::lookup_item_type(tcx, did);
2538 let (n_tps, rps, raw_ty) =
2539 (ity.generics.types.len(subst::TypeSpace),
2540 ity.generics.regions.get_slice(subst::TypeSpace),
2541 ity.ty);
2542
2543 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2544 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2545 let substs = subst::Substs::new_type(tps, rps);
2546 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2547
2548 TypeAndSubsts { substs: substs, ty: substd_ty }
2549}
2550
1a4d82fc
JJ
2551/// Controls whether the arguments are tupled. This is used for the call
2552/// operator.
2553///
2554/// Tupling means that all call-side arguments are packed into a tuple and
2555/// passed as a single parameter. For example, if tupling is enabled, this
2556/// function:
2557///
c34b1796 2558/// fn f(x: (isize, isize))
1a4d82fc
JJ
2559///
2560/// Can be called as:
2561///
2562/// f(1, 2);
2563///
2564/// Instead of:
2565///
2566/// f((1, 2));
2567#[derive(Clone, Eq, PartialEq)]
2568enum TupleArgumentsFlag {
2569 DontTupleArguments,
2570 TupleArguments,
2571}
2572
85aaf69f
SL
2573/// Unifies the return type with the expected type early, for more coercions
2574/// and forward type information on the argument expressions.
2575fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2576 call_span: Span,
2577 expected_ret: Expectation<'tcx>,
2578 formal_ret: ty::FnOutput<'tcx>,
2579 formal_args: &[Ty<'tcx>])
2580 -> Vec<Ty<'tcx>> {
2581 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2582 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2583 fcx.infcx().commit_regions_if_ok(|| {
2584 // Attempt to apply a subtyping relationship between the formal
2585 // return type (likely containing type variables if the function
2586 // is polymorphic) and the expected return type.
2587 // No argument expectations are produced if unification fails.
2588 let origin = infer::Misc(call_span);
2589 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2590 // FIXME(#15760) can't use try! here, FromError doesn't default
2591 // to identity so the resulting type is not constrained.
2592 if let Err(e) = ures {
2593 return Err(e);
2594 }
2595
2596 // Record all the argument types, with the substitutions
2597 // produced from the above subtyping unification.
2598 Ok(formal_args.iter().map(|ty| {
2599 fcx.infcx().resolve_type_vars_if_possible(ty)
2600 }).collect())
2601 }).ok()
2602 } else {
2603 None
2604 }
2605 }).unwrap_or(vec![]);
62682a34
SL
2606 debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
2607 formal_args, formal_ret,
2608 expected_args, expected_ret);
85aaf69f
SL
2609 expected_args
2610}
2611
1a4d82fc
JJ
2612/// Invariant:
2613/// If an expression has any sub-expressions that result in a type error,
2614/// inspecting that expression's type with `ty::type_is_error` will return
2615/// true. Likewise, if an expression is known to diverge, inspecting its
2616/// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2617/// strict, _|_ can appear in the type of an expression that does not,
2618/// itself, diverge: for example, fn() -> _|_.)
2619/// Note that inspecting a type's structure *directly* may expose the fact
62682a34 2620/// that there are actually multiple representations for `TyError`, so avoid
1a4d82fc
JJ
2621/// that when err needs to be handled differently.
2622fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 2623 expr: &'tcx ast::Expr,
1a4d82fc
JJ
2624 expected: Expectation<'tcx>,
2625 lvalue_pref: LvaluePreference,
2626 unifier: F) where
2627 F: FnOnce(),
2628{
62682a34
SL
2629 debug!(">> typechecking: expr={:?} expected={:?}",
2630 expr, expected);
1a4d82fc
JJ
2631
2632 // Checks a method call.
85aaf69f
SL
2633 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2634 expr: &'tcx ast::Expr,
2635 method_name: ast::SpannedIdent,
2636 args: &'tcx [P<ast::Expr>],
2637 tps: &[P<ast::Ty>],
2638 expected: Expectation<'tcx>,
2639 lvalue_pref: LvaluePreference) {
1a4d82fc
JJ
2640 let rcvr = &*args[0];
2641 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2642
2643 // no need to check for bot/err -- callee does that
2644 let expr_t = structurally_resolved_type(fcx,
2645 expr.span,
2646 fcx.expr_ty(&*rcvr));
2647
2648 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2649 let fn_ty = match method::lookup(fcx,
2650 method_name.span,
2651 method_name.node.name,
2652 expr_t,
2653 tps,
2654 expr,
2655 rcvr) {
2656 Ok(method) => {
2657 let method_ty = method.ty;
2658 let method_call = MethodCall::expr(expr.id);
2659 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2660 method_ty
2661 }
2662 Err(error) => {
85aaf69f 2663 method::report_error(fcx, method_name.span, expr_t,
c34b1796 2664 method_name.node.name, Some(rcvr), error);
1a4d82fc
JJ
2665 fcx.write_error(expr.id);
2666 fcx.tcx().types.err
2667 }
2668 };
2669
2670 // Call the generic checker.
1a4d82fc
JJ
2671 let ret_ty = check_method_argument_types(fcx,
2672 method_name.span,
2673 fn_ty,
2674 expr,
85aaf69f 2675 &args[1..],
85aaf69f
SL
2676 DontTupleArguments,
2677 expected);
1a4d82fc
JJ
2678
2679 write_call(fcx, expr, ret_ty);
2680 }
2681
2682 // A generic function for checking the then and else in an if
2683 // or if-else.
2684 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f
SL
2685 cond_expr: &'tcx ast::Expr,
2686 then_blk: &'tcx ast::Block,
2687 opt_else_expr: Option<&'tcx ast::Expr>,
1a4d82fc
JJ
2688 id: ast::NodeId,
2689 sp: Span,
2690 expected: Expectation<'tcx>) {
2691 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2692
2693 let expected = expected.adjust_for_branches(fcx);
2694 check_block_with_expected(fcx, then_blk, expected);
2695 let then_ty = fcx.node_ty(then_blk.id);
2696
2697 let branches_ty = match opt_else_expr {
2698 Some(ref else_expr) => {
2699 check_expr_with_expectation(fcx, &**else_expr, expected);
2700 let else_ty = fcx.expr_ty(&**else_expr);
2701 infer::common_supertype(fcx.infcx(),
2702 infer::IfExpression(sp),
2703 true,
2704 then_ty,
2705 else_ty)
2706 }
2707 None => {
2708 infer::common_supertype(fcx.infcx(),
2709 infer::IfExpressionWithNoElse(sp),
2710 false,
2711 then_ty,
2712 ty::mk_nil(fcx.tcx()))
2713 }
2714 };
2715
2716 let cond_ty = fcx.expr_ty(cond_expr);
2717 let if_ty = if ty::type_is_error(cond_ty) {
2718 fcx.tcx().types.err
2719 } else {
2720 branches_ty
2721 };
2722
2723 fcx.write_ty(id, if_ty);
2724 }
2725
1a4d82fc 2726 // Check field access expressions
85aaf69f
SL
2727 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2728 expr: &'tcx ast::Expr,
2729 lvalue_pref: LvaluePreference,
2730 base: &'tcx ast::Expr,
2731 field: &ast::SpannedIdent) {
1a4d82fc
JJ
2732 let tcx = fcx.ccx.tcx;
2733 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2734 let expr_t = structurally_resolved_type(fcx, expr.span,
2735 fcx.expr_ty(base));
2736 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
85aaf69f
SL
2737 let (_, autoderefs, field_ty) = autoderef(fcx,
2738 expr.span,
2739 expr_t,
2740 Some(base),
2741 UnresolvedTypeAction::Error,
2742 lvalue_pref,
2743 |base_t, _| {
1a4d82fc 2744 match base_t.sty {
62682a34
SL
2745 ty::TyStruct(base_id, substs) => {
2746 debug!("struct named {:?}", base_t);
1a4d82fc 2747 let fields = ty::lookup_struct_fields(tcx, base_id);
85aaf69f
SL
2748 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
2749 field.node.name, &(*substs))
1a4d82fc
JJ
2750 }
2751 _ => None
2752 }
2753 });
2754 match field_ty {
2755 Some(field_ty) => {
2756 fcx.write_ty(expr.id, field_ty);
9346a6ac 2757 fcx.write_autoderef_adjustment(base.id, autoderefs);
1a4d82fc
JJ
2758 return;
2759 }
2760 None => {}
2761 }
2762
2763 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2764 fcx.type_error_message(
2765 field.span,
2766 |actual| {
2767 format!("attempted to take value of method `{}` on type \
2768 `{}`", token::get_ident(field.node), actual)
2769 },
2770 expr_t, None);
2771
c34b1796 2772 tcx.sess.fileline_help(field.span,
1a4d82fc
JJ
2773 "maybe a `()` to call it is missing? \
2774 If not, try an anonymous function");
2775 } else {
2776 fcx.type_error_message(
2777 expr.span,
2778 |actual| {
2779 format!("attempted access of field `{}` on \
2780 type `{}`, but no field with that \
2781 name was found",
2782 token::get_ident(field.node),
2783 actual)
2784 },
2785 expr_t, None);
62682a34 2786 if let ty::TyStruct(did, _) = expr_t.sty {
9346a6ac 2787 suggest_field_names(did, field, tcx, vec![]);
85aaf69f 2788 }
1a4d82fc
JJ
2789 }
2790
2791 fcx.write_error(expr.id);
2792 }
2793
85aaf69f
SL
2794 // displays hints about the closest matches in field names
2795 fn suggest_field_names<'tcx>(id : DefId,
2796 field : &ast::SpannedIdent,
2797 tcx : &ty::ctxt<'tcx>,
2798 skip : Vec<&str>) {
2799 let ident = token::get_ident(field.node);
2800 let name = &ident;
2801 // only find fits with at least one matching letter
2802 let mut best_dist = name.len();
2803 let fields = ty::lookup_struct_fields(tcx, id);
2804 let mut best = None;
2805 for elem in &fields {
2806 let n = elem.name.as_str();
2807 // ignore already set fields
2808 if skip.iter().any(|&x| x == n) {
2809 continue;
2810 }
c34b1796
AL
2811 // ignore private fields from non-local crates
2812 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2813 continue;
2814 }
85aaf69f
SL
2815 let dist = lev_distance(n, name);
2816 if dist < best_dist {
2817 best = Some(n);
2818 best_dist = dist;
2819 }
2820 }
2821 if let Some(n) = best {
2822 tcx.sess.span_help(field.span,
2823 &format!("did you mean `{}`?", n));
2824 }
2825 }
2826
1a4d82fc 2827 // Check tuple index expressions
85aaf69f
SL
2828 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2829 expr: &'tcx ast::Expr,
2830 lvalue_pref: LvaluePreference,
2831 base: &'tcx ast::Expr,
c34b1796 2832 idx: codemap::Spanned<usize>) {
1a4d82fc
JJ
2833 let tcx = fcx.ccx.tcx;
2834 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2835 let expr_t = structurally_resolved_type(fcx, expr.span,
2836 fcx.expr_ty(base));
2837 let mut tuple_like = false;
2838 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
85aaf69f
SL
2839 let (_, autoderefs, field_ty) = autoderef(fcx,
2840 expr.span,
2841 expr_t,
2842 Some(base),
2843 UnresolvedTypeAction::Error,
2844 lvalue_pref,
2845 |base_t, _| {
1a4d82fc 2846 match base_t.sty {
62682a34 2847 ty::TyStruct(base_id, substs) => {
1a4d82fc
JJ
2848 tuple_like = ty::is_tuple_struct(tcx, base_id);
2849 if tuple_like {
62682a34 2850 debug!("tuple struct named {:?}", base_t);
1a4d82fc 2851 let fields = ty::lookup_struct_fields(tcx, base_id);
85aaf69f
SL
2852 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
2853 idx.node, &(*substs))
1a4d82fc
JJ
2854 } else {
2855 None
2856 }
2857 }
62682a34 2858 ty::TyTuple(ref v) => {
1a4d82fc
JJ
2859 tuple_like = true;
2860 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2861 }
2862 _ => None
2863 }
2864 });
2865 match field_ty {
2866 Some(field_ty) => {
2867 fcx.write_ty(expr.id, field_ty);
9346a6ac 2868 fcx.write_autoderef_adjustment(base.id, autoderefs);
1a4d82fc
JJ
2869 return;
2870 }
2871 None => {}
2872 }
2873 fcx.type_error_message(
2874 expr.span,
2875 |actual| {
2876 if tuple_like {
2877 format!("attempted out-of-bounds tuple index `{}` on \
2878 type `{}`",
2879 idx.node,
2880 actual)
2881 } else {
2882 format!("attempted tuple index `{}` on type `{}`, but the \
2883 type was not a tuple or tuple struct",
2884 idx.node,
2885 actual)
2886 }
2887 },
2888 expr_t, None);
2889
2890 fcx.write_error(expr.id);
2891 }
2892
2893 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2894 struct_ty: Ty<'tcx>,
2895 span: Span,
2896 class_id: ast::DefId,
2897 node_id: ast::NodeId,
2898 substitutions: &'tcx subst::Substs<'tcx>,
2899 field_types: &[ty::field_ty],
85aaf69f 2900 ast_fields: &'tcx [ast::Field],
1a4d82fc
JJ
2901 check_completeness: bool,
2902 enum_id_opt: Option<ast::DefId>) {
2903 let tcx = fcx.ccx.tcx;
2904
85aaf69f 2905 let mut class_field_map = FnvHashMap();
1a4d82fc 2906 let mut fields_found = 0;
85aaf69f 2907 for field in field_types {
1a4d82fc
JJ
2908 class_field_map.insert(field.name, (field.id, false));
2909 }
2910
2911 let mut error_happened = false;
2912
2913 // Typecheck each field.
85aaf69f 2914 for field in ast_fields {
1a4d82fc
JJ
2915 let mut expected_field_type = tcx.types.err;
2916
85aaf69f 2917 let pair = class_field_map.get(&field.ident.node.name).cloned();
1a4d82fc
JJ
2918 match pair {
2919 None => {
2920 fcx.type_error_message(
2921 field.ident.span,
2922 |actual| match enum_id_opt {
2923 Some(enum_id) => {
2924 let variant_type = ty::enum_variant_with_id(tcx,
2925 enum_id,
2926 class_id);
2927 format!("struct variant `{}::{}` has no field named `{}`",
2928 actual, variant_type.name.as_str(),
2929 token::get_ident(field.ident.node))
2930 }
2931 None => {
2932 format!("structure `{}` has no field named `{}`",
2933 actual,
2934 token::get_ident(field.ident.node))
2935 }
2936 },
2937 struct_ty,
2938 None);
85aaf69f
SL
2939 // prevent all specified fields from being suggested
2940 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
2941 let actual_id = match enum_id_opt {
2942 Some(_) => class_id,
2943 None => ty::ty_to_def_id(struct_ty).unwrap()
2944 };
2945 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
1a4d82fc
JJ
2946 error_happened = true;
2947 }
2948 Some((_, true)) => {
2949 span_err!(fcx.tcx().sess, field.ident.span, E0062,
2950 "field `{}` specified more than once",
2951 token::get_ident(field.ident.node));
2952 error_happened = true;
2953 }
2954 Some((field_id, false)) => {
2955 expected_field_type =
2956 ty::lookup_field_type(
2957 tcx, class_id, field_id, substitutions);
2958 expected_field_type =
2959 fcx.normalize_associated_types_in(
2960 field.span, &expected_field_type);
2961 class_field_map.insert(
2962 field.ident.node.name, (field_id, true));
2963 fields_found += 1;
2964 }
2965 }
2966
2967 // Make sure to give a type to the field even if there's
2968 // an error, so we can continue typechecking
2969 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
2970 }
2971
2972 if error_happened {
2973 fcx.write_error(node_id);
2974 }
2975
2976 if check_completeness && !error_happened {
2977 // Make sure the programmer specified all the fields.
2978 assert!(fields_found <= field_types.len());
2979 if fields_found < field_types.len() {
2980 let mut missing_fields = Vec::new();
85aaf69f 2981 for class_field in field_types {
1a4d82fc 2982 let name = class_field.name;
c34b1796 2983 let (_, seen) = *class_field_map.get(&name).unwrap();
1a4d82fc
JJ
2984 if !seen {
2985 missing_fields.push(
85aaf69f 2986 format!("`{}`", &token::get_name(name)))
1a4d82fc
JJ
2987 }
2988 }
2989
2990 span_err!(tcx.sess, span, E0063,
2991 "missing field{}: {}",
2992 if missing_fields.len() == 1 {""} else {"s"},
2993 missing_fields.connect(", "));
2994 }
2995 }
2996
2997 if !error_happened {
2998 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2999 class_id, substitutions));
3000 }
3001 }
3002
85aaf69f
SL
3003 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3004 id: ast::NodeId,
3005 span: codemap::Span,
3006 class_id: ast::DefId,
3007 fields: &'tcx [ast::Field],
3008 base_expr: Option<&'tcx ast::Expr>) {
1a4d82fc
JJ
3009 let tcx = fcx.ccx.tcx;
3010
3011 // Generate the struct type.
3012 let TypeAndSubsts {
3013 ty: mut struct_type,
3014 substs: struct_substs
3015 } = fcx.instantiate_type(span, class_id);
3016
3017 // Look up and check the fields.
3018 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3019 check_struct_or_variant_fields(fcx,
3020 struct_type,
3021 span,
3022 class_id,
3023 id,
3024 fcx.ccx.tcx.mk_substs(struct_substs),
85aaf69f 3025 &class_fields[..],
1a4d82fc
JJ
3026 fields,
3027 base_expr.is_none(),
3028 None);
3029 if ty::type_is_error(fcx.node_ty(id)) {
3030 struct_type = tcx.types.err;
3031 }
3032
3033 // Check the base expression if necessary.
3034 match base_expr {
3035 None => {}
3036 Some(base_expr) => {
3037 check_expr_has_type(fcx, &*base_expr, struct_type);
3038 }
3039 }
3040
3041 // Write in the resulting type.
3042 fcx.write_ty(id, struct_type);
3043 }
3044
85aaf69f
SL
3045 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3046 id: ast::NodeId,
3047 span: codemap::Span,
3048 enum_id: ast::DefId,
3049 variant_id: ast::DefId,
3050 fields: &'tcx [ast::Field]) {
1a4d82fc
JJ
3051 let tcx = fcx.ccx.tcx;
3052
3053 // Look up the number of type parameters and the raw type, and
3054 // determine whether the enum is region-parameterized.
3055 let TypeAndSubsts {
3056 ty: enum_type,
3057 substs: substitutions
3058 } = fcx.instantiate_type(span, enum_id);
3059
3060 // Look up and check the enum variant fields.
3061 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3062 check_struct_or_variant_fields(fcx,
3063 enum_type,
3064 span,
3065 variant_id,
3066 id,
3067 fcx.ccx.tcx.mk_substs(substitutions),
85aaf69f 3068 &variant_fields[..],
1a4d82fc
JJ
3069 fields,
3070 true,
3071 Some(enum_id));
3072 fcx.write_ty(id, enum_type);
3073 }
3074
85aaf69f
SL
3075 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3076 id: ast::NodeId,
3077 fields: &'tcx [ast::Field],
3078 base_expr: &'tcx Option<P<ast::Expr>>) {
1a4d82fc
JJ
3079 // Make sure to still write the types
3080 // otherwise we might ICE
3081 fcx.write_error(id);
85aaf69f 3082 for field in fields {
1a4d82fc
JJ
3083 check_expr(fcx, &*field.expr);
3084 }
3085 match *base_expr {
3086 Some(ref base) => check_expr(fcx, &**base),
3087 None => {}
3088 }
3089 }
3090
3091 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3092
3093 let tcx = fcx.ccx.tcx;
3094 let id = expr.id;
3095 match expr.node {
3096 ast::ExprBox(ref opt_place, ref subexpr) => {
3097 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3098 check_expr(fcx, &**subexpr);
3099
3100 let mut checked = false;
3101 opt_place.as_ref().map(|place| match place.node {
c34b1796 3102 ast::ExprPath(None, ref path) => {
d9579d0f
AL
3103 // FIXME(pcwalton): For now we hardcode the only permissible
3104 // place: the exchange heap.
c34b1796 3105 let definition = lookup_full_def(tcx, path.span, place.id);
1a4d82fc
JJ
3106 let def_id = definition.def_id();
3107 let referent_ty = fcx.expr_ty(&**subexpr);
3108 if tcx.lang_items.exchange_heap() == Some(def_id) {
3109 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3110 checked = true
3111 }
3112 }
3113 _ => {}
3114 });
3115
3116 if !checked {
3117 span_err!(tcx.sess, expr.span, E0066,
d9579d0f 3118 "only the exchange heap is currently supported");
1a4d82fc
JJ
3119 fcx.write_ty(id, tcx.types.err);
3120 }
3121 }
3122
3123 ast::ExprLit(ref lit) => {
3124 let typ = check_lit(fcx, &**lit, expected);
3125 fcx.write_ty(id, typ);
3126 }
3127 ast::ExprBinary(op, ref lhs, ref rhs) => {
c34b1796 3128 op::check_binop(fcx, expr, op, lhs, rhs);
1a4d82fc
JJ
3129 }
3130 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
c34b1796 3131 op::check_binop_assign(fcx, expr, op, lhs, rhs);
1a4d82fc
JJ
3132 }
3133 ast::ExprUnary(unop, ref oprnd) => {
85aaf69f 3134 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
1a4d82fc
JJ
3135 match unop {
3136 ast::UnUniq => match ty.sty {
62682a34 3137 ty::TyBox(ty) => {
1a4d82fc
JJ
3138 Expectation::rvalue_hint(ty)
3139 }
3140 _ => {
3141 NoExpectation
3142 }
3143 },
3144 ast::UnNot | ast::UnNeg => {
3145 expected
3146 }
3147 ast::UnDeref => {
3148 NoExpectation
3149 }
3150 }
3151 });
3152 let lvalue_pref = match unop {
3153 ast::UnDeref => lvalue_pref,
3154 _ => NoPreference
3155 };
3156 check_expr_with_expectation_and_lvalue_pref(
3157 fcx, &**oprnd, expected_inner, lvalue_pref);
3158 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3159
3160 if !ty::type_is_error(oprnd_t) {
3161 match unop {
3162 ast::UnUniq => {
3163 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3164 }
3165 ast::UnDeref => {
3166 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3167 oprnd_t = match ty::deref(oprnd_t, true) {
3168 Some(mt) => mt.ty,
3169 None => match try_overloaded_deref(fcx, expr.span,
3170 Some(MethodCall::expr(expr.id)),
3171 Some(&**oprnd), oprnd_t, lvalue_pref) {
3172 Some(mt) => mt.ty,
3173 None => {
62682a34
SL
3174 fcx.type_error_message(expr.span, |actual| {
3175 format!("type `{}` cannot be \
3176 dereferenced", actual)
3177 }, oprnd_t, None);
1a4d82fc
JJ
3178 tcx.types.err
3179 }
3180 }
3181 };
3182 }
3183 ast::UnNot => {
3184 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3185 oprnd_t);
3186 if !(ty::type_is_integral(oprnd_t) ||
62682a34 3187 oprnd_t.sty == ty::TyBool) {
c34b1796
AL
3188 oprnd_t = op::check_user_unop(fcx, "!", "not",
3189 tcx.lang_items.not_trait(),
3190 expr, &**oprnd, oprnd_t, unop);
1a4d82fc
JJ
3191 }
3192 }
3193 ast::UnNeg => {
3194 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3195 oprnd_t);
3196 if !(ty::type_is_integral(oprnd_t) ||
3197 ty::type_is_fp(oprnd_t)) {
c34b1796
AL
3198 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3199 tcx.lang_items.neg_trait(),
3200 expr, &**oprnd, oprnd_t, unop);
3201 }
62682a34 3202 if let ty::TyUint(_) = oprnd_t.sty {
c34b1796
AL
3203 if !tcx.sess.features.borrow().negate_unsigned {
3204 feature_gate::emit_feature_err(
3205 &tcx.sess.parse_sess.span_diagnostic,
3206 "negate_unsigned",
3207 expr.span,
3208 "unary negation of unsigned integers may be removed in the future");
3209 }
1a4d82fc
JJ
3210 }
3211 }
3212 }
3213 }
3214 fcx.write_ty(id, oprnd_t);
3215 }
3216 ast::ExprAddrOf(mutbl, ref oprnd) => {
85aaf69f 3217 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
1a4d82fc 3218 match ty.sty {
62682a34 3219 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
1a4d82fc
JJ
3220 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3221 // Lvalues may legitimately have unsized types.
3222 // For example, dereferences of a fat pointer and
3223 // the last field of a struct can be unsized.
3224 ExpectHasType(mt.ty)
3225 } else {
3226 Expectation::rvalue_hint(mt.ty)
3227 }
3228 }
3229 _ => NoExpectation
3230 }
3231 });
62682a34 3232 let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
1a4d82fc
JJ
3233 check_expr_with_expectation_and_lvalue_pref(fcx,
3234 &**oprnd,
3235 hint,
3236 lvalue_pref);
3237
3238 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3239 let oprnd_t = if ty::type_is_error(tm.ty) {
3240 tcx.types.err
3241 } else {
3242 // Note: at this point, we cannot say what the best lifetime
3243 // is to use for resulting pointer. We want to use the
3244 // shortest lifetime possible so as to avoid spurious borrowck
3245 // errors. Moreover, the longest lifetime will depend on the
3246 // precise details of the value whose address is being taken
3247 // (and how long it is valid), which we don't know yet until type
3248 // inference is complete.
3249 //
3250 // Therefore, here we simply generate a region variable. The
3251 // region inferencer will then select the ultimate value.
3252 // Finally, borrowck is charged with guaranteeing that the
3253 // value whose address was taken can actually be made to live
3254 // as long as it needs to live.
85aaf69f
SL
3255 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3256 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
1a4d82fc
JJ
3257 };
3258 fcx.write_ty(id, oprnd_t);
3259 }
c34b1796
AL
3260 ast::ExprPath(ref maybe_qself, ref path) => {
3261 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3262 fcx.to_ty(&qself.ty)
3263 });
85aaf69f 3264
c34b1796
AL
3265 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3266 d
3267 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3268 // Create some fake resolution that can't possibly be a type.
3269 def::PathResolution {
3270 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3271 last_private: LastMod(AllPublic),
3272 depth: path.segments.len()
3273 }
3274 } else {
3275 tcx.sess.span_bug(expr.span,
62682a34 3276 &format!("unbound path {:?}", expr))
c34b1796
AL
3277 };
3278
d9579d0f
AL
3279 if let Some((opt_ty, segments, def)) =
3280 resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
3281 expr.span, expr.id) {
9346a6ac
AL
3282 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
3283 expr.span,
3284 def);
3285 instantiate_path(fcx,
d9579d0f 3286 segments,
9346a6ac
AL
3287 scheme,
3288 &predicates,
d9579d0f 3289 opt_ty,
9346a6ac
AL
3290 def,
3291 expr.span,
3292 id);
c34b1796 3293 }
1a4d82fc
JJ
3294
3295 // We always require that the type provided as the value for
3296 // a type parameter outlives the moment of instantiation.
3297 constrain_path_type_parameters(fcx, expr);
3298 }
3299 ast::ExprInlineAsm(ref ia) => {
85aaf69f 3300 for &(_, ref input) in &ia.inputs {
1a4d82fc
JJ
3301 check_expr(fcx, &**input);
3302 }
85aaf69f 3303 for &(_, ref out, _) in &ia.outputs {
1a4d82fc
JJ
3304 check_expr(fcx, &**out);
3305 }
3306 fcx.write_nil(id);
3307 }
3308 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3309 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3310 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3311 ast::ExprRet(ref expr_opt) => {
3312 match fcx.ret_ty {
3313 ty::FnConverging(result_type) => {
3314 match *expr_opt {
3315 None =>
3316 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3317 result_type, ty::mk_nil(fcx.tcx())) {
3318 span_err!(tcx.sess, expr.span, E0069,
d9579d0f
AL
3319 "`return;` in a function whose return type is \
3320 not `()`");
1a4d82fc
JJ
3321 },
3322 Some(ref e) => {
3323 check_expr_coercable_to_type(fcx, &**e, result_type);
3324 }
3325 }
3326 }
3327 ty::FnDiverging => {
3328 if let Some(ref e) = *expr_opt {
3329 check_expr(fcx, &**e);
3330 }
3331 span_err!(tcx.sess, expr.span, E0166,
3332 "`return` in a function declared as diverging");
3333 }
3334 }
3335 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3336 }
3337 ast::ExprParen(ref a) => {
3338 check_expr_with_expectation_and_lvalue_pref(fcx,
3339 &**a,
3340 expected,
3341 lvalue_pref);
3342 fcx.write_ty(id, fcx.expr_ty(&**a));
3343 }
3344 ast::ExprAssign(ref lhs, ref rhs) => {
3345 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3346
3347 let tcx = fcx.tcx();
3348 if !ty::expr_is_lval(tcx, &**lhs) {
3349 span_err!(tcx.sess, expr.span, E0070,
3350 "illegal left-hand side expression");
3351 }
3352
3353 let lhs_ty = fcx.expr_ty(&**lhs);
3354 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3355 let rhs_ty = fcx.expr_ty(&**rhs);
3356
3357 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3358
3359 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3360 fcx.write_error(id);
3361 } else {
3362 fcx.write_nil(id);
3363 }
3364 }
3365 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3366 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3367 id, expr.span, expected);
3368 }
3369 ast::ExprIfLet(..) => {
3370 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3371 }
3372 ast::ExprWhile(ref cond, ref body, _) => {
3373 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3374 check_block_no_value(fcx, &**body);
3375 let cond_ty = fcx.expr_ty(&**cond);
3376 let body_ty = fcx.node_ty(body.id);
3377 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3378 fcx.write_error(id);
3379 }
3380 else {
3381 fcx.write_nil(id);
3382 }
3383 }
3384 ast::ExprWhileLet(..) => {
3385 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3386 }
85aaf69f
SL
3387 ast::ExprForLoop(..) => {
3388 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
1a4d82fc
JJ
3389 }
3390 ast::ExprLoop(ref body, _) => {
3391 check_block_no_value(fcx, &**body);
3392 if !may_break(tcx, expr.id, &**body) {
3393 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3394 } else {
3395 fcx.write_nil(id);
3396 }
3397 }
3398 ast::ExprMatch(ref discrim, ref arms, match_src) => {
85aaf69f 3399 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
1a4d82fc 3400 }
85aaf69f
SL
3401 ast::ExprClosure(capture, ref decl, ref body) => {
3402 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
1a4d82fc
JJ
3403 }
3404 ast::ExprBlock(ref b) => {
3405 check_block_with_expected(fcx, &**b, expected);
3406 fcx.write_ty(id, fcx.node_ty(b.id));
3407 }
3408 ast::ExprCall(ref callee, ref args) => {
85aaf69f 3409 callee::check_call(fcx, expr, &**callee, &args[..], expected);
1a4d82fc
JJ
3410 }
3411 ast::ExprMethodCall(ident, ref tps, ref args) => {
85aaf69f 3412 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
1a4d82fc
JJ
3413 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3414 let args_err = arg_tys.fold(false,
3415 |rest_err, a| {
3416 rest_err || ty::type_is_error(a)});
3417 if args_err {
3418 fcx.write_error(id);
3419 }
3420 }
3421 ast::ExprCast(ref e, ref t) => {
3422 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
c34b1796
AL
3423 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3424 }
3425
3426 // Find the type of `e`. Supply hints based on the type we are casting to,
3427 // if appropriate.
62682a34
SL
3428 let t_cast = fcx.to_ty(t);
3429 let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
3430 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
3431 let t_expr = fcx.expr_ty(e);
c34b1796
AL
3432
3433 // Eagerly check for some obvious errors.
62682a34 3434 if ty::type_is_error(t_expr) {
c34b1796 3435 fcx.write_error(id);
62682a34
SL
3436 } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
3437 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
c34b1796
AL
3438 } else {
3439 // Write a type for the whole expression, assuming everything is going
3440 // to work out Ok.
62682a34 3441 fcx.write_ty(id, t_cast);
c34b1796
AL
3442
3443 // Defer other checks until we're done type checking.
3444 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
62682a34 3445 let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
9346a6ac 3446 deferred_cast_checks.push(cast_check);
1a4d82fc 3447 }
1a4d82fc
JJ
3448 }
3449 ast::ExprVec(ref args) => {
85aaf69f 3450 let uty = expected.to_option(fcx).and_then(|uty| {
1a4d82fc 3451 match uty.sty {
62682a34 3452 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
1a4d82fc
JJ
3453 _ => None
3454 }
3455 });
3456
3457 let typ = match uty {
3458 Some(uty) => {
85aaf69f 3459 for e in args {
1a4d82fc
JJ
3460 check_expr_coercable_to_type(fcx, &**e, uty);
3461 }
3462 uty
3463 }
3464 None => {
3465 let t: Ty = fcx.infcx().next_ty_var();
85aaf69f 3466 for e in args {
1a4d82fc
JJ
3467 check_expr_has_type(fcx, &**e, t);
3468 }
3469 t
3470 }
3471 };
3472 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3473 fcx.write_ty(id, typ);
3474 }
3475 ast::ExprRepeat(ref element, ref count_expr) => {
c34b1796 3476 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
1a4d82fc
JJ
3477 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3478
3479 let uty = match expected {
3480 ExpectHasType(uty) => {
3481 match uty.sty {
62682a34 3482 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
1a4d82fc
JJ
3483 _ => None
3484 }
3485 }
3486 _ => None
3487 };
3488
3489 let (element_ty, t) = match uty {
3490 Some(uty) => {
3491 check_expr_coercable_to_type(fcx, &**element, uty);
3492 (uty, uty)
3493 }
3494 None => {
3495 let t: Ty = fcx.infcx().next_ty_var();
3496 check_expr_has_type(fcx, &**element, t);
3497 (fcx.expr_ty(&**element), t)
3498 }
3499 };
3500
3501 if count > 1 {
3502 // For [foo, ..n] where n > 1, `foo` must have
3503 // Copy type:
3504 fcx.require_type_meets(
3505 t,
3506 expr.span,
3507 traits::RepeatVec,
3508 ty::BoundCopy);
3509 }
3510
3511 if ty::type_is_error(element_ty) {
3512 fcx.write_error(id);
3513 } else {
3514 let t = ty::mk_vec(tcx, t, Some(count));
3515 fcx.write_ty(id, t);
3516 }
3517 }
3518 ast::ExprTup(ref elts) => {
85aaf69f 3519 let flds = expected.only_has_type(fcx).and_then(|ty| {
1a4d82fc 3520 match ty.sty {
62682a34 3521 ty::TyTuple(ref flds) => Some(&flds[..]),
1a4d82fc
JJ
3522 _ => None
3523 }
3524 });
3525 let mut err_field = false;
3526
3527 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3528 let t = match flds {
3529 Some(ref fs) if i < fs.len() => {
3530 let ety = fs[i];
3531 check_expr_coercable_to_type(fcx, &**e, ety);
3532 ety
3533 }
3534 _ => {
3535 check_expr_with_expectation(fcx, &**e, NoExpectation);
3536 fcx.expr_ty(&**e)
3537 }
3538 };
3539 err_field = err_field || ty::type_is_error(t);
3540 t
3541 }).collect();
3542 if err_field {
3543 fcx.write_error(id);
3544 } else {
3545 let typ = ty::mk_tup(tcx, elt_ts);
3546 fcx.write_ty(id, typ);
3547 }
3548 }
3549 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3550 // Resolve the path.
c34b1796 3551 let def = lookup_full_def(tcx, path.span, id);
1a4d82fc 3552 let struct_id = match def {
c34b1796 3553 def::DefVariant(enum_id, variant_id, true) => {
1a4d82fc 3554 check_struct_enum_variant(fcx, id, expr.span, enum_id,
85aaf69f 3555 variant_id, &fields[..]);
1a4d82fc
JJ
3556 enum_id
3557 }
c34b1796 3558 def::DefTrait(def_id) => {
1a4d82fc
JJ
3559 span_err!(tcx.sess, path.span, E0159,
3560 "use of trait `{}` as a struct constructor",
3561 pprust::path_to_string(path));
3562 check_struct_fields_on_error(fcx,
3563 id,
85aaf69f 3564 &fields[..],
1a4d82fc
JJ
3565 base_expr);
3566 def_id
3567 },
c34b1796 3568 def => {
1a4d82fc
JJ
3569 // Verify that this was actually a struct.
3570 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3571 match typ.ty.sty {
62682a34 3572 ty::TyStruct(struct_did, _) => {
1a4d82fc
JJ
3573 check_struct_constructor(fcx,
3574 id,
3575 expr.span,
3576 struct_did,
85aaf69f 3577 &fields[..],
1a4d82fc
JJ
3578 base_expr.as_ref().map(|e| &**e));
3579 }
3580 _ => {
3581 span_err!(tcx.sess, path.span, E0071,
3582 "`{}` does not name a structure",
3583 pprust::path_to_string(path));
3584 check_struct_fields_on_error(fcx,
3585 id,
85aaf69f 3586 &fields[..],
1a4d82fc
JJ
3587 base_expr);
3588 }
3589 }
3590
3591 def.def_id()
3592 }
1a4d82fc
JJ
3593 };
3594
3595 // Turn the path into a type and verify that that type unifies with
3596 // the resulting structure type. This is needed to handle type
3597 // parameters correctly.
3598 let actual_structure_type = fcx.expr_ty(&*expr);
3599 if !ty::type_is_error(actual_structure_type) {
3600 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3601 match fcx.mk_subty(false,
3602 infer::Misc(path.span),
3603 actual_structure_type,
3604 type_and_substs.ty) {
3605 Ok(()) => {}
3606 Err(type_error) => {
85aaf69f
SL
3607 span_err!(fcx.tcx().sess, path.span, E0235,
3608 "structure constructor specifies a \
1a4d82fc
JJ
3609 structure of type `{}`, but this \
3610 structure has type `{}`: {}",
3611 fcx.infcx()
3612 .ty_to_string(type_and_substs.ty),
3613 fcx.infcx()
3614 .ty_to_string(
3615 actual_structure_type),
62682a34 3616 type_error);
9346a6ac 3617 ty::note_and_explain_type_err(tcx, &type_error, path.span);
1a4d82fc
JJ
3618 }
3619 }
3620 }
3621
3622 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3623 }
3624 ast::ExprField(ref base, ref field) => {
3625 check_field(fcx, expr, lvalue_pref, &**base, field);
3626 }
3627 ast::ExprTupField(ref base, idx) => {
3628 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3629 }
3630 ast::ExprIndex(ref base, ref idx) => {
3631 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
d9579d0f
AL
3632 check_expr(fcx, &**idx);
3633
1a4d82fc 3634 let base_t = fcx.expr_ty(&**base);
d9579d0f
AL
3635 let idx_t = fcx.expr_ty(&**idx);
3636
1a4d82fc
JJ
3637 if ty::type_is_error(base_t) {
3638 fcx.write_ty(id, base_t);
d9579d0f
AL
3639 } else if ty::type_is_error(idx_t) {
3640 fcx.write_ty(id, idx_t);
1a4d82fc 3641 } else {
d9579d0f
AL
3642 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3643 match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3644 Some((index_ty, element_ty)) => {
3645 let idx_expr_ty = fcx.expr_ty(idx);
3646 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3647 fcx.write_ty(id, element_ty);
3648 }
3649 None => {
3650 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3651 fcx.type_error_message(
3652 expr.span,
3653 |actual| {
3654 format!("cannot index a value of type `{}`",
3655 actual)
3656 },
3657 base_t,
3658 None);
3659 fcx.write_ty(id, fcx.tcx().types.err);
1a4d82fc
JJ
3660 }
3661 }
3662 }
3663 }
3664 ast::ExprRange(ref start, ref end) => {
3665 let t_start = start.as_ref().map(|e| {
3666 check_expr(fcx, &**e);
3667 fcx.expr_ty(&**e)
3668 });
3669 let t_end = end.as_ref().map(|e| {
3670 check_expr(fcx, &**e);
3671 fcx.expr_ty(&**e)
3672 });
3673
3674 let idx_type = match (t_start, t_end) {
3675 (Some(ty), None) | (None, Some(ty)) => {
3676 Some(ty)
3677 }
3678 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3679 ty::type_is_error(t_end)) => {
3680 Some(fcx.tcx().types.err)
3681 }
3682 (Some(t_start), Some(t_end)) => {
3683 Some(infer::common_supertype(fcx.infcx(),
3684 infer::RangeExpression(expr.span),
3685 true,
3686 t_start,
3687 t_end))
3688 }
3689 _ => None
3690 };
3691
3692 // Note that we don't check the type of start/end satisfy any
3693 // bounds because right now the range structs do not have any. If we add
3694 // some bounds, then we'll need to check `t_start` against them here.
3695
3696 let range_type = match idx_type {
3697 Some(idx_type) if ty::type_is_error(idx_type) => {
3698 fcx.tcx().types.err
3699 }
3700 Some(idx_type) => {
3701 // Find the did from the appropriate lang item.
3702 let did = match (start, end) {
3703 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3704 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3705 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3706 (&None, &None) => {
3707 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3708 }
3709 };
3710
3711 if let Some(did) = did {
85aaf69f 3712 let predicates = ty::lookup_predicates(tcx, did);
1a4d82fc 3713 let substs = Substs::new_type(vec![idx_type], vec![]);
85aaf69f 3714 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
1a4d82fc
JJ
3715 fcx.add_obligations_for_parameters(
3716 traits::ObligationCause::new(expr.span,
3717 fcx.body_id,
3718 traits::ItemObligation(did)),
3719 &bounds);
3720
3721 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3722 } else {
85aaf69f 3723 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
1a4d82fc
JJ
3724 fcx.tcx().types.err
3725 }
3726 }
3727 None => {
85aaf69f
SL
3728 // Neither start nor end => RangeFull
3729 if let Some(did) = tcx.lang_items.range_full_struct() {
1a4d82fc
JJ
3730 let substs = Substs::new_type(vec![], vec![]);
3731 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3732 } else {
85aaf69f 3733 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
1a4d82fc
JJ
3734 fcx.tcx().types.err
3735 }
3736 }
3737 };
3738
3739 fcx.write_ty(id, range_type);
3740 }
3741
3742 }
3743
3744 debug!("type of expr({}) {} is...", expr.id,
3745 syntax::print::pprust::expr_to_string(expr));
62682a34
SL
3746 debug!("... {:?}, expected is {:?}",
3747 fcx.expr_ty(expr),
3748 expected);
1a4d82fc
JJ
3749
3750 unifier();
3751}
3752
d9579d0f
AL
3753pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
3754 path_res: def::PathResolution,
3755 opt_self_ty: Option<Ty<'tcx>>,
3756 path: &'a ast::Path,
3757 span: Span,
3758 node_id: ast::NodeId)
3759 -> Option<(Option<Ty<'tcx>>,
3760 &'a [ast::PathSegment],
3761 def::Def)>
3762{
62682a34
SL
3763
3764 // Associated constants can't depend on generic types.
3765 fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3766 def: def::Def,
3767 ty: Ty<'tcx>,
3768 span: Span,
3769 node_id: ast::NodeId) -> bool {
3770 match def {
3771 def::DefAssociatedConst(..) => {
3772 if ty::type_has_params(ty) || ty::type_has_self(ty) {
3773 span_err!(fcx.sess(), span, E0329,
3774 "Associated consts cannot depend \
3775 on type parameters or Self.");
3776 fcx.write_error(node_id);
3777 return true;
3778 }
3779 }
3780 _ => {}
3781 }
3782 false
3783 }
3784
d9579d0f
AL
3785 // If fully resolved already, we don't have to do anything.
3786 if path_res.depth == 0 {
62682a34
SL
3787 if let Some(ty) = opt_self_ty {
3788 if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
3789 span, node_id) {
3790 return None;
3791 }
3792 }
d9579d0f
AL
3793 Some((opt_self_ty, &path.segments, path_res.base_def))
3794 } else {
3795 let mut def = path_res.base_def;
3796 let ty_segments = path.segments.init();
3797 let base_ty_end = path.segments.len() - path_res.depth;
3798 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
3799 PathParamMode::Optional,
3800 &mut def,
3801 opt_self_ty,
3802 &ty_segments[..base_ty_end],
3803 &ty_segments[base_ty_end..]);
3804 let item_segment = path.segments.last().unwrap();
3805 let item_name = item_segment.identifier.name;
3806 match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
3807 Ok((def, lp)) => {
62682a34
SL
3808 if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
3809 return None;
3810 }
d9579d0f
AL
3811 // Write back the new resolution.
3812 fcx.ccx.tcx.def_map.borrow_mut()
3813 .insert(node_id, def::PathResolution {
3814 base_def: def,
3815 last_private: path_res.last_private.or(lp),
3816 depth: 0
3817 });
3818 Some((Some(ty), slice::ref_slice(item_segment), def))
3819 }
3820 Err(error) => {
3821 method::report_error(fcx, span, ty,
3822 item_name, None, error);
3823 fcx.write_error(node_id);
3824 None
3825 }
3826 }
3827 }
3828}
3829
1a4d82fc
JJ
3830fn constrain_path_type_parameters(fcx: &FnCtxt,
3831 expr: &ast::Expr)
3832{
3833 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3834 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3835 });
3836}
3837
3838impl<'tcx> Expectation<'tcx> {
3839 /// Provide an expectation for an rvalue expression given an *optional*
3840 /// hint, which is not required for type safety (the resulting type might
3841 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3842 /// is useful in determining the concrete type.
3843 ///
3844 /// The primary use case is where the expected type is a fat pointer,
c34b1796 3845 /// like `&[isize]`. For example, consider the following statement:
1a4d82fc 3846 ///
c34b1796 3847 /// let x: &[isize] = &[1, 2, 3];
1a4d82fc
JJ
3848 ///
3849 /// In this case, the expected type for the `&[1, 2, 3]` expression is
c34b1796
AL
3850 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3851 /// expectation `ExpectHasType([isize])`, that would be too strong --
3852 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
1a4d82fc 3853 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
c34b1796 3854 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
1a4d82fc
JJ
3855 /// which still is useful, because it informs integer literals and the like.
3856 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3857 /// for examples of where this comes up,.
3858 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
3859 match ty.sty {
62682a34 3860 ty::TySlice(_) | ty::TyTrait(..) => {
1a4d82fc
JJ
3861 ExpectRvalueLikeUnsized(ty)
3862 }
3863 _ => ExpectHasType(ty)
3864 }
3865 }
3866
1a4d82fc
JJ
3867 // Resolves `expected` by a single level if it is a variable. If
3868 // there is no expected type or resolution is not possible (e.g.,
3869 // no constraints yet present), just returns `None`.
3870 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3871 match self {
3872 NoExpectation => {
3873 NoExpectation
3874 }
3875 ExpectCastableToType(t) => {
3876 ExpectCastableToType(
3877 fcx.infcx().resolve_type_vars_if_possible(&t))
3878 }
3879 ExpectHasType(t) => {
3880 ExpectHasType(
3881 fcx.infcx().resolve_type_vars_if_possible(&t))
3882 }
3883 ExpectRvalueLikeUnsized(t) => {
3884 ExpectRvalueLikeUnsized(
3885 fcx.infcx().resolve_type_vars_if_possible(&t))
3886 }
3887 }
3888 }
3889
85aaf69f 3890 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
1a4d82fc 3891 match self.resolve(fcx) {
85aaf69f 3892 NoExpectation => None,
1a4d82fc
JJ
3893 ExpectCastableToType(ty) |
3894 ExpectHasType(ty) |
85aaf69f 3895 ExpectRvalueLikeUnsized(ty) => Some(ty),
1a4d82fc
JJ
3896 }
3897 }
3898
85aaf69f 3899 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
1a4d82fc 3900 match self.resolve(fcx) {
85aaf69f
SL
3901 ExpectHasType(ty) => Some(ty),
3902 _ => None
1a4d82fc
JJ
3903 }
3904 }
3905}
3906
85aaf69f 3907pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
c34b1796 3908 local: &'tcx ast::Local,
85aaf69f 3909 init: &'tcx ast::Expr)
1a4d82fc 3910{
c34b1796
AL
3911 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
3912
3913 let local_ty = fcx.local_ty(init.span, local.id);
62682a34 3914 if let Some(m) = ref_bindings {
c34b1796
AL
3915 // Somewhat subtle: if we have a `ref` binding in the pattern,
3916 // we want to avoid introducing coercions for the RHS. This is
3917 // both because it helps preserve sanity and, in the case of
3918 // ref mut, for soundness (issue #23116). In particular, in
3919 // the latter case, we need to be clear that the type of the
3920 // referent for the reference that results is *equal to* the
3921 // type of the lvalue it is referencing, and not some
3922 // supertype thereof.
62682a34 3923 check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
c34b1796
AL
3924 let init_ty = fcx.expr_ty(init);
3925 demand::eqtype(fcx, init.span, init_ty, local_ty);
62682a34
SL
3926 } else {
3927 check_expr_coercable_to_type(fcx, init, local_ty)
c34b1796 3928 };
1a4d82fc
JJ
3929}
3930
85aaf69f 3931pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
1a4d82fc
JJ
3932 let tcx = fcx.ccx.tcx;
3933
3934 let t = fcx.local_ty(local.span, local.id);
3935 fcx.write_ty(local.id, t);
3936
3937 if let Some(ref init) = local.init {
c34b1796 3938 check_decl_initializer(fcx, local, &**init);
1a4d82fc
JJ
3939 let init_ty = fcx.expr_ty(&**init);
3940 if ty::type_is_error(init_ty) {
3941 fcx.write_ty(local.id, init_ty);
3942 }
3943 }
3944
3945 let pcx = pat_ctxt {
3946 fcx: fcx,
3947 map: pat_id_map(&tcx.def_map, &*local.pat),
3948 };
3949 _match::check_pat(&pcx, &*local.pat, t);
3950 let pat_ty = fcx.node_ty(local.pat.id);
3951 if ty::type_is_error(pat_ty) {
3952 fcx.write_ty(local.id, pat_ty);
3953 }
3954}
3955
85aaf69f 3956pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
1a4d82fc
JJ
3957 let node_id;
3958 let mut saw_bot = false;
3959 let mut saw_err = false;
3960 match stmt.node {
3961 ast::StmtDecl(ref decl, id) => {
3962 node_id = id;
3963 match decl.node {
3964 ast::DeclLocal(ref l) => {
3965 check_decl_local(fcx, &**l);
3966 let l_t = fcx.node_ty(l.id);
3967 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
3968 saw_err = saw_err || ty::type_is_error(l_t);
3969 }
3970 ast::DeclItem(_) => {/* ignore for now */ }
3971 }
3972 }
3973 ast::StmtExpr(ref expr, id) => {
3974 node_id = id;
3975 // Check with expected type of ()
3976 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
3977 let expr_ty = fcx.expr_ty(&**expr);
3978 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
3979 saw_err = saw_err || ty::type_is_error(expr_ty);
3980 }
3981 ast::StmtSemi(ref expr, id) => {
3982 node_id = id;
3983 check_expr(fcx, &**expr);
3984 let expr_ty = fcx.expr_ty(&**expr);
3985 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
3986 saw_err |= ty::type_is_error(expr_ty);
3987 }
3988 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3989 }
3990 if saw_bot {
3991 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
3992 }
3993 else if saw_err {
3994 fcx.write_error(node_id);
3995 }
3996 else {
3997 fcx.write_nil(node_id)
3998 }
3999}
4000
85aaf69f 4001pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
1a4d82fc
JJ
4002 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4003 let blkty = fcx.node_ty(blk.id);
4004 if ty::type_is_error(blkty) {
4005 fcx.write_error(blk.id);
4006 } else {
4007 let nilty = ty::mk_nil(fcx.tcx());
4008 demand::suptype(fcx, blk.span, nilty, blkty);
4009 }
4010}
4011
4012fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
85aaf69f 4013 blk: &'tcx ast::Block,
1a4d82fc
JJ
4014 expected: Expectation<'tcx>) {
4015 let prev = {
4016 let mut fcx_ps = fcx.ps.borrow_mut();
4017 let unsafety_state = fcx_ps.recurse(blk);
4018 replace(&mut *fcx_ps, unsafety_state)
4019 };
4020
4021 let mut warned = false;
4022 let mut any_diverges = false;
4023 let mut any_err = false;
85aaf69f 4024 for s in &blk.stmts {
1a4d82fc
JJ
4025 check_stmt(fcx, &**s);
4026 let s_id = ast_util::stmt_id(&**s);
4027 let s_ty = fcx.node_ty(s_id);
4028 if any_diverges && !warned && match s.node {
4029 ast::StmtDecl(ref decl, _) => {
4030 match decl.node {
4031 ast::DeclLocal(_) => true,
4032 _ => false,
4033 }
4034 }
4035 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4036 _ => false
4037 } {
4038 fcx.ccx
4039 .tcx
4040 .sess
4041 .add_lint(lint::builtin::UNREACHABLE_CODE,
4042 s_id,
4043 s.span,
4044 "unreachable statement".to_string());
4045 warned = true;
4046 }
4047 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4048 any_err = any_err || ty::type_is_error(s_ty);
4049 }
4050 match blk.expr {
4051 None => if any_err {
4052 fcx.write_error(blk.id);
4053 } else if any_diverges {
4054 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4055 } else {
4056 fcx.write_nil(blk.id);
4057 },
4058 Some(ref e) => {
4059 if any_diverges && !warned {
4060 fcx.ccx
4061 .tcx
4062 .sess
4063 .add_lint(lint::builtin::UNREACHABLE_CODE,
4064 e.id,
4065 e.span,
4066 "unreachable expression".to_string());
4067 }
4068 let ety = match expected {
4069 ExpectHasType(ety) => {
4070 check_expr_coercable_to_type(fcx, &**e, ety);
4071 ety
4072 }
4073 _ => {
4074 check_expr_with_expectation(fcx, &**e, expected);
4075 fcx.expr_ty(&**e)
4076 }
4077 };
4078
4079 if any_err {
4080 fcx.write_error(blk.id);
4081 } else if any_diverges {
4082 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4083 } else {
4084 fcx.write_ty(blk.id, ety);
4085 }
4086 }
4087 };
4088
4089 *fcx.ps.borrow_mut() = prev;
4090}
4091
4092/// Checks a constant appearing in a type. At the moment this is just the
4093/// length expression in a fixed-length vector, but someday it might be
4094/// extended to type-level numeric literals.
4095fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
85aaf69f 4096 expr: &'tcx ast::Expr,
1a4d82fc
JJ
4097 expected_type: Ty<'tcx>) {
4098 let inh = static_inherited_fields(ccx);
4099 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4100 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4101}
4102
85aaf69f
SL
4103fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4104 sp: Span,
4105 e: &'tcx ast::Expr,
4106 id: ast::NodeId) {
1a4d82fc
JJ
4107 let inh = static_inherited_fields(ccx);
4108 let rty = ty::node_id_to_type(ccx.tcx, id);
4109 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
c34b1796 4110 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
1a4d82fc
JJ
4111 check_const_with_ty(&fcx, sp, e, declty);
4112}
4113
4114fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4115 _: Span,
85aaf69f 4116 e: &'tcx ast::Expr,
1a4d82fc
JJ
4117 declty: Ty<'tcx>) {
4118 // Gather locals in statics (because of block expressions).
4119 // This is technically unnecessary because locals in static items are forbidden,
4120 // but prevents type checking from blowing up before const checking can properly
4121 // emit a error.
4122 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4123
4124 check_expr_with_hint(fcx, e, declty);
4125 demand::coerce(fcx, e.span, declty, e);
d9579d0f 4126 fcx.select_all_obligations_or_error();
c34b1796 4127 fcx.check_casts();
1a4d82fc
JJ
4128 regionck::regionck_expr(fcx, e);
4129 writeback::resolve_type_vars_in_expr(fcx, e);
4130}
4131
4132/// Checks whether a type can be represented in memory. In particular, it
4133/// identifies types that contain themselves without indirection through a
4134/// pointer, which would mean their size is unbounded. This is different from
4135/// the question of whether a type can be instantiated. See the definition of
4136/// `check_instantiable`.
4137pub fn check_representable(tcx: &ty::ctxt,
4138 sp: Span,
4139 item_id: ast::NodeId,
4140 designation: &str) -> bool {
4141 let rty = ty::node_id_to_type(tcx, item_id);
4142
4143 // Check that it is possible to represent this type. This call identifies
4144 // (1) types that contain themselves and (2) types that contain a different
4145 // recursive type. It is only necessary to throw an error on those that
4146 // contain themselves. For case 2, there must be an inner type that will be
4147 // caught by case 1.
4148 match ty::is_type_representable(tcx, sp, rty) {
4149 ty::SelfRecursive => {
4150 span_err!(tcx.sess, sp, E0072,
4151 "illegal recursive {} type; \
4152 wrap the inner value in a box to make it representable",
4153 designation);
4154 return false
4155 }
4156 ty::Representable | ty::ContainsRecursive => (),
4157 }
4158 return true
4159}
4160
4161/// Checks whether a type can be created without an instance of itself.
4162/// This is similar but different from the question of whether a type
4163/// can be represented. For example, the following type:
4164///
4165/// enum foo { None, Some(foo) }
4166///
4167/// is instantiable but is not representable. Similarly, the type
4168///
4169/// enum foo { Some(@foo) }
4170///
4171/// is representable, but not instantiable.
4172pub fn check_instantiable(tcx: &ty::ctxt,
4173 sp: Span,
4174 item_id: ast::NodeId)
4175 -> bool {
4176 let item_ty = ty::node_id_to_type(tcx, item_id);
4177 if !ty::is_instantiable(tcx, item_ty) {
4178 span_err!(tcx.sess, sp, E0073,
4179 "this type cannot be instantiated without an \
4180 instance of itself");
62682a34
SL
4181 fileline_help!(tcx.sess, sp, "consider using `Option<{:?}>`",
4182 item_ty);
1a4d82fc
JJ
4183 false
4184 } else {
4185 true
4186 }
4187}
4188
4189pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4190 let t = ty::node_id_to_type(tcx, id);
4191 if ty::type_needs_subst(t) {
4192 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4193 return;
4194 }
4195 match t.sty {
62682a34 4196 ty::TyStruct(did, substs) => {
1a4d82fc
JJ
4197 let fields = ty::lookup_struct_fields(tcx, did);
4198 if fields.is_empty() {
4199 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4200 return;
4201 }
4202 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4203 if !fields.iter().all(
4204 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4205 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4206 return;
4207 }
4208 if !ty::type_is_machine(e) {
4209 span_err!(tcx.sess, sp, E0077,
4210 "SIMD vector element type should be machine type");
4211 return;
4212 }
4213 }
4214 _ => ()
4215 }
4216}
4217
85aaf69f
SL
4218pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4219 sp: Span,
4220 vs: &'tcx [P<ast::Variant>],
4221 id: ast::NodeId) {
1a4d82fc
JJ
4222
4223 fn disr_in_range(ccx: &CrateCtxt,
4224 ty: attr::IntType,
4225 disr: ty::Disr) -> bool {
4226 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4227 match ty {
4228 ast::TyU8 => disr as u8 as Disr == disr,
4229 ast::TyU16 => disr as u16 as Disr == disr,
4230 ast::TyU32 => disr as u32 as Disr == disr,
4231 ast::TyU64 => disr as u64 as Disr == disr,
c34b1796 4232 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
1a4d82fc
JJ
4233 }
4234 }
4235 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4236 match ty {
4237 ast::TyI8 => disr as i8 as Disr == disr,
4238 ast::TyI16 => disr as i16 as Disr == disr,
4239 ast::TyI32 => disr as i32 as Disr == disr,
4240 ast::TyI64 => disr as i64 as Disr == disr,
c34b1796 4241 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
1a4d82fc
JJ
4242 }
4243 }
4244 match ty {
4245 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4246 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4247 }
4248 }
4249
4250 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f 4251 vs: &'tcx [P<ast::Variant>],
1a4d82fc 4252 id: ast::NodeId,
c34b1796
AL
4253 hint: attr::ReprAttr) {
4254 #![allow(trivial_numeric_casts)]
1a4d82fc
JJ
4255
4256 let rty = ty::node_id_to_type(ccx.tcx, id);
1a4d82fc 4257 let mut disr_vals: Vec<ty::Disr> = Vec::new();
1a4d82fc 4258
c34b1796
AL
4259 let inh = static_inherited_fields(ccx);
4260 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
4261
4262 let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint));
85aaf69f 4263 for v in vs {
c34b1796
AL
4264 if let Some(ref e) = v.node.disr_expr {
4265 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
4266 }
4267 }
1a4d82fc 4268
c34b1796 4269 let def_id = local_def(id);
1a4d82fc 4270
c34b1796
AL
4271 // ty::enum_variants guards against discriminant overflows, so
4272 // we need not check for that.
4273 let variants = ty::enum_variants(ccx.tcx, def_id);
1a4d82fc 4274
c34b1796
AL
4275 for (v, variant) in vs.iter().zip(variants.iter()) {
4276 let current_disr_val = variant.disr_val;
1a4d82fc
JJ
4277
4278 // Check for duplicate discriminant values
4279 match disr_vals.iter().position(|&x| x == current_disr_val) {
4280 Some(i) => {
4281 span_err!(ccx.tcx.sess, v.span, E0081,
4282 "discriminant value `{}` already exists", disr_vals[i]);
4283 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4284 "conflicting discriminant here")
4285 }
4286 None => {}
4287 }
4288 // Check for unrepresentable discriminant values
4289 match hint {
4290 attr::ReprAny | attr::ReprExtern => (),
4291 attr::ReprInt(sp, ity) => {
4292 if !disr_in_range(ccx, ity, current_disr_val) {
4293 span_err!(ccx.tcx.sess, v.span, E0082,
4294 "discriminant value outside specified type");
4295 span_note!(ccx.tcx.sess, sp,
4296 "discriminant type specified here");
4297 }
4298 }
4299 attr::ReprPacked => {
4300 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4301 }
4302 }
4303 disr_vals.push(current_disr_val);
1a4d82fc 4304 }
1a4d82fc
JJ
4305 }
4306
4307 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
c34b1796 4308 .get(0).unwrap_or(&attr::ReprAny);
1a4d82fc
JJ
4309
4310 if hint != attr::ReprAny && vs.len() <= 1 {
4311 if vs.len() == 1 {
4312 span_err!(ccx.tcx.sess, sp, E0083,
4313 "unsupported representation for univariant enum");
4314 } else {
4315 span_err!(ccx.tcx.sess, sp, E0084,
4316 "unsupported representation for zero-variant enum");
4317 };
4318 }
4319
c34b1796 4320 do_check(ccx, vs, id, hint);
1a4d82fc
JJ
4321
4322 check_representable(ccx.tcx, sp, id, "enum");
4323
4324 // Check that it is possible to instantiate this enum:
4325 //
4326 // This *sounds* like the same that as representable, but it's
4327 // not. See def'n of `check_instantiable()` for details.
4328 check_instantiable(ccx.tcx, sp, id);
4329}
4330
1a4d82fc 4331// Returns the type parameter count and the type for the given definition.
85aaf69f
SL
4332fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4333 sp: Span,
4334 defn: def::Def)
4335 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
1a4d82fc 4336 match defn {
85aaf69f
SL
4337 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4338 let typ = fcx.local_ty(sp, nid);
4339 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4340 ty::GenericPredicates::empty())
4341 }
c34b1796 4342 def::DefFn(id, _) | def::DefMethod(id, _) |
85aaf69f 4343 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
d9579d0f 4344 def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
85aaf69f
SL
4345 (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4346 }
4347 def::DefTrait(_) |
4348 def::DefTy(..) |
4349 def::DefAssociatedTy(..) |
85aaf69f
SL
4350 def::DefPrimTy(_) |
4351 def::DefTyParam(..) |
4352 def::DefMod(..) |
4353 def::DefForeignMod(..) |
4354 def::DefUse(..) |
4355 def::DefRegion(..) |
85aaf69f
SL
4356 def::DefLabel(..) |
4357 def::DefSelfTy(..) => {
4358 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4359 }
1a4d82fc
JJ
4360 }
4361}
4362
4363// Instantiates the given path, which must refer to an item with the given
4364// number of type parameters and type.
4365pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
c34b1796 4366 segments: &[ast::PathSegment],
1a4d82fc 4367 type_scheme: TypeScheme<'tcx>,
85aaf69f
SL
4368 type_predicates: &ty::GenericPredicates<'tcx>,
4369 opt_self_ty: Option<Ty<'tcx>>,
1a4d82fc
JJ
4370 def: def::Def,
4371 span: Span,
4372 node_id: ast::NodeId) {
62682a34 4373 debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
c34b1796 4374 segments,
62682a34 4375 def,
1a4d82fc 4376 node_id,
62682a34 4377 type_scheme);
1a4d82fc
JJ
4378
4379 // We need to extract the type parameters supplied by the user in
4380 // the path `path`. Due to the current setup, this is a bit of a
4381 // tricky-process; the problem is that resolve only tells us the
4382 // end-point of the path resolution, and not the intermediate steps.
4383 // Luckily, we can (at least for now) deduce the intermediate steps
4384 // just from the end-point.
4385 //
d9579d0f 4386 // There are basically four cases to consider:
1a4d82fc
JJ
4387 //
4388 // 1. Reference to a *type*, such as a struct or enum:
4389 //
4390 // mod a { struct Foo<T> { ... } }
4391 //
4392 // Because we don't allow types to be declared within one
4393 // another, a path that leads to a type will always look like
4394 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4395 // that only the final segment can have type parameters, and
4396 // they are located in the TypeSpace.
4397 //
4398 // *Note:* Generally speaking, references to types don't
4399 // actually pass through this function, but rather the
4400 // `ast_ty_to_ty` function in `astconv`. However, in the case
4401 // of struct patterns (and maybe literals) we do invoke
4402 // `instantiate_path` to get the general type of an instance of
4403 // a struct. (In these cases, there are actually no type
4404 // parameters permitted at present, but perhaps we will allow
4405 // them in the future.)
4406 //
4407 // 1b. Reference to a enum variant or tuple-like struct:
4408 //
4409 // struct foo<T>(...)
4410 // enum E<T> { foo(...) }
4411 //
4412 // In these cases, the parameters are declared in the type
4413 // space.
4414 //
4415 // 2. Reference to a *fn item*:
4416 //
4417 // fn foo<T>() { }
4418 //
4419 // In this case, the path will again always have the form
4420 // `a::b::foo::<T>` where only the final segment should have
4421 // type parameters. However, in this case, those parameters are
4422 // declared on a value, and hence are in the `FnSpace`.
4423 //
4424 // 3. Reference to a *method*:
4425 //
4426 // impl<A> SomeStruct<A> {
4427 // fn foo<B>(...)
4428 // }
4429 //
4430 // Here we can have a path like
4431 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4432 // may appear in two places. The penultimate segment,
4433 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4434 // final segment, `foo::<B>` contains parameters in fn space.
4435 //
d9579d0f
AL
4436 // 4. Reference to an *associated const*:
4437 //
4438 // impl<A> AnotherStruct<A> {
4439 // const FOO: B = BAR;
4440 // }
4441 //
4442 // The path in this case will look like
4443 // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
4444 // only will have parameters in TypeSpace.
4445 //
1a4d82fc
JJ
4446 // The first step then is to categorize the segments appropriately.
4447
9346a6ac 4448 assert!(!segments.is_empty());
c34b1796
AL
4449
4450 let mut ufcs_method = None;
1a4d82fc
JJ
4451 let mut segment_spaces: Vec<_>;
4452 match def {
4453 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4454 def::DefSelfTy(..) |
4455 def::DefStruct(..) |
4456 def::DefVariant(..) |
1a4d82fc
JJ
4457 def::DefTy(..) |
4458 def::DefAssociatedTy(..) |
1a4d82fc
JJ
4459 def::DefTrait(..) |
4460 def::DefPrimTy(..) |
4461 def::DefTyParam(..) => {
4462 // Everything but the final segment should have no
4463 // parameters at all.
c34b1796 4464 segment_spaces = repeat(None).take(segments.len() - 1).collect();
1a4d82fc
JJ
4465 segment_spaces.push(Some(subst::TypeSpace));
4466 }
4467
4468 // Case 2. Reference to a top-level value.
4469 def::DefFn(..) |
4470 def::DefConst(..) |
4471 def::DefStatic(..) => {
c34b1796 4472 segment_spaces = repeat(None).take(segments.len() - 1).collect();
1a4d82fc
JJ
4473 segment_spaces.push(Some(subst::FnSpace));
4474 }
4475
4476 // Case 3. Reference to a method.
c34b1796
AL
4477 def::DefMethod(_, provenance) => {
4478 match provenance {
1a4d82fc
JJ
4479 def::FromTrait(trait_did) => {
4480 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4481 }
4482 def::FromImpl(_) => {}
4483 }
4484
c34b1796
AL
4485 if segments.len() >= 2 {
4486 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4487 segment_spaces.push(Some(subst::TypeSpace));
4488 segment_spaces.push(Some(subst::FnSpace));
4489 } else {
4490 // `<T>::method` will end up here, and so can `T::method`.
4491 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4492 segment_spaces = vec![Some(subst::FnSpace)];
4493 ufcs_method = Some((provenance, self_ty));
4494 }
1a4d82fc
JJ
4495 }
4496
d9579d0f
AL
4497 def::DefAssociatedConst(_, provenance) => {
4498 match provenance {
4499 def::FromTrait(trait_did) => {
4500 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4501 }
4502 def::FromImpl(_) => {}
4503 }
4504
4505 if segments.len() >= 2 {
4506 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4507 segment_spaces.push(Some(subst::TypeSpace));
4508 segment_spaces.push(None);
4509 } else {
4510 segment_spaces = vec![None];
4511 }
4512 }
4513
1a4d82fc
JJ
4514 // Other cases. Various nonsense that really shouldn't show up
4515 // here. If they do, an error will have been reported
4516 // elsewhere. (I hope)
4517 def::DefMod(..) |
4518 def::DefForeignMod(..) |
4519 def::DefLocal(..) |
4520 def::DefUse(..) |
4521 def::DefRegion(..) |
4522 def::DefLabel(..) |
4523 def::DefUpvar(..) => {
c34b1796 4524 segment_spaces = repeat(None).take(segments.len()).collect();
1a4d82fc
JJ
4525 }
4526 }
c34b1796
AL
4527 assert_eq!(segment_spaces.len(), segments.len());
4528
4529 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4530 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4531 // type parameters are not mandatory.
4532 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
1a4d82fc
JJ
4533
4534 debug!("segment_spaces={:?}", segment_spaces);
4535
4536 // Next, examine the definition, and determine how many type
4537 // parameters we expect from each space.
4538 let type_defs = &type_scheme.generics.types;
4539 let region_defs = &type_scheme.generics.regions;
4540
4541 // Now that we have categorized what space the parameters for each
4542 // segment belong to, let's sort out the parameters that the user
4543 // provided (if any) into their appropriate spaces. We'll also report
4544 // errors if type parameters are provided in an inappropriate place.
4545 let mut substs = Substs::empty();
62682a34 4546 for (opt_space, segment) in segment_spaces.iter().zip(segments) {
1a4d82fc
JJ
4547 match *opt_space {
4548 None => {
c34b1796
AL
4549 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4550 NO_TPS | NO_REGIONS);
1a4d82fc
JJ
4551 }
4552
4553 Some(space) => {
4554 push_explicit_parameters_from_segment_to_substs(fcx,
4555 space,
c34b1796 4556 span,
1a4d82fc
JJ
4557 type_defs,
4558 region_defs,
4559 segment,
4560 &mut substs);
4561 }
4562 }
4563 }
85aaf69f 4564 if let Some(self_ty) = opt_self_ty {
c34b1796
AL
4565 if type_defs.len(subst::SelfSpace) == 1 {
4566 substs.types.push(subst::SelfSpace, self_ty);
4567 }
85aaf69f 4568 }
1a4d82fc
JJ
4569
4570 // Now we have to compare the types that the user *actually*
4571 // provided against the types that were *expected*. If the user
4572 // did not provide any types, then we want to substitute inference
4573 // variables. If the user provided some types, we may still need
4574 // to add defaults. If the user provided *too many* types, that's
4575 // a problem.
85aaf69f 4576 for &space in &ParamSpace::all() {
c34b1796
AL
4577 adjust_type_parameters(fcx, span, space, type_defs,
4578 require_type_space, &mut substs);
1a4d82fc
JJ
4579 assert_eq!(substs.types.len(space), type_defs.len(space));
4580
4581 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4582 assert_eq!(substs.regions().len(space), region_defs.len(space));
4583 }
4584
4585 // The things we are substituting into the type should not contain
4586 // escaping late-bound regions, and nor should the base type scheme.
4587 assert!(!substs.has_regions_escaping_depth(0));
4588 assert!(!type_scheme.has_escaping_regions());
4589
4590 // Add all the obligations that are required, substituting and
4591 // normalized appropriately.
85aaf69f 4592 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
1a4d82fc
JJ
4593 fcx.add_obligations_for_parameters(
4594 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4595 &bounds);
4596
4597 // Substitute the values for the type parameters into the type of
4598 // the referenced item.
4599 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4600
1a4d82fc 4601
c34b1796
AL
4602 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4603 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4604 // is inherent, there is no `Self` parameter, instead, the impl needs
4605 // type parameters, which we can infer by unifying the provided `Self`
4606 // with the substituted impl type.
4607 let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
4608 assert_eq!(substs.types.len(subst::TypeSpace),
4609 impl_scheme.generics.types.len(subst::TypeSpace));
4610 assert_eq!(substs.regions().len(subst::TypeSpace),
4611 impl_scheme.generics.regions.len(subst::TypeSpace));
1a4d82fc 4612
c34b1796
AL
4613 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4614 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4615 fcx.tcx().sess.span_bug(span,
4616 &format!(
62682a34
SL
4617 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
4618 self_ty,
4619 impl_ty));
1a4d82fc
JJ
4620 }
4621 }
4622
c34b1796
AL
4623 fcx.write_ty(node_id, ty_substituted);
4624 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4625 return;
4626
1a4d82fc
JJ
4627 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4628 /// parameters are provided, then reports an error and clears the output vector.
4629 ///
4630 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4631 /// use inference variables. This seems less likely to lead to derived errors.
4632 ///
4633 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4634 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4635 /// here because we can easily use the precise span of the N+1'th parameter.
4636 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4637 fcx: &FnCtxt<'a, 'tcx>,
4638 space: subst::ParamSpace,
4639 span: Span,
4640 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4641 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4642 segment: &ast::PathSegment,
4643 substs: &mut Substs<'tcx>)
4644 {
4645 match segment.parameters {
4646 ast::AngleBracketedParameters(ref data) => {
4647 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4648 fcx, space, type_defs, region_defs, data, substs);
4649 }
4650
4651 ast::ParenthesizedParameters(ref data) => {
85aaf69f 4652 span_err!(fcx.tcx().sess, span, E0238,
1a4d82fc
JJ
4653 "parenthesized parameters may only be used with a trait");
4654 push_explicit_parenthesized_parameters_from_segment_to_substs(
4655 fcx, space, span, type_defs, data, substs);
4656 }
4657 }
4658 }
4659
4660 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4661 fcx: &FnCtxt<'a, 'tcx>,
4662 space: subst::ParamSpace,
4663 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4664 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4665 data: &ast::AngleBracketedParameterData,
4666 substs: &mut Substs<'tcx>)
4667 {
4668 {
4669 let type_count = type_defs.len(space);
4670 assert_eq!(substs.types.len(space), 0);
4671 for (i, typ) in data.types.iter().enumerate() {
4672 let t = fcx.to_ty(&**typ);
4673 if i < type_count {
4674 substs.types.push(space, t);
4675 } else if i == type_count {
4676 span_err!(fcx.tcx().sess, typ.span, E0087,
4677 "too many type parameters provided: \
62682a34
SL
4678 expected at most {} parameter{}, \
4679 found {} parameter{}",
4680 type_count,
4681 if type_count == 1 {""} else {"s"},
4682 data.types.len(),
4683 if data.types.len() == 1 {""} else {"s"});
1a4d82fc
JJ
4684 substs.types.truncate(space, 0);
4685 break;
4686 }
4687 }
4688 }
4689
9346a6ac 4690 if !data.bindings.is_empty() {
1a4d82fc
JJ
4691 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4692 "unexpected binding of associated item in expression path \
4693 (only allowed in type paths)");
4694 }
4695
4696 {
4697 let region_count = region_defs.len(space);
4698 assert_eq!(substs.regions().len(space), 0);
4699 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4700 let r = ast_region_to_region(fcx.tcx(), lifetime);
4701 if i < region_count {
4702 substs.mut_regions().push(space, r);
4703 } else if i == region_count {
4704 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4705 "too many lifetime parameters provided: \
62682a34 4706 expected {} parameter{}, found {} parameter{}",
1a4d82fc 4707 region_count,
62682a34
SL
4708 if region_count == 1 {""} else {"s"},
4709 data.lifetimes.len(),
4710 if data.lifetimes.len() == 1 {""} else {"s"});
1a4d82fc
JJ
4711 substs.mut_regions().truncate(space, 0);
4712 break;
4713 }
4714 }
4715 }
4716 }
4717
4718 /// As with
4719 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4720 /// but intended for `Foo(A,B) -> C` form. This expands to
4721 /// roughly the same thing as `Foo<(A,B),C>`. One important
4722 /// difference has to do with the treatment of anonymous
4723 /// regions, which are translated into bound regions (NYI).
4724 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4725 fcx: &FnCtxt<'a, 'tcx>,
4726 space: subst::ParamSpace,
4727 span: Span,
4728 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4729 data: &ast::ParenthesizedParameterData,
4730 substs: &mut Substs<'tcx>)
4731 {
4732 let type_count = type_defs.len(space);
4733 if type_count < 2 {
4734 span_err!(fcx.tcx().sess, span, E0167,
4735 "parenthesized form always supplies 2 type parameters, \
4736 but only {} parameter(s) were expected",
4737 type_count);
4738 }
4739
4740 let input_tys: Vec<Ty> =
4741 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4742
4743 let tuple_ty =
4744 ty::mk_tup(fcx.tcx(), input_tys);
4745
4746 if type_count >= 1 {
4747 substs.types.push(space, tuple_ty);
4748 }
4749
4750 let output_ty: Option<Ty> =
4751 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4752
4753 let output_ty =
4754 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4755
4756 if type_count >= 2 {
4757 substs.types.push(space, output_ty);
4758 }
4759 }
4760
4761 fn adjust_type_parameters<'a, 'tcx>(
4762 fcx: &FnCtxt<'a, 'tcx>,
4763 span: Span,
4764 space: ParamSpace,
4765 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
c34b1796 4766 require_type_space: bool,
1a4d82fc
JJ
4767 substs: &mut Substs<'tcx>)
4768 {
4769 let provided_len = substs.types.len(space);
4770 let desired = defs.get_slice(space);
4771 let required_len = desired.iter()
4772 .take_while(|d| d.default.is_none())
4773 .count();
4774
4775 debug!("adjust_type_parameters(space={:?}, \
4776 provided_len={}, \
4777 desired_len={}, \
4778 required_len={})",
4779 space,
4780 provided_len,
4781 desired.len(),
4782 required_len);
4783
4784 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4785 assert!(provided_len <= desired.len());
4786
4787 // Nothing specified at all: supply inference variables for
4788 // everything.
c34b1796
AL
4789 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4790 substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
1a4d82fc
JJ
4791 return;
4792 }
4793
4794 // Too few parameters specified: report an error and use Err
4795 // for everything.
4796 if provided_len < required_len {
4797 let qualifier =
4798 if desired.len() != required_len { "at least " } else { "" };
4799 span_err!(fcx.tcx().sess, span, E0089,
62682a34
SL
4800 "too few type parameters provided: expected {}{} parameter{}, \
4801 found {} parameter{}",
4802 qualifier, required_len,
4803 if required_len == 1 {""} else {"s"},
4804 provided_len,
4805 if provided_len == 1 {""} else {"s"});
1a4d82fc
JJ
4806 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
4807 return;
4808 }
4809
4810 // Otherwise, add in any optional parameters that the user
4811 // omitted. The case of *too many* parameters is handled
4812 // already by
4813 // push_explicit_parameters_from_segment_to_substs(). Note
4814 // that the *default* type are expressed in terms of all prior
4815 // parameters, so we have to substitute as we go with the
4816 // partial substitution that we have built up.
85aaf69f 4817 for i in provided_len..desired.len() {
1a4d82fc
JJ
4818 let default = desired[i].default.unwrap();
4819 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4820 substs.types.push(space, default);
4821 }
4822 assert_eq!(substs.types.len(space), desired.len());
4823
62682a34 4824 debug!("Final substs: {:?}", substs);
1a4d82fc
JJ
4825 }
4826
4827 fn adjust_region_parameters(
4828 fcx: &FnCtxt,
4829 span: Span,
4830 space: ParamSpace,
4831 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4832 substs: &mut Substs)
4833 {
4834 let provided_len = substs.mut_regions().len(space);
4835 let desired = defs.get_slice(space);
4836
4837 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4838 assert!(provided_len <= desired.len());
4839
4840 // If nothing was provided, just use inference variables.
4841 if provided_len == 0 {
4842 substs.mut_regions().replace(
4843 space,
4844 fcx.infcx().region_vars_for_defs(span, desired));
4845 return;
4846 }
4847
4848 // If just the right number were provided, everybody is happy.
4849 if provided_len == desired.len() {
4850 return;
4851 }
4852
4853 // Otherwise, too few were provided. Report an error and then
4854 // use inference variables.
4855 span_err!(fcx.tcx().sess, span, E0090,
62682a34
SL
4856 "too few lifetime parameters provided: expected {} parameter{}, \
4857 found {} parameter{}",
4858 desired.len(),
4859 if desired.len() == 1 {""} else {"s"},
4860 provided_len,
4861 if provided_len == 1 {""} else {"s"});
1a4d82fc
JJ
4862
4863 substs.mut_regions().replace(
4864 space,
4865 fcx.infcx().region_vars_for_defs(span, desired));
4866 }
4867}
4868
85aaf69f
SL
4869fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4870 sp: Span,
4871 ty: Ty<'tcx>,
4872 f: F) -> Ty<'tcx>
4873 where F: Fn() -> Ty<'tcx>
4874{
4875 let mut ty = fcx.resolve_type_vars_if_possible(ty);
1a4d82fc 4876
1a4d82fc 4877 if ty::type_is_ty_var(ty) {
85aaf69f
SL
4878 let alternative = f();
4879
4880 // If not, error.
4881 if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
4882 fcx.type_error_message(sp, |_actual| {
4883 "the type of this value must be known in this context".to_string()
4884 }, ty, None);
4885 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4886 ty = fcx.tcx().types.err;
4887 } else {
4888 demand::suptype(fcx, sp, alternative, ty);
4889 ty = alternative;
4890 }
1a4d82fc
JJ
4891 }
4892
4893 ty
4894}
4895
85aaf69f
SL
4896// Resolves `typ` by a single level if `typ` is a type variable. If no
4897// resolution is possible, then an error is reported.
4898pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4899 sp: Span,
4900 ty: Ty<'tcx>)
4901 -> Ty<'tcx>
4902{
4903 structurally_resolve_type_or_else(fcx, sp, ty, || {
4904 fcx.tcx().types.err
4905 })
4906}
4907
1a4d82fc
JJ
4908// Returns true if b contains a break that can exit from b
4909pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4910 // First: is there an unlabeled break immediately
4911 // inside the loop?
4912 (loop_query(&*b, |e| {
4913 match *e {
c34b1796 4914 ast::ExprBreak(None) => true,
1a4d82fc
JJ
4915 _ => false
4916 }
4917 })) ||
c34b1796
AL
4918 // Second: is there a labeled break with label
4919 // <id> nested anywhere inside the loop?
1a4d82fc 4920 (block_query(b, |e| {
c34b1796
AL
4921 if let ast::ExprBreak(Some(_)) = e.node {
4922 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
4923 } else {
4924 false
4925 }
4926 }))
1a4d82fc
JJ
4927}
4928
4929pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4930 span: Span,
4931 tps: &OwnedSlice<ast::TyParam>,
4932 ty: Ty<'tcx>) {
62682a34
SL
4933 debug!("check_bounds_are_used(n_tps={}, ty={:?})",
4934 tps.len(), ty);
1a4d82fc
JJ
4935
4936 // make a vector of booleans initially false, set to true when used
9346a6ac 4937 if tps.is_empty() { return; }
1a4d82fc
JJ
4938 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
4939
4940 ty::walk_ty(ty, |t| {
4941 match t.sty {
62682a34 4942 ty::TyParam(ParamTy {idx, ..}) => {
1a4d82fc 4943 debug!("Found use of ty param num {}", idx);
c34b1796 4944 tps_used[idx as usize] = true;
1a4d82fc
JJ
4945 }
4946 _ => ()
4947 }
4948 });
4949
4950 for (i, b) in tps_used.iter().enumerate() {
4951 if !*b {
4952 span_err!(ccx.tcx.sess, span, E0091,
4953 "type parameter `{}` is unused",
4954 token::get_ident(tps[i].ident));
4955 }
4956 }
4957}
4958
d9579d0f
AL
4959/// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
4960/// and in libcore/intrinsics.rs
1a4d82fc
JJ
4961pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4962 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
85aaf69f 4963 let name = token::intern(&format!("P{}", n));
1a4d82fc
JJ
4964 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
4965 }
4966
4967 let tcx = ccx.tcx;
4968 let name = token::get_ident(it.ident);
85aaf69f
SL
4969 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
4970 let split : Vec<&str> = name.split('_').collect();
1a4d82fc
JJ
4971 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4972
4973 //We only care about the operation here
4974 let (n_tps, inputs, output) = match split[1] {
4975 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4976 param(ccx, 0),
4977 param(ccx, 0)),
4978 param(ccx, 0)),
4979 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4980 param(ccx, 0)),
4981 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4982 ty::mk_nil(tcx)),
4983
4984 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4985 "min" | "umax" | "umin" => {
4986 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4987 param(ccx, 0))
4988 }
d9579d0f 4989 "fence" | "singlethreadfence" => {
1a4d82fc
JJ
4990 (0, Vec::new(), ty::mk_nil(tcx))
4991 }
4992 op => {
4993 span_err!(tcx.sess, it.span, E0092,
4994 "unrecognized atomic operation function: `{}`", op);
4995 return;
4996 }
4997 };
4998 (n_tps, inputs, ty::FnConverging(output))
85aaf69f 4999 } else if &name[..] == "abort" || &name[..] == "unreachable" {
1a4d82fc
JJ
5000 (0, Vec::new(), ty::FnDiverging)
5001 } else {
85aaf69f 5002 let (n_tps, inputs, output) = match &name[..] {
1a4d82fc
JJ
5003 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5004 "size_of" |
c34b1796 5005 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
d9579d0f
AL
5006 "size_of_val" | "min_align_of_val" => {
5007 (1, vec![
5008 ty::mk_imm_rptr(tcx,
5009 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5010 ty::BrAnon(0))),
5011 param(ccx, 0))
5012 ], ccx.tcx.types.usize)
5013 }
c34b1796 5014 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
85aaf69f
SL
5015 "uninit" => (1, Vec::new(), param(ccx, 0)),
5016 "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
1a4d82fc
JJ
5017 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5018 "move_val_init" => {
85aaf69f 5019 (1,
1a4d82fc
JJ
5020 vec!(
5021 ty::mk_mut_rptr(tcx,
5022 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5023 ty::BrAnon(0))),
5024 param(ccx, 0)),
5025 param(ccx, 0)
5026 ),
5027 ty::mk_nil(tcx))
5028 }
d9579d0f
AL
5029 "drop_in_place" => {
5030 (1, vec![ty::mk_mut_ptr(tcx, param(ccx, 0))], ty::mk_nil(tcx))
5031 }
85aaf69f 5032 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
1a4d82fc 5033
c34b1796
AL
5034 "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
5035 ast::MutImmutable)),
85aaf69f 5036 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
62682a34 5037 "offset" | "arith_offset" => {
1a4d82fc
JJ
5038 (1,
5039 vec!(
5040 ty::mk_ptr(tcx, ty::mt {
5041 ty: param(ccx, 0),
5042 mutbl: ast::MutImmutable
5043 }),
c34b1796 5044 ccx.tcx.types.isize
1a4d82fc
JJ
5045 ),
5046 ty::mk_ptr(tcx, ty::mt {
5047 ty: param(ccx, 0),
5048 mutbl: ast::MutImmutable
5049 }))
5050 }
c34b1796
AL
5051 "copy" | "copy_nonoverlapping" => {
5052 (1,
5053 vec!(
5054 ty::mk_ptr(tcx, ty::mt {
5055 ty: param(ccx, 0),
5056 mutbl: ast::MutImmutable
5057 }),
5058 ty::mk_ptr(tcx, ty::mt {
5059 ty: param(ccx, 0),
5060 mutbl: ast::MutMutable
5061 }),
5062 tcx.types.usize,
5063 ),
5064 ty::mk_nil(tcx))
5065 }
1a4d82fc
JJ
5066 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5067 (1,
5068 vec!(
5069 ty::mk_ptr(tcx, ty::mt {
5070 ty: param(ccx, 0),
5071 mutbl: ast::MutMutable
5072 }),
5073 ty::mk_ptr(tcx, ty::mt {
5074 ty: param(ccx, 0),
5075 mutbl: ast::MutImmutable
5076 }),
c34b1796 5077 tcx.types.usize,
1a4d82fc
JJ
5078 ),
5079 ty::mk_nil(tcx))
5080 }
c34b1796 5081 "write_bytes" | "volatile_set_memory" => {
1a4d82fc
JJ
5082 (1,
5083 vec!(
5084 ty::mk_ptr(tcx, ty::mt {
5085 ty: param(ccx, 0),
5086 mutbl: ast::MutMutable
5087 }),
5088 tcx.types.u8,
c34b1796 5089 tcx.types.usize,
1a4d82fc
JJ
5090 ),
5091 ty::mk_nil(tcx))
5092 }
5093 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5094 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5095 "powif32" => {
5096 (0,
5097 vec!( tcx.types.f32, tcx.types.i32 ),
5098 tcx.types.f32)
5099 }
5100 "powif64" => {
5101 (0,
5102 vec!( tcx.types.f64, tcx.types.i32 ),
5103 tcx.types.f64)
5104 }
5105 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5106 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5107 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5108 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5109 "powf32" => {
5110 (0,
5111 vec!( tcx.types.f32, tcx.types.f32 ),
5112 tcx.types.f32)
5113 }
5114 "powf64" => {
5115 (0,
5116 vec!( tcx.types.f64, tcx.types.f64 ),
5117 tcx.types.f64)
5118 }
5119 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5120 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5121 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5122 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5123 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5124 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5125 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5126 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5127 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5128 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5129 "fmaf32" => {
5130 (0,
5131 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5132 tcx.types.f32)
5133 }
5134 "fmaf64" => {
5135 (0,
5136 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5137 tcx.types.f64)
5138 }
5139 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5140 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5141 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5142 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5143 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5144 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5145 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5146 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5147 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5148 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5149 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5150 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5151 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5152 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5153 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5154 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5155 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5156 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5157 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5158 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5159 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5160 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5161 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5162 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5163 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5164 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5165 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5166 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5167 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5168 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5169 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5170
5171 "volatile_load" =>
5172 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5173 "volatile_store" =>
5174 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5175
5176 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5177 (0, vec!(tcx.types.i8, tcx.types.i8),
5178 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5179
5180 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5181 (0, vec!(tcx.types.i16, tcx.types.i16),
5182 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5183
5184 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5185 (0, vec!(tcx.types.i32, tcx.types.i32),
5186 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5187
5188 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5189 (0, vec!(tcx.types.i64, tcx.types.i64),
5190 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5191
5192 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5193 (0, vec!(tcx.types.u8, tcx.types.u8),
5194 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5195
5196 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5197 (0, vec!(tcx.types.u16, tcx.types.u16),
5198 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5199
5200 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5201 (0, vec!(tcx.types.u32, tcx.types.u32),
5202 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5203
5204 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5205 (0, vec!(tcx.types.u64, tcx.types.u64),
5206 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5207
d9579d0f
AL
5208 "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
5209 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5210
c34b1796
AL
5211 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5212 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5213
1a4d82fc
JJ
5214 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5215
5216 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5217
9346a6ac
AL
5218 "discriminant_value" => (1, vec![
5219 ty::mk_imm_rptr(tcx,
5220 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5221 ty::BrAnon(0))),
5222 param(ccx, 0))], tcx.types.u64),
5223
1a4d82fc
JJ
5224 ref other => {
5225 span_err!(tcx.sess, it.span, E0093,
5226 "unrecognized intrinsic function: `{}`", *other);
5227 return;
5228 }
5229 };
5230 (n_tps, inputs, ty::FnConverging(output))
5231 };
5232 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5233 unsafety: ast::Unsafety::Unsafe,
5234 abi: abi::RustIntrinsic,
5235 sig: ty::Binder(FnSig {
5236 inputs: inputs,
5237 output: output,
5238 variadic: false,
5239 }),
5240 }));
5241 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5242 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5243 if i_n_tps != n_tps {
5244 span_err!(tcx.sess, it.span, E0094,
5245 "intrinsic has wrong number of type \
5246 parameters: found {}, expected {}",
5247 i_n_tps, n_tps);
5248 } else {
5249 require_same_types(tcx,
5250 None,
5251 false,
5252 it.span,
5253 i_ty.ty,
5254 fty,
5255 || {
5256 format!("intrinsic has wrong type: expected `{}`",
62682a34 5257 fty)
1a4d82fc
JJ
5258 });
5259 }
5260}