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