]>
Commit | Line | Data |
---|---|---|
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 | ||
15 | Within 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 | |
17 | function). Inference is used to supply types wherever they are | |
18 | unknown. | |
19 | ||
20 | By far the most complex case is checking the body of a function. This | |
21 | can 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 | ||
53 | While type checking a function, the intermediate types for the | |
54 | expressions, blocks, and so forth contained within the function are | |
7cac9316 | 55 | stored in `fcx.node_types` and `fcx.node_substs`. These types |
1a4d82fc JJ |
56 | may contain unresolved type variables. After type checking is |
57 | complete, the functions in the writeback module are used to take the | |
58 | types from this table, resolve them, and then write them into their | |
8bb4bdeb | 59 | permanent home in the type context `tcx`. |
1a4d82fc JJ |
60 | |
61 | This means that during inferencing you should use `fcx.write_ty()` | |
62 | and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of | |
63 | nodes within the function. | |
64 | ||
65 | The types of top-level items, which never contain unbound type | |
66 | variables, are stored directly into the `tcx` tables. | |
67 | ||
68 | n.b.: A type variable is not the same thing as a type parameter. A | |
69 | type variable is rather an "instance" of a type parameter: that is, | |
70 | given a generic function `fn foo<T>(t: T)`: while checking the | |
71 | function `foo`, the type `ty_param(0)` refers to the type `T`, which | |
72 | is treated in abstract. When `foo()` is called, however, `T` will be | |
73 | substituted for a fresh type variable `N`. This variable will | |
74 | eventually be resolved to some concrete type (which might itself be | |
75 | type parameter). | |
76 | ||
77 | */ | |
78 | ||
1a4d82fc | 79 | pub use self::Expectation::*; |
7cac9316 XL |
80 | use self::autoderef::Autoderef; |
81 | use self::callee::DeferredCallResolution; | |
cc61c64b | 82 | use self::coercion::{CoerceMany, DynamicCoerceMany}; |
d9579d0f | 83 | pub use self::compare_method::{compare_impl_method, compare_const_impl}; |
7cac9316 | 84 | use self::method::MethodCallee; |
1a4d82fc JJ |
85 | use self::TupleArgumentsFlag::*; |
86 | ||
32a655c1 | 87 | use astconv::AstConv; |
476ff2be | 88 | use hir::def::{Def, CtorKind}; |
cc61c64b XL |
89 | use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; |
90 | use rustc_back::slice::ref_slice; | |
abe05a73 | 91 | use namespace::Namespace; |
cc61c64b XL |
92 | use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; |
93 | use rustc::infer::type_variable::{TypeVariableOrigin}; | |
ea8adc8c | 94 | use rustc::middle::region; |
c30ab7b3 | 95 | use rustc::ty::subst::{Kind, Subst, Substs}; |
7cac9316 XL |
96 | use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; |
97 | use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; | |
8bb4bdeb | 98 | use rustc::ty::{self, Ty, TyCtxt, Visibility}; |
cc61c64b | 99 | use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; |
5bcae85e | 100 | use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; |
8bb4bdeb | 101 | use rustc::ty::maps::Providers; |
54a0048b | 102 | use rustc::ty::util::{Representability, IntTypeExt}; |
abe05a73 | 103 | use errors::{DiagnosticBuilder, DiagnosticId}; |
c1a9b12d | 104 | use require_c_abi_if_variadic; |
041b39d2 | 105 | use session::{CompileIncomplete, Session}; |
1a4d82fc | 106 | use TypeAndSubsts; |
1a4d82fc | 107 | use lint; |
476ff2be | 108 | use util::common::{ErrorReported, indenter}; |
abe05a73 | 109 | use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap}; |
1a4d82fc | 110 | |
041b39d2 | 111 | use std::cell::{Cell, RefCell, Ref, RefMut}; |
abe05a73 | 112 | use std::rc::Rc; |
cc61c64b | 113 | use std::collections::hash_map::Entry; |
476ff2be | 114 | use std::cmp; |
041b39d2 | 115 | use std::fmt::Display; |
1a4d82fc | 116 | use std::mem::replace; |
476ff2be | 117 | use std::ops::{self, Deref}; |
7453a54e | 118 | use syntax::abi::Abi; |
e9174d1e | 119 | use syntax::ast; |
abe05a73 | 120 | use syntax::attr; |
476ff2be | 121 | use syntax::codemap::{self, original_sp, Spanned}; |
5bcae85e | 122 | use syntax::feature_gate::{GateIssue, emit_feature_err}; |
1a4d82fc | 123 | use syntax::ptr::P; |
476ff2be | 124 | use syntax::symbol::{Symbol, InternedString, keywords}; |
9cc50fc6 | 125 | use syntax::util::lev_distance::find_best_match_for_name; |
3b2f2976 | 126 | use syntax_pos::{self, BytePos, Span, MultiSpan}; |
e9174d1e | 127 | |
476ff2be SL |
128 | use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; |
129 | use rustc::hir::itemlikevisit::ItemLikeVisitor; | |
041b39d2 | 130 | use rustc::hir::map::Node; |
54a0048b | 131 | use rustc::hir::{self, PatKind}; |
476ff2be | 132 | use rustc::middle::lang_items; |
b039eaaf | 133 | use rustc_back::slice; |
8bb4bdeb | 134 | use rustc_const_math::ConstInt; |
1a4d82fc | 135 | |
3157f602 | 136 | mod autoderef; |
85aaf69f | 137 | pub mod dropck; |
1a4d82fc | 138 | pub mod _match; |
1a4d82fc | 139 | pub mod writeback; |
abe05a73 | 140 | mod regionck; |
85aaf69f | 141 | pub mod coercion; |
1a4d82fc JJ |
142 | pub mod demand; |
143 | pub mod method; | |
144 | mod upvar; | |
e9174d1e | 145 | mod wfcheck; |
9346a6ac | 146 | mod cast; |
1a4d82fc JJ |
147 | mod closure; |
148 | mod callee; | |
85aaf69f | 149 | mod compare_method; |
ea8adc8c | 150 | mod generator_interior; |
e9174d1e | 151 | mod intrinsic; |
c34b1796 | 152 | mod op; |
1a4d82fc | 153 | |
041b39d2 XL |
154 | /// A wrapper for InferCtxt's `in_progress_tables` field. |
155 | #[derive(Copy, Clone)] | |
156 | struct MaybeInProgressTables<'a, 'tcx: 'a> { | |
157 | maybe_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>, | |
158 | } | |
159 | ||
160 | impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { | |
161 | fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { | |
162 | match self.maybe_tables { | |
163 | Some(tables) => tables.borrow(), | |
164 | None => { | |
165 | bug!("MaybeInProgressTables: inh/fcx.tables.borrow() with no tables") | |
166 | } | |
167 | } | |
168 | } | |
169 | ||
170 | fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { | |
171 | match self.maybe_tables { | |
172 | Some(tables) => tables.borrow_mut(), | |
173 | None => { | |
174 | bug!("MaybeInProgressTables: inh/fcx.tables.borrow_mut() with no tables") | |
175 | } | |
176 | } | |
177 | } | |
178 | } | |
179 | ||
180 | ||
1a4d82fc JJ |
181 | /// closures defined within the function. For example: |
182 | /// | |
183 | /// fn foo() { | |
184 | /// bar(move|| { ... }) | |
185 | /// } | |
186 | /// | |
187 | /// Here, the function `foo()` and the closure passed to | |
188 | /// `bar()` will each have their own `FnCtxt`, but they will | |
189 | /// share the inherited fields. | |
a7813a04 | 190 | pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { |
a7813a04 | 191 | infcx: InferCtxt<'a, 'gcx, 'tcx>, |
8bb4bdeb | 192 | |
041b39d2 XL |
193 | tables: MaybeInProgressTables<'a, 'tcx>, |
194 | ||
1a4d82fc | 195 | locals: RefCell<NodeMap<Ty<'tcx>>>, |
1a4d82fc | 196 | |
7453a54e SL |
197 | fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>, |
198 | ||
85aaf69f SL |
199 | // When we process a call like `c()` where `c` is a closure type, |
200 | // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or | |
201 | // `FnOnce` closure. In that case, we defer full resolution of the | |
202 | // call until upvar inference can kick in and make the | |
203 | // decision. We keep these deferred resolutions grouped by the | |
204 | // def-id of the closure, so that once we decide, we can easily go | |
205 | // back and process them. | |
7cac9316 | 206 | deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolution<'gcx, 'tcx>>>>, |
c34b1796 | 207 | |
9346a6ac | 208 | deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>, |
5bcae85e | 209 | |
ea8adc8c XL |
210 | deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>)>>, |
211 | ||
5bcae85e SL |
212 | // Anonymized types found in explicit return types and their |
213 | // associated fresh inference variable. Writeback resolves these | |
214 | // variables to get the concrete type, which can be used to | |
215 | // deanonymize TyAnon, after typeck is done with all functions. | |
8bb4bdeb | 216 | anon_types: RefCell<NodeMap<Ty<'tcx>>>, |
7cac9316 XL |
217 | |
218 | /// Each type parameter has an implicit region bound that | |
219 | /// indicates it must outlive at least the function body (the user | |
220 | /// may specify stronger requirements). This field indicates the | |
221 | /// region of the callee. If it is `None`, then the parameter | |
222 | /// environment is for an item or something where the "callee" is | |
223 | /// not clear. | |
224 | implicit_region_bound: Option<ty::Region<'tcx>>, | |
041b39d2 XL |
225 | |
226 | body_id: Option<hir::BodyId>, | |
85aaf69f SL |
227 | } |
228 | ||
a7813a04 XL |
229 | impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { |
230 | type Target = InferCtxt<'a, 'gcx, 'tcx>; | |
231 | fn deref(&self) -> &Self::Target { | |
232 | &self.infcx | |
233 | } | |
234 | } | |
235 | ||
1a4d82fc JJ |
236 | /// When type-checking an expression, we propagate downward |
237 | /// whatever type hint we are able in the form of an `Expectation`. | |
62682a34 | 238 | #[derive(Copy, Clone, Debug)] |
c34b1796 | 239 | pub enum Expectation<'tcx> { |
1a4d82fc JJ |
240 | /// We know nothing about what type this expression should have. |
241 | NoExpectation, | |
242 | ||
041b39d2 XL |
243 | /// This expression is an `if` condition, it must resolve to `bool`. |
244 | ExpectIfCondition, | |
245 | ||
1a4d82fc JJ |
246 | /// This expression should have the type given (or some subtype) |
247 | ExpectHasType(Ty<'tcx>), | |
248 | ||
249 | /// This expression will be cast to the `Ty` | |
250 | ExpectCastableToType(Ty<'tcx>), | |
251 | ||
252 | /// This rvalue expression will be wrapped in `&` or `Box` and coerced | |
253 | /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`. | |
254 | ExpectRvalueLikeUnsized(Ty<'tcx>), | |
255 | } | |
256 | ||
a7813a04 | 257 | impl<'a, 'gcx, 'tcx> Expectation<'tcx> { |
1a4d82fc JJ |
258 | // Disregard "castable to" expectations because they |
259 | // can lead us astray. Consider for example `if cond | |
260 | // {22} else {c} as u8` -- if we propagate the | |
261 | // "castable to u8" constraint to 22, it will pick the | |
262 | // type 22u8, which is overly constrained (c might not | |
263 | // be a u8). In effect, the problem is that the | |
264 | // "castable to" expectation is not the tightest thing | |
265 | // we can say, so we want to drop it in this case. | |
266 | // The tightest thing we can say is "must unify with | |
267 | // else branch". Note that in the case of a "has type" | |
268 | // constraint, this limitation does not hold. | |
269 | ||
270 | // If the expected type is just a type variable, then don't use | |
271 | // an expected type. Otherwise, we might write parts of the type | |
272 | // when checking the 'then' block which are incompatible with the | |
273 | // 'else' branch. | |
a7813a04 | 274 | fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> { |
1a4d82fc JJ |
275 | match *self { |
276 | ExpectHasType(ety) => { | |
a7813a04 | 277 | let ety = fcx.shallow_resolve(ety); |
c1a9b12d | 278 | if !ety.is_ty_var() { |
1a4d82fc JJ |
279 | ExpectHasType(ety) |
280 | } else { | |
281 | NoExpectation | |
282 | } | |
283 | } | |
284 | ExpectRvalueLikeUnsized(ety) => { | |
285 | ExpectRvalueLikeUnsized(ety) | |
286 | } | |
287 | _ => NoExpectation | |
288 | } | |
289 | } | |
a7813a04 XL |
290 | |
291 | /// Provide an expectation for an rvalue expression given an *optional* | |
292 | /// hint, which is not required for type safety (the resulting type might | |
293 | /// be checked higher up, as is the case with `&expr` and `box expr`), but | |
294 | /// is useful in determining the concrete type. | |
295 | /// | |
296 | /// The primary use case is where the expected type is a fat pointer, | |
297 | /// like `&[isize]`. For example, consider the following statement: | |
298 | /// | |
299 | /// let x: &[isize] = &[1, 2, 3]; | |
300 | /// | |
301 | /// In this case, the expected type for the `&[1, 2, 3]` expression is | |
302 | /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the | |
303 | /// expectation `ExpectHasType([isize])`, that would be too strong -- | |
304 | /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`. | |
305 | /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced | |
306 | /// to the type `&[isize]`. Therefore, we propagate this more limited hint, | |
307 | /// which still is useful, because it informs integer literals and the like. | |
308 | /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169 | |
309 | /// for examples of where this comes up,. | |
310 | fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { | |
311 | match fcx.tcx.struct_tail(ty).sty { | |
476ff2be | 312 | ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => { |
a7813a04 XL |
313 | ExpectRvalueLikeUnsized(ty) |
314 | } | |
315 | _ => ExpectHasType(ty) | |
316 | } | |
317 | } | |
318 | ||
319 | // Resolves `expected` by a single level if it is a variable. If | |
320 | // there is no expected type or resolution is not possible (e.g., | |
321 | // no constraints yet present), just returns `None`. | |
322 | fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> { | |
323 | match self { | |
041b39d2 XL |
324 | NoExpectation => NoExpectation, |
325 | ExpectIfCondition => ExpectIfCondition, | |
a7813a04 XL |
326 | ExpectCastableToType(t) => { |
327 | ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t)) | |
328 | } | |
329 | ExpectHasType(t) => { | |
330 | ExpectHasType(fcx.resolve_type_vars_if_possible(&t)) | |
331 | } | |
332 | ExpectRvalueLikeUnsized(t) => { | |
333 | ExpectRvalueLikeUnsized(fcx.resolve_type_vars_if_possible(&t)) | |
334 | } | |
335 | } | |
336 | } | |
337 | ||
338 | fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> { | |
339 | match self.resolve(fcx) { | |
340 | NoExpectation => None, | |
041b39d2 | 341 | ExpectIfCondition => Some(fcx.tcx.types.bool), |
a7813a04 XL |
342 | ExpectCastableToType(ty) | |
343 | ExpectHasType(ty) | | |
344 | ExpectRvalueLikeUnsized(ty) => Some(ty), | |
345 | } | |
346 | } | |
347 | ||
cc61c64b XL |
348 | /// It sometimes happens that we want to turn an expectation into |
349 | /// a **hard constraint** (i.e., something that must be satisfied | |
350 | /// for the program to type-check). `only_has_type` will return | |
351 | /// such a constraint, if it exists. | |
a7813a04 XL |
352 | fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> { |
353 | match self.resolve(fcx) { | |
354 | ExpectHasType(ty) => Some(ty), | |
041b39d2 XL |
355 | ExpectIfCondition => Some(fcx.tcx.types.bool), |
356 | NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, | |
a7813a04 XL |
357 | } |
358 | } | |
cc61c64b XL |
359 | |
360 | /// Like `only_has_type`, but instead of returning `None` if no | |
361 | /// hard constraint exists, creates a fresh type variable. | |
362 | fn coercion_target_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'tcx> { | |
363 | self.only_has_type(fcx) | |
364 | .unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span))) | |
365 | } | |
1a4d82fc JJ |
366 | } |
367 | ||
368 | #[derive(Copy, Clone)] | |
369 | pub struct UnsafetyState { | |
370 | pub def: ast::NodeId, | |
e9174d1e | 371 | pub unsafety: hir::Unsafety, |
c1a9b12d | 372 | pub unsafe_push_count: u32, |
1a4d82fc JJ |
373 | from_fn: bool |
374 | } | |
375 | ||
376 | impl UnsafetyState { | |
e9174d1e | 377 | pub fn function(unsafety: hir::Unsafety, def: ast::NodeId) -> UnsafetyState { |
c1a9b12d | 378 | UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true } |
1a4d82fc JJ |
379 | } |
380 | ||
e9174d1e | 381 | pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState { |
1a4d82fc JJ |
382 | match self.unsafety { |
383 | // If this unsafe, then if the outer function was already marked as | |
384 | // unsafe we shouldn't attribute the unsafe'ness to the block. This | |
385 | // way the block can be warned about instead of ignoring this | |
386 | // extraneous block (functions are never warned about). | |
e9174d1e | 387 | hir::Unsafety::Unsafe if self.from_fn => *self, |
1a4d82fc JJ |
388 | |
389 | unsafety => { | |
c1a9b12d | 390 | let (unsafety, def, count) = match blk.rules { |
e9174d1e | 391 | hir::PushUnsafeBlock(..) => |
c1a9b12d | 392 | (unsafety, blk.id, self.unsafe_push_count.checked_add(1).unwrap()), |
e9174d1e | 393 | hir::PopUnsafeBlock(..) => |
c1a9b12d | 394 | (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()), |
e9174d1e SL |
395 | hir::UnsafeBlock(..) => |
396 | (hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count), | |
476ff2be | 397 | hir::DefaultBlock => |
c1a9b12d | 398 | (unsafety, self.def, self.unsafe_push_count), |
1a4d82fc | 399 | }; |
3b2f2976 XL |
400 | UnsafetyState{ def, |
401 | unsafety, | |
c1a9b12d SL |
402 | unsafe_push_count: count, |
403 | from_fn: false } | |
1a4d82fc JJ |
404 | } |
405 | } | |
406 | } | |
407 | } | |
408 | ||
cc61c64b XL |
409 | #[derive(Debug, Copy, Clone)] |
410 | pub enum LvalueOp { | |
411 | Deref, | |
412 | Index | |
413 | } | |
414 | ||
cc61c64b XL |
415 | /// Tracks whether executing a node may exit normally (versus |
416 | /// return/break/panic, which "diverge", leaving dead code in their | |
417 | /// wake). Tracked semi-automatically (through type variables marked | |
418 | /// as diverging), with some manual adjustments for control-flow | |
419 | /// primitives (approximating a CFG). | |
420 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] | |
421 | pub enum Diverges { | |
476ff2be SL |
422 | /// Potentially unknown, some cases converge, |
423 | /// others require a CFG to determine them. | |
424 | Maybe, | |
425 | ||
426 | /// Definitely known to diverge and therefore | |
427 | /// not reach the next sibling or its parent. | |
428 | Always, | |
429 | ||
430 | /// Same as `Always` but with a reachability | |
431 | /// warning already emitted | |
432 | WarnedAlways | |
433 | } | |
434 | ||
435 | // Convenience impls for combinig `Diverges`. | |
436 | ||
437 | impl ops::BitAnd for Diverges { | |
438 | type Output = Self; | |
439 | fn bitand(self, other: Self) -> Self { | |
440 | cmp::min(self, other) | |
441 | } | |
442 | } | |
443 | ||
444 | impl ops::BitOr for Diverges { | |
445 | type Output = Self; | |
446 | fn bitor(self, other: Self) -> Self { | |
447 | cmp::max(self, other) | |
448 | } | |
449 | } | |
450 | ||
451 | impl ops::BitAndAssign for Diverges { | |
452 | fn bitand_assign(&mut self, other: Self) { | |
453 | *self = *self & other; | |
454 | } | |
455 | } | |
456 | ||
457 | impl ops::BitOrAssign for Diverges { | |
458 | fn bitor_assign(&mut self, other: Self) { | |
459 | *self = *self | other; | |
460 | } | |
461 | } | |
462 | ||
463 | impl Diverges { | |
464 | fn always(self) -> bool { | |
465 | self >= Diverges::Always | |
466 | } | |
467 | } | |
468 | ||
cc61c64b | 469 | pub struct BreakableCtxt<'gcx: 'tcx, 'tcx> { |
476ff2be | 470 | may_break: bool, |
cc61c64b XL |
471 | |
472 | // this is `null` for loops where break with a value is illegal, | |
473 | // such as `while`, `for`, and `while let` | |
474 | coerce: Option<DynamicCoerceMany<'gcx, 'tcx>>, | |
476ff2be SL |
475 | } |
476 | ||
cc61c64b XL |
477 | pub struct EnclosingBreakables<'gcx: 'tcx, 'tcx> { |
478 | stack: Vec<BreakableCtxt<'gcx, 'tcx>>, | |
476ff2be SL |
479 | by_id: NodeMap<usize>, |
480 | } | |
481 | ||
cc61c64b XL |
482 | impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> { |
483 | fn find_breakable(&mut self, target_id: ast::NodeId) -> &mut BreakableCtxt<'gcx, 'tcx> { | |
484 | let ix = *self.by_id.get(&target_id).unwrap_or_else(|| { | |
485 | bug!("could not find enclosing breakable with id {}", target_id); | |
486 | }); | |
487 | &mut self.stack[ix] | |
476ff2be SL |
488 | } |
489 | } | |
490 | ||
a7813a04 | 491 | pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { |
1a4d82fc JJ |
492 | body_id: ast::NodeId, |
493 | ||
7cac9316 XL |
494 | /// The parameter environment used for proving trait obligations |
495 | /// in this function. This can change when we descend into | |
496 | /// closures (as they bring new things into scope), hence it is | |
497 | /// not part of `Inherited` (as of the time of this writing, | |
498 | /// closures do not yet change the environment, but they will | |
499 | /// eventually). | |
500 | param_env: ty::ParamEnv<'tcx>, | |
501 | ||
1a4d82fc JJ |
502 | // Number of errors that had been reported when we started |
503 | // checking this function. On exit, if we find that *more* errors | |
504 | // have been reported, we will skip regionck and other work that | |
505 | // expects the types within the function to be consistent. | |
c34b1796 | 506 | err_count_on_creation: usize, |
1a4d82fc | 507 | |
cc61c64b | 508 | ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>, |
1a4d82fc | 509 | |
ea8adc8c XL |
510 | yield_ty: Option<Ty<'tcx>>, |
511 | ||
1a4d82fc JJ |
512 | ps: RefCell<UnsafetyState>, |
513 | ||
cc61c64b XL |
514 | /// Whether the last checked node generates a divergence (e.g., |
515 | /// `return` will set this to Always). In general, when entering | |
516 | /// an expression or other node in the tree, the initial value | |
517 | /// indicates whether prior parts of the containing expression may | |
518 | /// have diverged. It is then typically set to `Maybe` (and the | |
519 | /// old value remembered) for processing the subparts of the | |
520 | /// current expression. As each subpart is processed, they may set | |
521 | /// the flag to `Always` etc. Finally, at the end, we take the | |
522 | /// result and "union" it with the original value, so that when we | |
523 | /// return the flag indicates if any subpart of the the parent | |
524 | /// expression (up to and including this part) has diverged. So, | |
525 | /// if you read it after evaluating a subexpression `X`, the value | |
526 | /// you get indicates whether any subexpression that was | |
527 | /// evaluating up to and including `X` diverged. | |
528 | /// | |
529 | /// We use this flag for two purposes: | |
530 | /// | |
531 | /// - To warn about unreachable code: if, after processing a | |
532 | /// sub-expression but before we have applied the effects of the | |
533 | /// current node, we see that the flag is set to `Always`, we | |
534 | /// can issue a warning. This corresponds to something like | |
535 | /// `foo(return)`; we warn on the `foo()` expression. (We then | |
536 | /// update the flag to `WarnedAlways` to suppress duplicate | |
537 | /// reports.) Similarly, if we traverse to a fresh statement (or | |
3b2f2976 | 538 | /// tail expression) from a `Always` setting, we will issue a |
cc61c64b XL |
539 | /// warning. This corresponds to something like `{return; |
540 | /// foo();}` or `{return; 22}`, where we would warn on the | |
541 | /// `foo()` or `22`. | |
542 | /// | |
543 | /// - To permit assignment into a local variable or other lvalue | |
544 | /// (including the "return slot") of type `!`. This is allowed | |
545 | /// if **either** the type of value being assigned is `!`, which | |
546 | /// means the current code is dead, **or** the expression's | |
3b2f2976 | 547 | /// diverging flag is true, which means that a diverging value was |
cc61c64b XL |
548 | /// wrapped (e.g., `let x: ! = foo(return)`). |
549 | /// | |
550 | /// To repeat the last point: an expression represents dead-code | |
551 | /// if, after checking it, **either** its type is `!` OR the | |
552 | /// diverges flag is set to something other than `Maybe`. | |
476ff2be SL |
553 | diverges: Cell<Diverges>, |
554 | ||
555 | /// Whether any child nodes have any type errors. | |
556 | has_errors: Cell<bool>, | |
557 | ||
cc61c64b | 558 | enclosing_breakables: RefCell<EnclosingBreakables<'gcx, 'tcx>>, |
476ff2be | 559 | |
a7813a04 XL |
560 | inh: &'a Inherited<'a, 'gcx, 'tcx>, |
561 | } | |
562 | ||
563 | impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> { | |
564 | type Target = Inherited<'a, 'gcx, 'tcx>; | |
565 | fn deref(&self) -> &Self::Target { | |
566 | &self.inh | |
567 | } | |
568 | } | |
1a4d82fc | 569 | |
8bb4bdeb | 570 | /// Helper type of a temporary returned by Inherited::build(...). |
a7813a04 XL |
571 | /// Necessary because we can't write the following bound: |
572 | /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>). | |
573 | pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
7cac9316 XL |
574 | infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>, |
575 | def_id: DefId, | |
1a4d82fc JJ |
576 | } |
577 | ||
8bb4bdeb | 578 | impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { |
7cac9316 | 579 | pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) |
8bb4bdeb | 580 | -> InheritedBuilder<'a, 'gcx, 'tcx> { |
3b2f2976 XL |
581 | let hir_id_root = if def_id.is_local() { |
582 | let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
583 | let hir_id = tcx.hir.definitions().node_to_hir_id(node_id); | |
584 | DefId::local(hir_id.owner) | |
585 | } else { | |
586 | def_id | |
587 | }; | |
588 | ||
a7813a04 | 589 | InheritedBuilder { |
3b2f2976 | 590 | infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(hir_id_root), |
7cac9316 | 591 | def_id, |
1a4d82fc JJ |
592 | } |
593 | } | |
a7813a04 XL |
594 | } |
595 | ||
596 | impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { | |
597 | fn enter<F, R>(&'tcx mut self, f: F) -> R | |
598 | where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R | |
599 | { | |
7cac9316 XL |
600 | let def_id = self.def_id; |
601 | self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id))) | |
a7813a04 XL |
602 | } |
603 | } | |
1a4d82fc | 604 | |
a7813a04 | 605 | impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { |
7cac9316 XL |
606 | fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { |
607 | let tcx = infcx.tcx; | |
608 | let item_id = tcx.hir.as_local_node_id(def_id); | |
609 | let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); | |
ea8adc8c XL |
610 | let implicit_region_bound = body_id.map(|body_id| { |
611 | let body = tcx.hir.body(body_id); | |
612 | tcx.mk_region(ty::ReScope(region::Scope::CallSite(body.value.hir_id.local_id))) | |
7cac9316 XL |
613 | }); |
614 | ||
c30ab7b3 | 615 | Inherited { |
041b39d2 XL |
616 | tables: MaybeInProgressTables { |
617 | maybe_tables: infcx.in_progress_tables, | |
618 | }, | |
3b2f2976 | 619 | infcx, |
c30ab7b3 SL |
620 | fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), |
621 | locals: RefCell::new(NodeMap()), | |
622 | deferred_call_resolutions: RefCell::new(DefIdMap()), | |
623 | deferred_cast_checks: RefCell::new(Vec::new()), | |
ea8adc8c | 624 | deferred_generator_interiors: RefCell::new(Vec::new()), |
8bb4bdeb | 625 | anon_types: RefCell::new(NodeMap()), |
7cac9316 | 626 | implicit_region_bound, |
041b39d2 | 627 | body_id, |
c30ab7b3 SL |
628 | } |
629 | } | |
630 | ||
cc61c64b XL |
631 | fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { |
632 | debug!("register_predicate({:?})", obligation); | |
633 | if obligation.has_escaping_regions() { | |
634 | span_bug!(obligation.cause.span, "escaping regions in predicate {:?}", | |
635 | obligation); | |
636 | } | |
637 | self.fulfillment_cx | |
638 | .borrow_mut() | |
639 | .register_predicate_obligation(self, obligation); | |
640 | } | |
641 | ||
7cac9316 XL |
642 | fn register_predicates<I>(&self, obligations: I) |
643 | where I: IntoIterator<Item = traits::PredicateObligation<'tcx>> { | |
cc61c64b XL |
644 | for obligation in obligations { |
645 | self.register_predicate(obligation); | |
646 | } | |
647 | } | |
648 | ||
649 | fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T { | |
650 | self.register_predicates(infer_ok.obligations); | |
651 | infer_ok.value | |
652 | } | |
653 | ||
1a4d82fc | 654 | fn normalize_associated_types_in<T>(&self, |
1a4d82fc JJ |
655 | span: Span, |
656 | body_id: ast::NodeId, | |
7cac9316 | 657 | param_env: ty::ParamEnv<'tcx>, |
cc61c64b | 658 | value: &T) -> T |
9cc50fc6 | 659 | where T : TypeFoldable<'tcx> |
1a4d82fc | 660 | { |
abe05a73 | 661 | let ok = self.partially_normalize_associated_types_in(span, body_id, param_env, value); |
cc61c64b | 662 | self.register_infer_ok_obligations(ok) |
1a4d82fc JJ |
663 | } |
664 | ||
7cac9316 XL |
665 | /// Replace any late-bound regions bound in `value` with |
666 | /// free variants attached to `all_outlive_scope`. | |
667 | fn liberate_late_bound_regions<T>(&self, | |
668 | all_outlive_scope: DefId, | |
669 | value: &ty::Binder<T>) | |
670 | -> T | |
671 | where T: TypeFoldable<'tcx> | |
672 | { | |
673 | self.tcx.replace_late_bound_regions(value, |br| { | |
674 | self.tcx.mk_region(ty::ReFree(ty::FreeRegion { | |
675 | scope: all_outlive_scope, | |
676 | bound_region: br | |
677 | })) | |
678 | }).0 | |
679 | } | |
1a4d82fc JJ |
680 | } |
681 | ||
8bb4bdeb | 682 | struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } |
476ff2be | 683 | |
8bb4bdeb | 684 | impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { |
e9174d1e | 685 | fn visit_item(&mut self, i: &'tcx hir::Item) { |
8bb4bdeb | 686 | check_item_type(self.tcx, i); |
1a4d82fc | 687 | } |
8bb4bdeb XL |
688 | fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { } |
689 | fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } | |
690 | } | |
1a4d82fc | 691 | |
041b39d2 | 692 | pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { |
8bb4bdeb XL |
693 | tcx.sess.track_errors(|| { |
694 | let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); | |
cc61c64b | 695 | tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor()); |
8bb4bdeb XL |
696 | }) |
697 | } | |
1a4d82fc | 698 | |
041b39d2 | 699 | pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { |
8bb4bdeb | 700 | tcx.sess.track_errors(|| { |
cc61c64b | 701 | tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); |
8bb4bdeb XL |
702 | }) |
703 | } | |
32a655c1 | 704 | |
041b39d2 | 705 | pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { |
7cac9316 | 706 | tcx.typeck_item_bodies(LOCAL_CRATE) |
cc61c64b | 707 | } |
32a655c1 | 708 | |
041b39d2 XL |
709 | fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) |
710 | -> Result<(), CompileIncomplete> | |
711 | { | |
cc61c64b | 712 | debug_assert!(crate_num == LOCAL_CRATE); |
041b39d2 | 713 | Ok(tcx.sess.track_errors(|| { |
7cac9316 | 714 | for body_owner_def_id in tcx.body_owners() { |
abe05a73 | 715 | ty::maps::queries::typeck_tables_of::ensure(tcx, body_owner_def_id); |
7cac9316 | 716 | } |
041b39d2 | 717 | })?) |
1a4d82fc JJ |
718 | } |
719 | ||
8bb4bdeb XL |
720 | pub fn provide(providers: &mut Providers) { |
721 | *providers = Providers { | |
cc61c64b | 722 | typeck_item_bodies, |
7cac9316 XL |
723 | typeck_tables_of, |
724 | has_typeck_tables, | |
8bb4bdeb | 725 | closure_kind, |
ea8adc8c | 726 | generator_sig, |
8bb4bdeb | 727 | adt_destructor, |
abe05a73 | 728 | used_trait_imports, |
8bb4bdeb XL |
729 | ..*providers |
730 | }; | |
731 | } | |
476ff2be | 732 | |
ea8adc8c XL |
733 | fn generator_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
734 | def_id: DefId) | |
735 | -> Option<ty::PolyGenSig<'tcx>> { | |
736 | let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
737 | let hir_id = tcx.hir.node_to_hir_id(node_id); | |
738 | tcx.typeck_tables_of(def_id).generator_sigs()[hir_id].map(|s| ty::Binder(s)) | |
739 | } | |
740 | ||
8bb4bdeb XL |
741 | fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
742 | def_id: DefId) | |
743 | -> ty::ClosureKind { | |
744 | let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
3b2f2976 XL |
745 | let hir_id = tcx.hir.node_to_hir_id(node_id); |
746 | tcx.typeck_tables_of(def_id).closure_kinds()[hir_id].0 | |
e9174d1e | 747 | } |
c34b1796 | 748 | |
8bb4bdeb XL |
749 | fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
750 | def_id: DefId) | |
751 | -> Option<ty::Destructor> { | |
752 | tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl) | |
e9174d1e SL |
753 | } |
754 | ||
7cac9316 XL |
755 | /// If this def-id is a "primary tables entry", returns `Some((body_id, decl))` |
756 | /// with information about it's body-id and fn-decl (if any). Otherwise, | |
757 | /// returns `None`. | |
758 | /// | |
759 | /// If this function returns "some", then `typeck_tables(def_id)` will | |
760 | /// succeed; if it returns `None`, then `typeck_tables(def_id)` may or | |
761 | /// may not succeed. In some cases where this function returns `None` | |
762 | /// (notably closures), `typeck_tables(def_id)` would wind up | |
763 | /// redirecting to the owning function. | |
764 | fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
765 | id: ast::NodeId) | |
766 | -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)> | |
767 | { | |
768 | match tcx.hir.get(id) { | |
8bb4bdeb XL |
769 | hir::map::NodeItem(item) => { |
770 | match item.node { | |
771 | hir::ItemConst(_, body) | | |
7cac9316 XL |
772 | hir::ItemStatic(_, _, body) => |
773 | Some((body, None)), | |
774 | hir::ItemFn(ref decl, .., body) => | |
775 | Some((body, Some(decl))), | |
776 | _ => | |
777 | None, | |
8bb4bdeb | 778 | } |
5bcae85e | 779 | } |
8bb4bdeb XL |
780 | hir::map::NodeTraitItem(item) => { |
781 | match item.node { | |
7cac9316 XL |
782 | hir::TraitItemKind::Const(_, Some(body)) => |
783 | Some((body, None)), | |
784 | hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => | |
785 | Some((body, Some(&sig.decl))), | |
786 | _ => | |
787 | None, | |
8bb4bdeb XL |
788 | } |
789 | } | |
790 | hir::map::NodeImplItem(item) => { | |
791 | match item.node { | |
7cac9316 XL |
792 | hir::ImplItemKind::Const(_, body) => |
793 | Some((body, None)), | |
794 | hir::ImplItemKind::Method(ref sig, body) => | |
795 | Some((body, Some(&sig.decl))), | |
796 | _ => | |
797 | None, | |
c34b1796 | 798 | } |
8bb4bdeb XL |
799 | } |
800 | hir::map::NodeExpr(expr) => { | |
801 | // FIXME(eddyb) Closures should have separate | |
802 | // function definition IDs and expression IDs. | |
803 | // Type-checking should not let closures get | |
804 | // this far in a constant position. | |
805 | // Assume that everything other than closures | |
806 | // is a constant "initializer" expression. | |
807 | match expr.node { | |
7cac9316 XL |
808 | hir::ExprClosure(..) => |
809 | None, | |
810 | _ => | |
811 | Some((hir::BodyId { node_id: expr.id }, None)), | |
8bb4bdeb XL |
812 | } |
813 | } | |
7cac9316 XL |
814 | _ => None, |
815 | } | |
816 | } | |
817 | ||
818 | fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
819 | def_id: DefId) | |
820 | -> bool { | |
821 | // Closures' tables come from their outermost function, | |
822 | // as they are part of the same "inference environment". | |
823 | let outer_def_id = tcx.closure_base_def_id(def_id); | |
824 | if outer_def_id != def_id { | |
825 | return tcx.has_typeck_tables(outer_def_id); | |
826 | } | |
827 | ||
828 | let id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
829 | primary_body_of(tcx, id).is_some() | |
830 | } | |
831 | ||
abe05a73 XL |
832 | fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
833 | def_id: DefId) | |
834 | -> Rc<DefIdSet> { | |
835 | tcx.typeck_tables_of(def_id).used_trait_imports.clone() | |
836 | } | |
837 | ||
7cac9316 XL |
838 | fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
839 | def_id: DefId) | |
840 | -> &'tcx ty::TypeckTables<'tcx> { | |
841 | // Closures' tables come from their outermost function, | |
842 | // as they are part of the same "inference environment". | |
843 | let outer_def_id = tcx.closure_base_def_id(def_id); | |
844 | if outer_def_id != def_id { | |
845 | return tcx.typeck_tables_of(outer_def_id); | |
846 | } | |
847 | ||
848 | let id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
849 | let span = tcx.hir.span(id); | |
850 | ||
851 | // Figure out what primary body this item has. | |
852 | let (body_id, fn_decl) = primary_body_of(tcx, id).unwrap_or_else(|| { | |
853 | span_bug!(span, "can't type-check body of {:?}", def_id); | |
854 | }); | |
8bb4bdeb XL |
855 | let body = tcx.hir.body(body_id); |
856 | ||
3b2f2976 | 857 | let tables = Inherited::build(tcx, def_id).enter(|inh| { |
7cac9316 | 858 | let param_env = tcx.param_env(def_id); |
8bb4bdeb | 859 | let fcx = if let Some(decl) = fn_decl { |
041b39d2 | 860 | let fn_sig = tcx.fn_sig(def_id); |
8bb4bdeb XL |
861 | |
862 | check_abi(tcx, span, fn_sig.abi()); | |
a7813a04 | 863 | |
8bb4bdeb | 864 | // Compute the fty from point of view of inside fn. |
8bb4bdeb | 865 | let fn_sig = |
7cac9316 | 866 | inh.liberate_late_bound_regions(def_id, &fn_sig); |
8bb4bdeb | 867 | let fn_sig = |
7cac9316 XL |
868 | inh.normalize_associated_types_in(body.value.span, |
869 | body_id.node_id, | |
870 | param_env, | |
871 | &fn_sig); | |
c30ab7b3 | 872 | |
ea8adc8c | 873 | check_fn(&inh, param_env, fn_sig, decl, id, body, false).0 |
8bb4bdeb | 874 | } else { |
7cac9316 XL |
875 | let fcx = FnCtxt::new(&inh, param_env, body.value.id); |
876 | let expected_type = tcx.type_of(def_id); | |
8bb4bdeb XL |
877 | let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type); |
878 | fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); | |
879 | ||
880 | // Gather locals in statics (because of block expressions). | |
881 | // This is technically unnecessary because locals in static items are forbidden, | |
882 | // but prevents type checking from blowing up before const checking can properly | |
883 | // emit an error. | |
884 | GatherLocalsVisitor { fcx: &fcx }.visit_body(body); | |
a7813a04 | 885 | |
8bb4bdeb XL |
886 | fcx.check_expr_coercable_to_type(&body.value, expected_type); |
887 | ||
888 | fcx | |
889 | }; | |
a7813a04 XL |
890 | |
891 | fcx.select_all_obligations_and_apply_defaults(); | |
476ff2be | 892 | fcx.closure_analyze(body); |
a7813a04 XL |
893 | fcx.select_obligations_where_possible(); |
894 | fcx.check_casts(); | |
ea8adc8c | 895 | fcx.resolve_generator_interiors(def_id); |
8bb4bdeb | 896 | fcx.select_all_obligations_or_error(); |
a7813a04 | 897 | |
8bb4bdeb XL |
898 | if fn_decl.is_some() { |
899 | fcx.regionck_fn(id, body); | |
900 | } else { | |
901 | fcx.regionck_expr(body); | |
902 | } | |
903 | ||
904 | fcx.resolve_type_vars_in_body(body) | |
3b2f2976 XL |
905 | }); |
906 | ||
907 | // Consistency check our TypeckTables instance can hold all ItemLocalIds | |
908 | // it will need to hold. | |
909 | assert_eq!(tables.local_id_root, | |
910 | Some(DefId::local(tcx.hir.definitions().node_to_hir_id(id).owner))); | |
911 | tables | |
1a4d82fc JJ |
912 | } |
913 | ||
8bb4bdeb XL |
914 | fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { |
915 | if !tcx.sess.target.target.is_abi_supported(abi) { | |
916 | struct_span_err!(tcx.sess, span, E0570, | |
c30ab7b3 SL |
917 | "The ABI `{}` is not supported for the current target", abi).emit() |
918 | } | |
919 | } | |
920 | ||
a7813a04 XL |
921 | struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { |
922 | fcx: &'a FnCtxt<'a, 'gcx, 'tcx> | |
1a4d82fc JJ |
923 | } |
924 | ||
a7813a04 | 925 | impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> { |
476ff2be | 926 | fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> { |
1a4d82fc JJ |
927 | match ty_opt { |
928 | None => { | |
929 | // infer the variable's type | |
476ff2be | 930 | let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); |
a7813a04 | 931 | self.fcx.locals.borrow_mut().insert(nid, var_ty); |
1a4d82fc JJ |
932 | var_ty |
933 | } | |
934 | Some(typ) => { | |
935 | // take type that the user specified | |
a7813a04 | 936 | self.fcx.locals.borrow_mut().insert(nid, typ); |
1a4d82fc JJ |
937 | typ |
938 | } | |
939 | } | |
940 | } | |
941 | } | |
942 | ||
a7813a04 | 943 | impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { |
476ff2be SL |
944 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { |
945 | NestedVisitorMap::None | |
946 | } | |
947 | ||
1a4d82fc | 948 | // Add explicitly-declared locals. |
a7813a04 | 949 | fn visit_local(&mut self, local: &'gcx hir::Local) { |
1a4d82fc | 950 | let o_ty = match local.ty { |
7453a54e | 951 | Some(ref ty) => Some(self.fcx.to_ty(&ty)), |
1a4d82fc JJ |
952 | None => None |
953 | }; | |
954 | self.assign(local.span, local.id, o_ty); | |
62682a34 SL |
955 | debug!("Local variable {:?} is assigned type {}", |
956 | local.pat, | |
a7813a04 XL |
957 | self.fcx.ty_to_string( |
958 | self.fcx.locals.borrow().get(&local.id).unwrap().clone())); | |
92a42be0 | 959 | intravisit::walk_local(self, local); |
1a4d82fc JJ |
960 | } |
961 | ||
962 | // Add pattern bindings. | |
a7813a04 | 963 | fn visit_pat(&mut self, p: &'gcx hir::Pat) { |
476ff2be | 964 | if let PatKind::Binding(_, _, ref path1, _) = p.node { |
3157f602 XL |
965 | let var_ty = self.assign(p.span, p.id, None); |
966 | ||
967 | self.fcx.require_type_is_sized(var_ty, p.span, | |
968 | traits::VariableType(p.id)); | |
969 | ||
970 | debug!("Pattern binding {} is assigned to {} with type {:?}", | |
971 | path1.node, | |
972 | self.fcx.ty_to_string( | |
973 | self.fcx.locals.borrow().get(&p.id).unwrap().clone()), | |
974 | var_ty); | |
1a4d82fc | 975 | } |
92a42be0 | 976 | intravisit::walk_pat(self, p); |
1a4d82fc JJ |
977 | } |
978 | ||
92a42be0 | 979 | // Don't descend into the bodies of nested closures |
a7813a04 | 980 | fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl, |
32a655c1 | 981 | _: hir::BodyId, _: Span, _: ast::NodeId) { } |
1a4d82fc JJ |
982 | } |
983 | ||
8bb4bdeb | 984 | /// Helper used for fns and closures. Does the grungy work of checking a function |
1a4d82fc JJ |
985 | /// body and returns the function context used for that purpose, since in the case of a fn item |
986 | /// there is still a bit more to do. | |
987 | /// | |
988 | /// * ... | |
989 | /// * inherited: other fields inherited from the enclosing fn (if any) | |
a7813a04 | 990 | fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, |
7cac9316 | 991 | param_env: ty::ParamEnv<'tcx>, |
8bb4bdeb | 992 | fn_sig: ty::FnSig<'tcx>, |
a7813a04 XL |
993 | decl: &'gcx hir::FnDecl, |
994 | fn_id: ast::NodeId, | |
ea8adc8c XL |
995 | body: &'gcx hir::Body, |
996 | can_be_generator: bool) | |
997 | -> (FnCtxt<'a, 'gcx, 'tcx>, Option<ty::GeneratorInterior<'tcx>>) | |
1a4d82fc | 998 | { |
5bcae85e | 999 | let mut fn_sig = fn_sig.clone(); |
1a4d82fc | 1000 | |
7cac9316 | 1001 | debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env); |
1a4d82fc JJ |
1002 | |
1003 | // Create the function context. This is either derived from scratch or, | |
1004 | // in the case of function expressions, based on the outer context. | |
7cac9316 | 1005 | let mut fcx = FnCtxt::new(inherited, param_env, body.value.id); |
8bb4bdeb | 1006 | *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); |
1a4d82fc | 1007 | |
cc61c64b | 1008 | let ret_ty = fn_sig.output(); |
041b39d2 | 1009 | fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); |
cc61c64b XL |
1010 | let ret_ty = fcx.instantiate_anon_types(&ret_ty); |
1011 | fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); | |
8bb4bdeb XL |
1012 | fn_sig = fcx.tcx.mk_fn_sig( |
1013 | fn_sig.inputs().iter().cloned(), | |
cc61c64b | 1014 | ret_ty, |
8bb4bdeb XL |
1015 | fn_sig.variadic, |
1016 | fn_sig.unsafety, | |
1017 | fn_sig.abi | |
1018 | ); | |
1a4d82fc | 1019 | |
ea8adc8c XL |
1020 | let span = body.value.span; |
1021 | ||
1022 | if body.is_generator && can_be_generator { | |
1023 | fcx.yield_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span))); | |
1024 | } | |
1025 | ||
32a655c1 | 1026 | GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); |
1a4d82fc | 1027 | |
32a655c1 SL |
1028 | // Add formal parameters. |
1029 | for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { | |
32a655c1 | 1030 | // Check the pattern. |
ea8adc8c XL |
1031 | fcx.check_pat_walk(&arg.pat, arg_ty, |
1032 | ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true); | |
041b39d2 XL |
1033 | |
1034 | // Check that argument is Sized. | |
1035 | // The check for a non-trivial pattern is a hack to avoid duplicate warnings | |
1036 | // for simple cases like `fn foo(x: Trait)`, | |
1037 | // where we would error once on the parameter as a whole, and once on the binding `x`. | |
1038 | if arg.pat.simple_name().is_none() { | |
1039 | fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); | |
1040 | } | |
1041 | ||
3b2f2976 | 1042 | fcx.write_ty(arg.hir_id, arg_ty); |
1a4d82fc JJ |
1043 | } |
1044 | ||
3b2f2976 | 1045 | let fn_hir_id = fcx.tcx.hir.node_to_hir_id(fn_id); |
ea8adc8c XL |
1046 | let gen_ty = if can_be_generator && body.is_generator { |
1047 | let gen_sig = ty::GenSig { | |
1048 | yield_ty: fcx.yield_ty.unwrap(), | |
1049 | return_ty: ret_ty, | |
1050 | }; | |
1051 | inherited.tables.borrow_mut().generator_sigs_mut().insert(fn_hir_id, Some(gen_sig)); | |
1052 | ||
1053 | let witness = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span)); | |
1054 | fcx.deferred_generator_interiors.borrow_mut().push((body.id(), witness)); | |
1055 | let interior = ty::GeneratorInterior::new(witness); | |
1056 | ||
1057 | inherited.tables.borrow_mut().generator_interiors_mut().insert(fn_hir_id, interior); | |
1058 | ||
1059 | Some(interior) | |
1060 | } else { | |
1061 | inherited.tables.borrow_mut().generator_sigs_mut().insert(fn_hir_id, None); | |
1062 | None | |
1063 | }; | |
3b2f2976 | 1064 | inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_hir_id, fn_sig); |
1a4d82fc | 1065 | |
cc61c64b XL |
1066 | fcx.check_return_expr(&body.value); |
1067 | ||
1068 | // Finalize the return check by taking the LUB of the return types | |
1069 | // we saw and assigning it to the expected return type. This isn't | |
1070 | // really expected to fail, since the coercions would have failed | |
1071 | // earlier when trying to find a LUB. | |
1072 | // | |
1073 | // However, the behavior around `!` is sort of complex. In the | |
1074 | // event that the `actual_return_ty` comes back as `!`, that | |
1075 | // indicates that the fn either does not return or "returns" only | |
1076 | // values of type `!`. In this case, if there is an expected | |
1077 | // return type that is *not* `!`, that should be ok. But if the | |
1078 | // return type is being inferred, we want to "fallback" to `!`: | |
1079 | // | |
1080 | // let x = move || panic!(); | |
1081 | // | |
1082 | // To allow for that, I am creating a type variable with diverging | |
1083 | // fallback. This was deemed ever so slightly better than unifying | |
1084 | // the return value with `!` because it allows for the caller to | |
1085 | // make more assumptions about the return type (e.g., they could do | |
1086 | // | |
1087 | // let y: Option<u32> = Some(x()); | |
1088 | // | |
1089 | // which would then cause this return type to become `u32`, not | |
1090 | // `!`). | |
1091 | let coercion = fcx.ret_coercion.take().unwrap().into_inner(); | |
1092 | let mut actual_return_ty = coercion.complete(&fcx); | |
1093 | if actual_return_ty.is_never() { | |
1094 | actual_return_ty = fcx.next_diverging_ty_var( | |
ea8adc8c | 1095 | TypeVariableOrigin::DivergingFn(span)); |
cc61c64b | 1096 | } |
ea8adc8c | 1097 | fcx.demand_suptype(span, ret_ty, actual_return_ty); |
1a4d82fc | 1098 | |
ea8adc8c | 1099 | (fcx, gen_ty) |
1a4d82fc JJ |
1100 | } |
1101 | ||
8bb4bdeb XL |
1102 | fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1103 | id: ast::NodeId, | |
1104 | span: Span) { | |
1105 | let def_id = tcx.hir.local_def_id(id); | |
7cac9316 | 1106 | let def = tcx.adt_def(def_id); |
8bb4bdeb XL |
1107 | def.destructor(tcx); // force the destructor to be evaluated |
1108 | check_representable(tcx, span, def_id); | |
1a4d82fc | 1109 | |
cc61c64b | 1110 | if def.repr.simd() { |
8bb4bdeb | 1111 | check_simd(tcx, span, def_id); |
1a4d82fc | 1112 | } |
cc61c64b | 1113 | |
3b2f2976 | 1114 | check_packed(tcx, span, def_id); |
1a4d82fc JJ |
1115 | } |
1116 | ||
8bb4bdeb XL |
1117 | fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1118 | id: ast::NodeId, | |
1119 | span: Span) { | |
1120 | let def_id = tcx.hir.local_def_id(id); | |
7cac9316 | 1121 | let def = tcx.adt_def(def_id); |
8bb4bdeb XL |
1122 | def.destructor(tcx); // force the destructor to be evaluated |
1123 | check_representable(tcx, span, def_id); | |
3b2f2976 XL |
1124 | |
1125 | check_packed(tcx, span, def_id); | |
9e0c209e SL |
1126 | } |
1127 | ||
8bb4bdeb | 1128 | pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) { |
b039eaaf | 1129 | debug!("check_item_type(it.id={}, it.name={})", |
1a4d82fc | 1130 | it.id, |
8bb4bdeb | 1131 | tcx.item_path_str(tcx.hir.local_def_id(it.id))); |
1a4d82fc | 1132 | let _indenter = indenter(); |
1a4d82fc | 1133 | match it.node { |
9346a6ac | 1134 | // Consts can play a role in type-checking, so they are included here. |
8bb4bdeb XL |
1135 | hir::ItemStatic(..) | |
1136 | hir::ItemConst(..) => { | |
7cac9316 | 1137 | tcx.typeck_tables_of(tcx.hir.local_def_id(it.id)); |
8bb4bdeb | 1138 | } |
e9174d1e | 1139 | hir::ItemEnum(ref enum_definition, _) => { |
8bb4bdeb XL |
1140 | check_enum(tcx, |
1141 | it.span, | |
1142 | &enum_definition.variants, | |
1143 | it.id); | |
1a4d82fc | 1144 | } |
e9174d1e | 1145 | hir::ItemFn(..) => {} // entirely within check_item_body |
476ff2be | 1146 | hir::ItemImpl(.., ref impl_item_refs) => { |
b039eaaf | 1147 | debug!("ItemImpl {} with id {}", it.name, it.id); |
8bb4bdeb XL |
1148 | let impl_def_id = tcx.hir.local_def_id(it.id); |
1149 | if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { | |
1150 | check_impl_items_against_trait(tcx, | |
c30ab7b3 SL |
1151 | it.span, |
1152 | impl_def_id, | |
476ff2be SL |
1153 | impl_trait_ref, |
1154 | impl_item_refs); | |
c30ab7b3 | 1155 | let trait_def_id = impl_trait_ref.def_id; |
8bb4bdeb | 1156 | check_on_unimplemented(tcx, trait_def_id, it); |
1a4d82fc | 1157 | } |
1a4d82fc | 1158 | } |
a7813a04 | 1159 | hir::ItemTrait(..) => { |
8bb4bdeb XL |
1160 | let def_id = tcx.hir.local_def_id(it.id); |
1161 | check_on_unimplemented(tcx, def_id, it); | |
1a4d82fc | 1162 | } |
e9174d1e | 1163 | hir::ItemStruct(..) => { |
8bb4bdeb | 1164 | check_struct(tcx, it.id, it.span); |
1a4d82fc | 1165 | } |
9e0c209e | 1166 | hir::ItemUnion(..) => { |
8bb4bdeb | 1167 | check_union(tcx, it.id, it.span); |
9e0c209e | 1168 | } |
92a42be0 | 1169 | hir::ItemTy(_, ref generics) => { |
8bb4bdeb | 1170 | let def_id = tcx.hir.local_def_id(it.id); |
7cac9316 | 1171 | let pty_ty = tcx.type_of(def_id); |
8bb4bdeb | 1172 | check_bounds_are_used(tcx, generics, pty_ty); |
1a4d82fc | 1173 | } |
e9174d1e | 1174 | hir::ItemForeignMod(ref m) => { |
8bb4bdeb | 1175 | check_abi(tcx, it.span, m.abi); |
c30ab7b3 | 1176 | |
7453a54e | 1177 | if m.abi == Abi::RustIntrinsic { |
85aaf69f | 1178 | for item in &m.items { |
8bb4bdeb | 1179 | intrinsic::check_intrinsic_type(tcx, item); |
e9174d1e | 1180 | } |
7453a54e | 1181 | } else if m.abi == Abi::PlatformIntrinsic { |
e9174d1e | 1182 | for item in &m.items { |
8bb4bdeb | 1183 | intrinsic::check_platform_intrinsic_type(tcx, item); |
1a4d82fc JJ |
1184 | } |
1185 | } else { | |
85aaf69f | 1186 | for item in &m.items { |
7cac9316 | 1187 | let generics = tcx.generics_of(tcx.hir.local_def_id(item.id)); |
476ff2be | 1188 | if !generics.types.is_empty() { |
8bb4bdeb | 1189 | let mut err = struct_span_err!(tcx.sess, item.span, E0044, |
1a4d82fc | 1190 | "foreign items may not have type parameters"); |
9cc50fc6 | 1191 | span_help!(&mut err, item.span, |
e9174d1e SL |
1192 | "consider using specialization instead of \ |
1193 | type parameters"); | |
9cc50fc6 | 1194 | err.emit(); |
1a4d82fc JJ |
1195 | } |
1196 | ||
32a655c1 | 1197 | if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node { |
8bb4bdeb | 1198 | require_c_abi_if_variadic(tcx, fn_decl, m.abi, item.span); |
1a4d82fc JJ |
1199 | } |
1200 | } | |
1201 | } | |
1202 | } | |
1203 | _ => {/* nothing to do */ } | |
1204 | } | |
1205 | } | |
1206 | ||
8bb4bdeb | 1207 | fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
ea8adc8c | 1208 | trait_def_id: DefId, |
9e0c209e | 1209 | item: &hir::Item) { |
ea8adc8c XL |
1210 | let item_def_id = tcx.hir.local_def_id(item.id); |
1211 | // an error would be reported if this fails. | |
1212 | let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id); | |
85aaf69f SL |
1213 | } |
1214 | ||
a7813a04 XL |
1215 | fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1216 | impl_item: &hir::ImplItem, | |
1217 | parent_impl: DefId) | |
54a0048b SL |
1218 | { |
1219 | let mut err = struct_span_err!( | |
1220 | tcx.sess, impl_item.span, E0520, | |
9e0c209e SL |
1221 | "`{}` specializes an item from a parent `impl`, but \ |
1222 | that item is not marked `default`", | |
54a0048b | 1223 | impl_item.name); |
7cac9316 | 1224 | err.span_label(impl_item.span, format!("cannot specialize default item `{}`", |
9e0c209e | 1225 | impl_item.name)); |
54a0048b SL |
1226 | |
1227 | match tcx.span_of_impl(parent_impl) { | |
1228 | Ok(span) => { | |
7cac9316 | 1229 | err.span_label(span, "parent `impl` is here"); |
9e0c209e SL |
1230 | err.note(&format!("to specialize, `{}` in the parent `impl` must be marked `default`", |
1231 | impl_item.name)); | |
54a0048b SL |
1232 | } |
1233 | Err(cname) => { | |
1234 | err.note(&format!("parent implementation is in crate `{}`", cname)); | |
1235 | } | |
1236 | } | |
1237 | ||
1238 | err.emit(); | |
1239 | } | |
1240 | ||
a7813a04 | 1241 | fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
476ff2be | 1242 | trait_def: &ty::TraitDef, |
ea8adc8c | 1243 | trait_item: &ty::AssociatedItem, |
a7813a04 XL |
1244 | impl_id: DefId, |
1245 | impl_item: &hir::ImplItem) | |
54a0048b | 1246 | { |
7cac9316 | 1247 | let ancestors = trait_def.ancestors(tcx, impl_id); |
54a0048b | 1248 | |
476ff2be SL |
1249 | let kind = match impl_item.node { |
1250 | hir::ImplItemKind::Const(..) => ty::AssociatedKind::Const, | |
1251 | hir::ImplItemKind::Method(..) => ty::AssociatedKind::Method, | |
1252 | hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type | |
54a0048b | 1253 | }; |
ea8adc8c XL |
1254 | |
1255 | let parent = ancestors.defs(tcx, trait_item.name, kind, trait_def.def_id).skip(1).next() | |
476ff2be | 1256 | .map(|node_item| node_item.map(|parent| parent.defaultness)); |
54a0048b SL |
1257 | |
1258 | if let Some(parent) = parent { | |
7cac9316 | 1259 | if tcx.impl_item_is_final(&parent) { |
54a0048b SL |
1260 | report_forbidden_specialization(tcx, impl_item, parent.node.def_id()); |
1261 | } | |
1262 | } | |
1263 | ||
1264 | } | |
1265 | ||
8bb4bdeb | 1266 | fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1a4d82fc | 1267 | impl_span: Span, |
54a0048b | 1268 | impl_id: DefId, |
476ff2be SL |
1269 | impl_trait_ref: ty::TraitRef<'tcx>, |
1270 | impl_item_refs: &[hir::ImplItemRef]) { | |
54a0048b SL |
1271 | // If the trait reference itself is erroneous (so the compilation is going |
1272 | // to fail), skip checking the items here -- the `impl_item` table in `tcx` | |
1273 | // isn't populated for such impls. | |
1274 | if impl_trait_ref.references_error() { return; } | |
1275 | ||
1276 | // Locate trait definition and items | |
7cac9316 | 1277 | let trait_def = tcx.trait_def(impl_trait_ref.def_id); |
c1a9b12d | 1278 | let mut overridden_associated_type = None; |
1a4d82fc | 1279 | |
8bb4bdeb | 1280 | let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir.impl_item(iiref.id)); |
476ff2be | 1281 | |
1a4d82fc JJ |
1282 | // Check existing impl methods to see if they are both present in trait |
1283 | // and compatible with trait signature | |
476ff2be | 1284 | for impl_item in impl_items() { |
32a655c1 | 1285 | let ty_impl_item = tcx.associated_item(tcx.hir.local_def_id(impl_item.id)); |
476ff2be | 1286 | let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id) |
abe05a73 XL |
1287 | .find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) && |
1288 | tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id)) | |
1289 | .or_else(|| { | |
1290 | // Not compatible, but needed for the error message | |
1291 | tcx.associated_items(impl_trait_ref.def_id) | |
1292 | .find(|ac| tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id)) | |
1293 | }); | |
d9579d0f | 1294 | |
54a0048b | 1295 | // Check that impl definition matches trait definition |
9cc50fc6 SL |
1296 | if let Some(ty_trait_item) = ty_trait_item { |
1297 | match impl_item.node { | |
1298 | hir::ImplItemKind::Const(..) => { | |
9cc50fc6 | 1299 | // Find associated const definition. |
476ff2be | 1300 | if ty_trait_item.kind == ty::AssociatedKind::Const { |
8bb4bdeb | 1301 | compare_const_impl(tcx, |
476ff2be | 1302 | &ty_impl_item, |
9cc50fc6 | 1303 | impl_item.span, |
476ff2be SL |
1304 | &ty_trait_item, |
1305 | impl_trait_ref); | |
9cc50fc6 | 1306 | } else { |
5bcae85e | 1307 | let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323, |
9cc50fc6 | 1308 | "item `{}` is an associated const, \ |
476ff2be SL |
1309 | which doesn't match its trait `{}`", |
1310 | ty_impl_item.name, | |
5bcae85e | 1311 | impl_trait_ref); |
7cac9316 | 1312 | err.span_label(impl_item.span, "does not match trait"); |
5bcae85e SL |
1313 | // We can only get the spans from local trait definition |
1314 | // Same for E0324 and E0325 | |
32a655c1 | 1315 | if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { |
7cac9316 | 1316 | err.span_label(trait_span, "item in trait"); |
5bcae85e SL |
1317 | } |
1318 | err.emit() | |
9cc50fc6 | 1319 | } |
d9579d0f | 1320 | } |
7cac9316 | 1321 | hir::ImplItemKind::Method(..) => { |
32a655c1 | 1322 | let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id); |
476ff2be | 1323 | if ty_trait_item.kind == ty::AssociatedKind::Method { |
8bb4bdeb | 1324 | compare_impl_method(tcx, |
476ff2be | 1325 | &ty_impl_item, |
9cc50fc6 | 1326 | impl_item.span, |
476ff2be SL |
1327 | &ty_trait_item, |
1328 | impl_trait_ref, | |
abe05a73 | 1329 | trait_span); |
9cc50fc6 | 1330 | } else { |
5bcae85e | 1331 | let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324, |
9cc50fc6 | 1332 | "item `{}` is an associated method, \ |
476ff2be SL |
1333 | which doesn't match its trait `{}`", |
1334 | ty_impl_item.name, | |
5bcae85e | 1335 | impl_trait_ref); |
7cac9316 | 1336 | err.span_label(impl_item.span, "does not match trait"); |
32a655c1 | 1337 | if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { |
7cac9316 | 1338 | err.span_label(trait_span, "item in trait"); |
5bcae85e SL |
1339 | } |
1340 | err.emit() | |
9cc50fc6 | 1341 | } |
1a4d82fc | 1342 | } |
9cc50fc6 | 1343 | hir::ImplItemKind::Type(_) => { |
476ff2be SL |
1344 | if ty_trait_item.kind == ty::AssociatedKind::Type { |
1345 | if ty_trait_item.defaultness.has_value() { | |
9cc50fc6 SL |
1346 | overridden_associated_type = Some(impl_item); |
1347 | } | |
1348 | } else { | |
5bcae85e | 1349 | let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325, |
9cc50fc6 | 1350 | "item `{}` is an associated type, \ |
476ff2be SL |
1351 | which doesn't match its trait `{}`", |
1352 | ty_impl_item.name, | |
5bcae85e | 1353 | impl_trait_ref); |
7cac9316 | 1354 | err.span_label(impl_item.span, "does not match trait"); |
32a655c1 | 1355 | if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { |
7cac9316 | 1356 | err.span_label(trait_span, "item in trait"); |
5bcae85e SL |
1357 | } |
1358 | err.emit() | |
1a4d82fc JJ |
1359 | } |
1360 | } | |
1361 | } | |
54a0048b | 1362 | |
ea8adc8c XL |
1363 | check_specialization_validity(tcx, trait_def, &ty_trait_item, impl_id, impl_item); |
1364 | } | |
1a4d82fc JJ |
1365 | } |
1366 | ||
1367 | // Check for missing items from trait | |
62682a34 | 1368 | let mut missing_items = Vec::new(); |
c1a9b12d SL |
1369 | let mut invalidated_items = Vec::new(); |
1370 | let associated_type_overridden = overridden_associated_type.is_some(); | |
476ff2be | 1371 | for trait_item in tcx.associated_items(impl_trait_ref.def_id) { |
7cac9316 | 1372 | let is_implemented = trait_def.ancestors(tcx, impl_id) |
ea8adc8c | 1373 | .defs(tcx, trait_item.name, trait_item.kind, impl_trait_ref.def_id) |
476ff2be SL |
1374 | .next() |
1375 | .map(|node_item| !node_item.node.is_from_trait()) | |
1376 | .unwrap_or(false); | |
54a0048b SL |
1377 | |
1378 | if !is_implemented { | |
476ff2be SL |
1379 | if !trait_item.defaultness.has_value() { |
1380 | missing_items.push(trait_item); | |
54a0048b | 1381 | } else if associated_type_overridden { |
476ff2be | 1382 | invalidated_items.push(trait_item.name); |
1a4d82fc JJ |
1383 | } |
1384 | } | |
1385 | } | |
1386 | ||
62682a34 | 1387 | if !missing_items.is_empty() { |
476ff2be | 1388 | let mut err = struct_span_err!(tcx.sess, impl_span, E0046, |
c1a9b12d SL |
1389 | "not all trait items implemented, missing: `{}`", |
1390 | missing_items.iter() | |
476ff2be SL |
1391 | .map(|trait_item| trait_item.name.to_string()) |
1392 | .collect::<Vec<_>>().join("`, `")); | |
7cac9316 | 1393 | err.span_label(impl_span, format!("missing `{}` in implementation", |
5bcae85e | 1394 | missing_items.iter() |
476ff2be SL |
1395 | .map(|trait_item| trait_item.name.to_string()) |
1396 | .collect::<Vec<_>>().join("`, `"))); | |
1397 | for trait_item in missing_items { | |
32a655c1 | 1398 | if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) { |
7cac9316 | 1399 | err.span_label(span, format!("`{}` from trait", trait_item.name)); |
476ff2be | 1400 | } else { |
7cac9316 XL |
1401 | err.note_trait_signature(trait_item.name.to_string(), |
1402 | trait_item.signature(&tcx)); | |
476ff2be SL |
1403 | } |
1404 | } | |
1405 | err.emit(); | |
c1a9b12d SL |
1406 | } |
1407 | ||
1408 | if !invalidated_items.is_empty() { | |
1409 | let invalidator = overridden_associated_type.unwrap(); | |
1410 | span_err!(tcx.sess, invalidator.span, E0399, | |
1411 | "the following trait items need to be reimplemented \ | |
1412 | as `{}` was overridden: `{}`", | |
b039eaaf | 1413 | invalidator.name, |
c1a9b12d SL |
1414 | invalidated_items.iter() |
1415 | .map(|name| name.to_string()) | |
1416 | .collect::<Vec<_>>().join("`, `")) | |
1a4d82fc JJ |
1417 | } |
1418 | } | |
1419 | ||
a7813a04 XL |
1420 | /// Checks whether a type can be represented in memory. In particular, it |
1421 | /// identifies types that contain themselves without indirection through a | |
1422 | /// pointer, which would mean their size is unbounded. | |
9e0c209e SL |
1423 | fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1424 | sp: Span, | |
476ff2be | 1425 | item_def_id: DefId) |
9e0c209e | 1426 | -> bool { |
7cac9316 | 1427 | let rty = tcx.type_of(item_def_id); |
a7813a04 XL |
1428 | |
1429 | // Check that it is possible to represent this type. This call identifies | |
1430 | // (1) types that contain themselves and (2) types that contain a different | |
1431 | // recursive type. It is only necessary to throw an error on those that | |
1432 | // contain themselves. For case 2, there must be an inner type that will be | |
1433 | // caught by case 1. | |
1434 | match rty.is_representable(tcx, sp) { | |
7cac9316 XL |
1435 | Representability::SelfRecursive(spans) => { |
1436 | let mut err = tcx.recursive_type_with_infinite_size_error(item_def_id); | |
1437 | for span in spans { | |
1438 | err.span_label(span, "recursive without indirection"); | |
1439 | } | |
1440 | err.emit(); | |
a7813a04 XL |
1441 | return false |
1442 | } | |
1443 | Representability::Representable | Representability::ContainsRecursive => (), | |
1444 | } | |
1445 | return true | |
1446 | } | |
1447 | ||
476ff2be | 1448 | pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) { |
7cac9316 | 1449 | let t = tcx.type_of(def_id); |
a7813a04 | 1450 | match t.sty { |
9e0c209e | 1451 | ty::TyAdt(def, substs) if def.is_struct() => { |
a7813a04 XL |
1452 | let fields = &def.struct_variant().fields; |
1453 | if fields.is_empty() { | |
1454 | span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty"); | |
1455 | return; | |
1456 | } | |
1457 | let e = fields[0].ty(tcx, substs); | |
1458 | if !fields.iter().all(|f| f.ty(tcx, substs) == e) { | |
9e0c209e | 1459 | struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") |
7cac9316 | 1460 | .span_label(sp, "SIMD elements must have the same type") |
9e0c209e | 1461 | .emit(); |
a7813a04 XL |
1462 | return; |
1463 | } | |
1464 | match e.sty { | |
1465 | ty::TyParam(_) => { /* struct<T>(T, T, T, T) is ok */ } | |
1466 | _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ } | |
1467 | _ => { | |
1468 | span_err!(tcx.sess, sp, E0077, | |
1469 | "SIMD vector element type should be machine type"); | |
1470 | return; | |
d9579d0f | 1471 | } |
1a4d82fc JJ |
1472 | } |
1473 | } | |
a7813a04 XL |
1474 | _ => () |
1475 | } | |
1476 | } | |
1477 | ||
cc61c64b | 1478 | fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) { |
3b2f2976 XL |
1479 | if tcx.adt_def(def_id).repr.packed() { |
1480 | if tcx.adt_def(def_id).repr.align > 0 { | |
1481 | struct_span_err!(tcx.sess, sp, E0587, | |
1482 | "type has conflicting packed and align representation hints").emit(); | |
1483 | } | |
1484 | else if check_packed_inner(tcx, def_id, &mut Vec::new()) { | |
1485 | struct_span_err!(tcx.sess, sp, E0588, | |
1486 | "packed type cannot transitively contain a `[repr(align)]` type").emit(); | |
1487 | } | |
cc61c64b XL |
1488 | } |
1489 | } | |
1490 | ||
1491 | fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
1492 | def_id: DefId, | |
1493 | stack: &mut Vec<DefId>) -> bool { | |
7cac9316 | 1494 | let t = tcx.type_of(def_id); |
cc61c64b XL |
1495 | if stack.contains(&def_id) { |
1496 | debug!("check_packed_inner: {:?} is recursive", t); | |
1497 | return false; | |
1498 | } | |
1499 | match t.sty { | |
3b2f2976 | 1500 | ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => { |
7cac9316 | 1501 | if tcx.adt_def(def.did).repr.align > 0 { |
cc61c64b XL |
1502 | return true; |
1503 | } | |
1504 | // push struct def_id before checking fields | |
1505 | stack.push(def_id); | |
1506 | for field in &def.struct_variant().fields { | |
1507 | let f = field.ty(tcx, substs); | |
1508 | match f.sty { | |
1509 | ty::TyAdt(def, _) => { | |
1510 | if check_packed_inner(tcx, def.did, stack) { | |
1511 | return true; | |
1512 | } | |
1513 | } | |
1514 | _ => () | |
1515 | } | |
1516 | } | |
1517 | // only need to pop if not early out | |
1518 | stack.pop(); | |
1519 | } | |
1520 | _ => () | |
1521 | } | |
1522 | false | |
1523 | } | |
1524 | ||
a7813a04 | 1525 | #[allow(trivial_numeric_casts)] |
8bb4bdeb XL |
1526 | pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
1527 | sp: Span, | |
1528 | vs: &'tcx [hir::Variant], | |
1529 | id: ast::NodeId) { | |
1530 | let def_id = tcx.hir.local_def_id(id); | |
7cac9316 | 1531 | let def = tcx.adt_def(def_id); |
8bb4bdeb XL |
1532 | def.destructor(tcx); // force the destructor to be evaluated |
1533 | ||
abe05a73 XL |
1534 | if vs.is_empty() { |
1535 | let attributes = tcx.get_attrs(def_id); | |
1536 | if let Some(attr) = attr::find_by_name(&attributes, "repr") { | |
1537 | struct_span_err!( | |
1538 | tcx.sess, attr.span, E0084, | |
1539 | "unsupported representation for zero-variant enum") | |
1540 | .span_label(sp, "zero-variant enum") | |
1541 | .emit(); | |
1542 | } | |
a7813a04 XL |
1543 | } |
1544 | ||
8bb4bdeb XL |
1545 | let repr_type_ty = def.repr.discr_type().to_ty(tcx); |
1546 | if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { | |
ea8adc8c | 1547 | if !tcx.sess.features.borrow().repr128 { |
8bb4bdeb | 1548 | emit_feature_err(&tcx.sess.parse_sess, |
ea8adc8c XL |
1549 | "repr128", |
1550 | sp, | |
1551 | GateIssue::Language, | |
1552 | "repr with 128-bit type is unstable"); | |
32a655c1 SL |
1553 | } |
1554 | } | |
1555 | ||
5bcae85e | 1556 | for v in vs { |
32a655c1 | 1557 | if let Some(e) = v.node.disr_expr { |
7cac9316 | 1558 | tcx.typeck_tables_of(tcx.hir.local_def_id(e.node_id)); |
1a4d82fc | 1559 | } |
5bcae85e | 1560 | } |
a7813a04 | 1561 | |
8bb4bdeb XL |
1562 | let mut disr_vals: Vec<ConstInt> = Vec::new(); |
1563 | for (discr, v) in def.discriminants(tcx).zip(vs) { | |
5bcae85e | 1564 | // Check for duplicate discriminant values |
8bb4bdeb XL |
1565 | if let Some(i) = disr_vals.iter().position(|&x| x == discr) { |
1566 | let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap(); | |
1567 | let variant_i = tcx.hir.expect_variant(variant_i_node_id); | |
5bcae85e | 1568 | let i_span = match variant_i.node.disr_expr { |
8bb4bdeb XL |
1569 | Some(expr) => tcx.hir.span(expr.node_id), |
1570 | None => tcx.hir.span(variant_i_node_id) | |
5bcae85e SL |
1571 | }; |
1572 | let span = match v.node.disr_expr { | |
8bb4bdeb | 1573 | Some(expr) => tcx.hir.span(expr.node_id), |
5bcae85e SL |
1574 | None => v.span |
1575 | }; | |
8bb4bdeb | 1576 | struct_span_err!(tcx.sess, span, E0081, |
5bcae85e | 1577 | "discriminant value `{}` already exists", disr_vals[i]) |
7cac9316 XL |
1578 | .span_label(i_span, format!("first use of `{}`", disr_vals[i])) |
1579 | .span_label(span , format!("enum already has `{}`", disr_vals[i])) | |
5bcae85e | 1580 | .emit(); |
1a4d82fc | 1581 | } |
8bb4bdeb | 1582 | disr_vals.push(discr); |
5bcae85e | 1583 | } |
a7813a04 | 1584 | |
8bb4bdeb | 1585 | check_representable(tcx, sp, def_id); |
1a4d82fc JJ |
1586 | } |
1587 | ||
a7813a04 XL |
1588 | impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { |
1589 | fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } | |
1a4d82fc | 1590 | |
8bb4bdeb XL |
1591 | fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) |
1592 | -> ty::GenericPredicates<'tcx> | |
c34b1796 | 1593 | { |
8bb4bdeb XL |
1594 | let tcx = self.tcx; |
1595 | let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
1596 | let item_id = tcx.hir.ty_param_owner(node_id); | |
1597 | let item_def_id = tcx.hir.local_def_id(item_id); | |
7cac9316 | 1598 | let generics = tcx.generics_of(item_def_id); |
8bb4bdeb XL |
1599 | let index = generics.type_param_to_index[&def_id.index]; |
1600 | ty::GenericPredicates { | |
1601 | parent: None, | |
7cac9316 | 1602 | predicates: self.param_env.caller_bounds.iter().filter(|predicate| { |
8bb4bdeb XL |
1603 | match **predicate { |
1604 | ty::Predicate::Trait(ref data) => { | |
1605 | data.0.self_ty().is_param(index) | |
1606 | } | |
1607 | _ => false | |
1608 | } | |
1609 | }).cloned().collect() | |
1610 | } | |
c34b1796 AL |
1611 | } |
1612 | ||
32a655c1 | 1613 | fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>) |
7cac9316 | 1614 | -> Option<ty::Region<'tcx>> { |
32a655c1 | 1615 | let v = match def { |
ea8adc8c | 1616 | Some(def) => infer::EarlyBoundRegion(span, def.name), |
32a655c1 SL |
1617 | None => infer::MiscVariable(span) |
1618 | }; | |
1619 | Some(self.next_region_var(v)) | |
1620 | } | |
1621 | ||
476ff2be SL |
1622 | fn ty_infer(&self, span: Span) -> Ty<'tcx> { |
1623 | self.next_ty_var(TypeVariableOrigin::TypeInference(span)) | |
9e0c209e | 1624 | } |
c1a9b12d | 1625 | |
9e0c209e | 1626 | fn ty_infer_for_def(&self, |
8bb4bdeb | 1627 | ty_param_def: &ty::TypeParameterDef, |
c30ab7b3 | 1628 | substs: &[Kind<'tcx>], |
9e0c209e SL |
1629 | span: Span) -> Ty<'tcx> { |
1630 | self.type_var_for_def(span, ty_param_def, substs) | |
1a4d82fc JJ |
1631 | } |
1632 | ||
1633 | fn projected_ty_from_poly_trait_ref(&self, | |
1634 | span: Span, | |
041b39d2 XL |
1635 | item_def_id: DefId, |
1636 | poly_trait_ref: ty::PolyTraitRef<'tcx>) | |
1a4d82fc JJ |
1637 | -> Ty<'tcx> |
1638 | { | |
1639 | let (trait_ref, _) = | |
a7813a04 | 1640 | self.replace_late_bound_regions_with_fresh_var( |
1a4d82fc | 1641 | span, |
3b2f2976 | 1642 | infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id), |
1a4d82fc JJ |
1643 | &poly_trait_ref); |
1644 | ||
041b39d2 | 1645 | self.tcx().mk_projection(item_def_id, trait_ref.substs) |
1a4d82fc JJ |
1646 | } |
1647 | ||
8bb4bdeb XL |
1648 | fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { |
1649 | if ty.has_escaping_regions() { | |
1650 | ty // FIXME: normalization and escaping regions | |
1651 | } else { | |
1652 | self.normalize_associated_types_in(span, &ty) | |
1653 | } | |
1a4d82fc | 1654 | } |
a7813a04 XL |
1655 | |
1656 | fn set_tainted_by_errors(&self) { | |
1657 | self.infcx.set_tainted_by_errors() | |
1658 | } | |
ea8adc8c XL |
1659 | |
1660 | fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) { | |
1661 | self.write_ty(hir_id, ty) | |
1662 | } | |
a7813a04 XL |
1663 | } |
1664 | ||
a7813a04 XL |
1665 | /// Controls whether the arguments are tupled. This is used for the call |
1666 | /// operator. | |
1667 | /// | |
1668 | /// Tupling means that all call-side arguments are packed into a tuple and | |
1669 | /// passed as a single parameter. For example, if tupling is enabled, this | |
1670 | /// function: | |
1671 | /// | |
1672 | /// fn f(x: (isize, isize)) | |
1673 | /// | |
1674 | /// Can be called as: | |
1675 | /// | |
1676 | /// f(1, 2); | |
1677 | /// | |
1678 | /// Instead of: | |
1679 | /// | |
1680 | /// f((1, 2)); | |
1681 | #[derive(Clone, Eq, PartialEq)] | |
1682 | enum TupleArgumentsFlag { | |
1683 | DontTupleArguments, | |
1684 | TupleArguments, | |
1685 | } | |
1a4d82fc | 1686 | |
a7813a04 XL |
1687 | impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |
1688 | pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>, | |
7cac9316 | 1689 | param_env: ty::ParamEnv<'tcx>, |
a7813a04 XL |
1690 | body_id: ast::NodeId) |
1691 | -> FnCtxt<'a, 'gcx, 'tcx> { | |
1692 | FnCtxt { | |
3b2f2976 | 1693 | body_id, |
7cac9316 | 1694 | param_env, |
a7813a04 | 1695 | err_count_on_creation: inh.tcx.sess.err_count(), |
cc61c64b | 1696 | ret_coercion: None, |
ea8adc8c | 1697 | yield_ty: None, |
9e0c209e SL |
1698 | ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, |
1699 | ast::CRATE_NODE_ID)), | |
476ff2be SL |
1700 | diverges: Cell::new(Diverges::Maybe), |
1701 | has_errors: Cell::new(false), | |
cc61c64b | 1702 | enclosing_breakables: RefCell::new(EnclosingBreakables { |
476ff2be SL |
1703 | stack: Vec::new(), |
1704 | by_id: NodeMap(), | |
1705 | }), | |
3b2f2976 | 1706 | inh, |
a7813a04 | 1707 | } |
1a4d82fc JJ |
1708 | } |
1709 | ||
1a4d82fc | 1710 | pub fn sess(&self) -> &Session { |
a7813a04 | 1711 | &self.tcx.sess |
1a4d82fc JJ |
1712 | } |
1713 | ||
c34b1796 | 1714 | pub fn err_count_since_creation(&self) -> usize { |
a7813a04 | 1715 | self.tcx.sess.err_count() - self.err_count_on_creation |
1a4d82fc JJ |
1716 | } |
1717 | ||
476ff2be SL |
1718 | /// Produce warning on the given node, if the current point in the |
1719 | /// function is unreachable, and there hasn't been another warning. | |
1720 | fn warn_if_unreachable(&self, id: ast::NodeId, span: Span, kind: &str) { | |
1721 | if self.diverges.get() == Diverges::Always { | |
1722 | self.diverges.set(Diverges::WarnedAlways); | |
1723 | ||
cc61c64b XL |
1724 | debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); |
1725 | ||
3b2f2976 | 1726 | self.tcx().lint_node( |
8bb4bdeb XL |
1727 | lint::builtin::UNREACHABLE_CODE, |
1728 | id, span, | |
3b2f2976 | 1729 | &format!("unreachable {}", kind)); |
476ff2be SL |
1730 | } |
1731 | } | |
1732 | ||
1733 | pub fn cause(&self, | |
1734 | span: Span, | |
1735 | code: ObligationCauseCode<'tcx>) | |
1736 | -> ObligationCause<'tcx> { | |
1737 | ObligationCause::new(span, self.body_id, code) | |
1738 | } | |
1739 | ||
1740 | pub fn misc(&self, span: Span) -> ObligationCause<'tcx> { | |
1741 | self.cause(span, ObligationCauseCode::MiscObligation) | |
1742 | } | |
1743 | ||
85aaf69f | 1744 | /// Resolves type variables in `ty` if possible. Unlike the infcx |
a7813a04 XL |
1745 | /// version (resolve_type_vars_if_possible), this version will |
1746 | /// also select obligations if it seems useful, in an effort | |
1747 | /// to get more type information. | |
1748 | fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { | |
1749 | debug!("resolve_type_vars_with_obligations(ty={:?})", ty); | |
c34b1796 | 1750 | |
c1a9b12d SL |
1751 | // No TyInfer()? Nothing needs doing. |
1752 | if !ty.has_infer_types() { | |
a7813a04 | 1753 | debug!("resolve_type_vars_with_obligations: ty={:?}", ty); |
85aaf69f SL |
1754 | return ty; |
1755 | } | |
1756 | ||
1757 | // If `ty` is a type variable, see whether we already know what it is. | |
a7813a04 | 1758 | ty = self.resolve_type_vars_if_possible(&ty); |
c1a9b12d | 1759 | if !ty.has_infer_types() { |
a7813a04 | 1760 | debug!("resolve_type_vars_with_obligations: ty={:?}", ty); |
85aaf69f SL |
1761 | return ty; |
1762 | } | |
1763 | ||
7453a54e | 1764 | // If not, try resolving pending obligations as much as |
85aaf69f SL |
1765 | // possible. This can help substantially when there are |
1766 | // indirect dependencies that don't seem worth tracking | |
1767 | // precisely. | |
d9579d0f | 1768 | self.select_obligations_where_possible(); |
a7813a04 | 1769 | ty = self.resolve_type_vars_if_possible(&ty); |
c34b1796 | 1770 | |
a7813a04 | 1771 | debug!("resolve_type_vars_with_obligations: ty={:?}", ty); |
c34b1796 | 1772 | ty |
85aaf69f SL |
1773 | } |
1774 | ||
85aaf69f | 1775 | fn record_deferred_call_resolution(&self, |
e9174d1e | 1776 | closure_def_id: DefId, |
7cac9316 | 1777 | r: DeferredCallResolution<'gcx, 'tcx>) { |
a7813a04 | 1778 | let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); |
c34b1796 | 1779 | deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); |
85aaf69f SL |
1780 | } |
1781 | ||
1782 | fn remove_deferred_call_resolutions(&self, | |
e9174d1e | 1783 | closure_def_id: DefId) |
7cac9316 | 1784 | -> Vec<DeferredCallResolution<'gcx, 'tcx>> |
85aaf69f | 1785 | { |
a7813a04 | 1786 | let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); |
7cac9316 | 1787 | deferred_call_resolutions.remove(&closure_def_id).unwrap_or(vec![]) |
85aaf69f SL |
1788 | } |
1789 | ||
1a4d82fc | 1790 | pub fn tag(&self) -> String { |
c34b1796 AL |
1791 | let self_ptr: *const FnCtxt = self; |
1792 | format!("{:?}", self_ptr) | |
1a4d82fc JJ |
1793 | } |
1794 | ||
1795 | pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> { | |
a7813a04 | 1796 | match self.locals.borrow().get(&nid) { |
1a4d82fc JJ |
1797 | Some(&t) => t, |
1798 | None => { | |
32a655c1 SL |
1799 | span_bug!(span, "no type for local variable {}", |
1800 | self.tcx.hir.node_to_string(nid)); | |
1a4d82fc JJ |
1801 | } |
1802 | } | |
1803 | } | |
1804 | ||
1a4d82fc | 1805 | #[inline] |
3b2f2976 XL |
1806 | pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) { |
1807 | debug!("write_ty({:?}, {:?}) in fcx {}", | |
1808 | id, self.resolve_type_vars_if_possible(&ty), self.tag()); | |
1809 | self.tables.borrow_mut().node_types_mut().insert(id, ty); | |
476ff2be SL |
1810 | |
1811 | if ty.references_error() { | |
1812 | self.has_errors.set(true); | |
8bb4bdeb | 1813 | self.set_tainted_by_errors(); |
476ff2be | 1814 | } |
1a4d82fc JJ |
1815 | } |
1816 | ||
3b2f2976 XL |
1817 | // The NodeId and the ItemLocalId must identify the same item. We just pass |
1818 | // both of them for consistency checking. | |
1819 | pub fn write_method_call(&self, | |
1820 | hir_id: hir::HirId, | |
1821 | method: MethodCallee<'tcx>) { | |
1822 | self.tables | |
1823 | .borrow_mut() | |
1824 | .type_dependent_defs_mut() | |
1825 | .insert(hir_id, Def::Method(method.def_id)); | |
1826 | self.write_substs(hir_id, method.substs); | |
7cac9316 XL |
1827 | } |
1828 | ||
3b2f2976 | 1829 | pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) { |
7cac9316 | 1830 | if !substs.is_noop() { |
3b2f2976 | 1831 | debug!("write_substs({:?}, {:?}) in fcx {}", |
1a4d82fc | 1832 | node_id, |
62682a34 | 1833 | substs, |
1a4d82fc JJ |
1834 | self.tag()); |
1835 | ||
3b2f2976 | 1836 | self.tables.borrow_mut().node_substs_mut().insert(node_id, substs); |
1a4d82fc JJ |
1837 | } |
1838 | } | |
1839 | ||
7cac9316 XL |
1840 | pub fn apply_adjustments(&self, expr: &hir::Expr, adj: Vec<Adjustment<'tcx>>) { |
1841 | debug!("apply_adjustments(expr={:?}, adj={:?})", expr, adj); | |
1a4d82fc | 1842 | |
7cac9316 | 1843 | if adj.is_empty() { |
1a4d82fc JJ |
1844 | return; |
1845 | } | |
1846 | ||
3b2f2976 | 1847 | match self.tables.borrow_mut().adjustments_mut().entry(expr.hir_id) { |
cc61c64b XL |
1848 | Entry::Vacant(entry) => { entry.insert(adj); }, |
1849 | Entry::Occupied(mut entry) => { | |
1850 | debug!(" - composing on top of {:?}", entry.get()); | |
7cac9316 | 1851 | match (&entry.get()[..], &adj[..]) { |
cc61c64b XL |
1852 | // Applying any adjustment on top of a NeverToAny |
1853 | // is a valid NeverToAny adjustment, because it can't | |
1854 | // be reached. | |
7cac9316 XL |
1855 | (&[Adjustment { kind: Adjust::NeverToAny, .. }], _) => return, |
1856 | (&[ | |
1857 | Adjustment { kind: Adjust::Deref(_), .. }, | |
1858 | Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, | |
1859 | ], &[ | |
1860 | Adjustment { kind: Adjust::Deref(_), .. }, | |
1861 | .. // Any following adjustments are allowed. | |
1862 | ]) => { | |
cc61c64b | 1863 | // A reborrow has no effect before a dereference. |
cc61c64b XL |
1864 | } |
1865 | // FIXME: currently we never try to compose autoderefs | |
1866 | // and ReifyFnPointer/UnsafeFnPointer, but we could. | |
1867 | _ => | |
7cac9316 XL |
1868 | bug!("while adjusting {:?}, can't compose {:?} and {:?}", |
1869 | expr, entry.get(), adj) | |
cc61c64b | 1870 | }; |
7cac9316 | 1871 | *entry.get_mut() = adj; |
cc61c64b XL |
1872 | } |
1873 | } | |
1a4d82fc JJ |
1874 | } |
1875 | ||
1876 | /// Basically whenever we are converting from a type scheme into | |
1877 | /// the fn body space, we always want to normalize associated | |
1878 | /// types as well. This function combines the two. | |
1879 | fn instantiate_type_scheme<T>(&self, | |
1880 | span: Span, | |
1881 | substs: &Substs<'tcx>, | |
1882 | value: &T) | |
1883 | -> T | |
9cc50fc6 | 1884 | where T : TypeFoldable<'tcx> |
1a4d82fc | 1885 | { |
a7813a04 | 1886 | let value = value.subst(self.tcx, substs); |
1a4d82fc | 1887 | let result = self.normalize_associated_types_in(span, &value); |
62682a34 SL |
1888 | debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}", |
1889 | value, | |
1890 | substs, | |
1891 | result); | |
1a4d82fc JJ |
1892 | result |
1893 | } | |
1894 | ||
1895 | /// As `instantiate_type_scheme`, but for the bounds found in a | |
1896 | /// generic type scheme. | |
476ff2be SL |
1897 | fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: &Substs<'tcx>) |
1898 | -> ty::InstantiatedPredicates<'tcx> { | |
7cac9316 | 1899 | let bounds = self.tcx.predicates_of(def_id); |
9e0c209e | 1900 | let result = bounds.instantiate(self.tcx, substs); |
cc61c64b | 1901 | let result = self.normalize_associated_types_in(span, &result); |
9e0c209e SL |
1902 | debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", |
1903 | bounds, | |
1904 | substs, | |
1905 | result); | |
cc61c64b | 1906 | result |
1a4d82fc JJ |
1907 | } |
1908 | ||
5bcae85e SL |
1909 | /// Replace all anonymized types with fresh inference variables |
1910 | /// and record them for writeback. | |
1911 | fn instantiate_anon_types<T: TypeFoldable<'tcx>>(&self, value: &T) -> T { | |
1912 | value.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { | |
1913 | if let ty::TyAnon(def_id, substs) = ty.sty { | |
1914 | // Use the same type variable if the exact same TyAnon appears more | |
3b2f2976 | 1915 | // than once in the return type (e.g. if it's passed to a type alias). |
8bb4bdeb XL |
1916 | let id = self.tcx.hir.as_local_node_id(def_id).unwrap(); |
1917 | if let Some(ty_var) = self.anon_types.borrow().get(&id) { | |
5bcae85e SL |
1918 | return ty_var; |
1919 | } | |
476ff2be SL |
1920 | let span = self.tcx.def_span(def_id); |
1921 | let ty_var = self.next_ty_var(TypeVariableOrigin::TypeInference(span)); | |
8bb4bdeb | 1922 | self.anon_types.borrow_mut().insert(id, ty_var); |
5bcae85e | 1923 | |
7cac9316 XL |
1924 | let predicates_of = self.tcx.predicates_of(def_id); |
1925 | let bounds = predicates_of.instantiate(self.tcx, substs); | |
5bcae85e | 1926 | |
5bcae85e SL |
1927 | for predicate in bounds.predicates { |
1928 | // Change the predicate to refer to the type variable, | |
1929 | // which will be the concrete type, instead of the TyAnon. | |
1930 | // This also instantiates nested `impl Trait`. | |
1931 | let predicate = self.instantiate_anon_types(&predicate); | |
1932 | ||
1933 | // Require that the predicate holds for the concrete type. | |
1934 | let cause = traits::ObligationCause::new(span, self.body_id, | |
041b39d2 | 1935 | traits::SizedReturnType); |
7cac9316 XL |
1936 | self.register_predicate(traits::Obligation::new(cause, |
1937 | self.param_env, | |
1938 | predicate)); | |
5bcae85e SL |
1939 | } |
1940 | ||
1941 | ty_var | |
1942 | } else { | |
1943 | ty | |
1944 | } | |
1945 | }}) | |
1946 | } | |
1a4d82fc JJ |
1947 | |
1948 | fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T | |
9cc50fc6 | 1949 | where T : TypeFoldable<'tcx> |
1a4d82fc | 1950 | { |
7cac9316 | 1951 | self.inh.normalize_associated_types_in(span, self.body_id, self.param_env, value) |
cc61c64b XL |
1952 | } |
1953 | ||
1954 | fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T) | |
1955 | -> InferOk<'tcx, T> | |
1956 | where T : TypeFoldable<'tcx> | |
1957 | { | |
abe05a73 XL |
1958 | self.inh.partially_normalize_associated_types_in(span, |
1959 | self.body_id, | |
1960 | self.param_env, | |
1961 | value) | |
1a4d82fc JJ |
1962 | } |
1963 | ||
1a4d82fc JJ |
1964 | pub fn require_type_meets(&self, |
1965 | ty: Ty<'tcx>, | |
1966 | span: Span, | |
1967 | code: traits::ObligationCauseCode<'tcx>, | |
476ff2be | 1968 | def_id: DefId) |
1a4d82fc | 1969 | { |
476ff2be | 1970 | self.register_bound( |
1a4d82fc | 1971 | ty, |
476ff2be | 1972 | def_id, |
1a4d82fc JJ |
1973 | traits::ObligationCause::new(span, self.body_id, code)); |
1974 | } | |
1975 | ||
1976 | pub fn require_type_is_sized(&self, | |
1977 | ty: Ty<'tcx>, | |
1978 | span: Span, | |
1979 | code: traits::ObligationCauseCode<'tcx>) | |
1980 | { | |
476ff2be SL |
1981 | let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); |
1982 | self.require_type_meets(ty, span, code, lang_item); | |
1a4d82fc JJ |
1983 | } |
1984 | ||
476ff2be | 1985 | pub fn register_bound(&self, |
8bb4bdeb XL |
1986 | ty: Ty<'tcx>, |
1987 | def_id: DefId, | |
1988 | cause: traits::ObligationCause<'tcx>) | |
1a4d82fc | 1989 | { |
a7813a04 | 1990 | self.fulfillment_cx.borrow_mut() |
7cac9316 | 1991 | .register_bound(self, self.param_env, ty, def_id, cause); |
1a4d82fc JJ |
1992 | } |
1993 | ||
e9174d1e | 1994 | pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> { |
32a655c1 | 1995 | let t = AstConv::ast_ty_to_ty(self, ast_t); |
b039eaaf | 1996 | self.register_wf_obligation(t, ast_t.span, traits::MiscObligation); |
1a4d82fc JJ |
1997 | t |
1998 | } | |
1999 | ||
3b2f2976 XL |
2000 | pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { |
2001 | match self.tables.borrow().node_types().get(id) { | |
1a4d82fc | 2002 | Some(&t) => t, |
ea8adc8c | 2003 | None if self.is_tainted_by_errors() => self.tcx.types.err, |
1a4d82fc | 2004 | None => { |
3b2f2976 | 2005 | let node_id = self.tcx.hir.definitions().find_node_for_hir_id(id); |
54a0048b | 2006 | bug!("no type for node {}: {} in fcx {}", |
3b2f2976 | 2007 | node_id, self.tcx.hir.node_to_string(node_id), |
54a0048b | 2008 | self.tag()); |
1a4d82fc JJ |
2009 | } |
2010 | } | |
2011 | } | |
2012 | ||
e9174d1e SL |
2013 | /// Registers an obligation for checking later, during regionck, that the type `ty` must |
2014 | /// outlive the region `r`. | |
2015 | pub fn register_wf_obligation(&self, | |
2016 | ty: Ty<'tcx>, | |
2017 | span: Span, | |
2018 | code: traits::ObligationCauseCode<'tcx>) | |
2019 | { | |
2020 | // WF obligations never themselves fail, so no real need to give a detailed cause: | |
2021 | let cause = traits::ObligationCause::new(span, self.body_id, code); | |
7cac9316 XL |
2022 | self.register_predicate(traits::Obligation::new(cause, |
2023 | self.param_env, | |
2024 | ty::Predicate::WellFormed(ty))); | |
e9174d1e SL |
2025 | } |
2026 | ||
e9174d1e SL |
2027 | /// Registers obligations that all types appearing in `substs` are well-formed. |
2028 | pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) | |
1a4d82fc | 2029 | { |
9e0c209e | 2030 | for ty in substs.types() { |
e9174d1e | 2031 | self.register_wf_obligation(ty, expr.span, traits::MiscObligation); |
1a4d82fc JJ |
2032 | } |
2033 | } | |
2034 | ||
2035 | /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each | |
2036 | /// type/region parameter was instantiated (`substs`), creates and registers suitable | |
2037 | /// trait/region obligations. | |
2038 | /// | |
2039 | /// For example, if there is a function: | |
2040 | /// | |
2041 | /// ``` | |
2042 | /// fn foo<'a,T:'a>(...) | |
2043 | /// ``` | |
2044 | /// | |
2045 | /// and a reference: | |
2046 | /// | |
2047 | /// ``` | |
2048 | /// let f = foo; | |
2049 | /// ``` | |
2050 | /// | |
2051 | /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a` | |
2052 | /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally. | |
2053 | pub fn add_obligations_for_parameters(&self, | |
2054 | cause: traits::ObligationCause<'tcx>, | |
85aaf69f | 2055 | predicates: &ty::InstantiatedPredicates<'tcx>) |
1a4d82fc | 2056 | { |
85aaf69f | 2057 | assert!(!predicates.has_escaping_regions()); |
1a4d82fc | 2058 | |
62682a34 SL |
2059 | debug!("add_obligations_for_parameters(predicates={:?})", |
2060 | predicates); | |
1a4d82fc | 2061 | |
7cac9316 | 2062 | for obligation in traits::predicates_for_generics(cause, self.param_env, predicates) { |
62682a34 SL |
2063 | self.register_predicate(obligation); |
2064 | } | |
1a4d82fc | 2065 | } |
85aaf69f | 2066 | |
e9174d1e | 2067 | // FIXME(arielb1): use this instead of field.ty everywhere |
54a0048b SL |
2068 | // Only for fields! Returns <none> for methods> |
2069 | // Indifferent to privacy flags | |
e9174d1e SL |
2070 | pub fn field_ty(&self, |
2071 | span: Span, | |
476ff2be | 2072 | field: &'tcx ty::FieldDef, |
e9174d1e SL |
2073 | substs: &Substs<'tcx>) |
2074 | -> Ty<'tcx> | |
85aaf69f | 2075 | { |
e9174d1e | 2076 | self.normalize_associated_types_in(span, |
a7813a04 | 2077 | &field.ty(self.tcx, substs)) |
85aaf69f | 2078 | } |
c34b1796 AL |
2079 | |
2080 | fn check_casts(&self) { | |
a7813a04 | 2081 | let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); |
62682a34 SL |
2082 | for cast in deferred_cast_checks.drain(..) { |
2083 | cast.check(self); | |
c34b1796 | 2084 | } |
c34b1796 | 2085 | } |
d9579d0f | 2086 | |
ea8adc8c XL |
2087 | fn resolve_generator_interiors(&self, def_id: DefId) { |
2088 | let mut deferred_generator_interiors = self.deferred_generator_interiors.borrow_mut(); | |
2089 | for (body_id, witness) in deferred_generator_interiors.drain(..) { | |
2090 | generator_interior::resolve_interior(self, def_id, body_id, witness); | |
2091 | } | |
2092 | } | |
2093 | ||
c1a9b12d | 2094 | /// Apply "fallbacks" to some types |
8bb4bdeb XL |
2095 | /// unconstrained types get replaced with ! or () (depending on whether |
2096 | /// feature(never_type) is enabled), unconstrained ints with i32, and | |
2097 | /// unconstrained floats with f64. | |
c1a9b12d | 2098 | fn default_type_parameters(&self) { |
54a0048b SL |
2099 | use rustc::ty::error::UnconstrainedNumeric::Neither; |
2100 | use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; | |
a7813a04 XL |
2101 | |
2102 | // Defaulting inference variables becomes very dubious if we have | |
2103 | // encountered type-checking errors. Therefore, if we think we saw | |
2104 | // some errors in this function, just resolve all uninstanted type | |
2105 | // varibles to TyError. | |
2106 | if self.is_tainted_by_errors() { | |
2107 | for ty in &self.unsolved_variables() { | |
2108 | if let ty::TyInfer(_) = self.shallow_resolve(ty).sty { | |
2109 | debug!("default_type_parameters: defaulting `{:?}` to error", ty); | |
3157f602 | 2110 | self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx().types.err); |
a7813a04 XL |
2111 | } |
2112 | } | |
2113 | return; | |
2114 | } | |
2115 | ||
2116 | for ty in &self.unsolved_variables() { | |
2117 | let resolved = self.resolve_type_vars_if_possible(ty); | |
2118 | if self.type_var_diverges(resolved) { | |
5bcae85e | 2119 | debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges", |
a7813a04 | 2120 | resolved); |
5bcae85e SL |
2121 | self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, |
2122 | self.tcx.mk_diverging_default()); | |
c1a9b12d | 2123 | } else { |
a7813a04 | 2124 | match self.type_is_unconstrained_numeric(resolved) { |
c1a9b12d | 2125 | UnconstrainedInt => { |
a7813a04 XL |
2126 | debug!("default_type_parameters: defaulting `{:?}` to `i32`", |
2127 | resolved); | |
3157f602 | 2128 | self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32) |
c1a9b12d SL |
2129 | }, |
2130 | UnconstrainedFloat => { | |
a7813a04 XL |
2131 | debug!("default_type_parameters: defaulting `{:?}` to `f32`", |
2132 | resolved); | |
3157f602 | 2133 | self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64) |
c1a9b12d SL |
2134 | } |
2135 | Neither => { } | |
2136 | } | |
2137 | } | |
2138 | } | |
2139 | } | |
2140 | ||
cc61c64b | 2141 | // Implements type inference fallback algorithm |
d9579d0f | 2142 | fn select_all_obligations_and_apply_defaults(&self) { |
d9579d0f AL |
2143 | self.select_obligations_where_possible(); |
2144 | self.default_type_parameters(); | |
2145 | self.select_obligations_where_possible(); | |
2146 | } | |
2147 | ||
2148 | fn select_all_obligations_or_error(&self) { | |
2149 | debug!("select_all_obligations_or_error"); | |
2150 | ||
2151 | // upvar inference should have ensured that all deferred call | |
2152 | // resolutions are handled by now. | |
a7813a04 | 2153 | assert!(self.deferred_call_resolutions.borrow().is_empty()); |
d9579d0f AL |
2154 | |
2155 | self.select_all_obligations_and_apply_defaults(); | |
c1a9b12d | 2156 | |
a7813a04 | 2157 | let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); |
5bcae85e | 2158 | |
a7813a04 | 2159 | match fulfillment_cx.select_all_or_error(self) { |
d9579d0f | 2160 | Ok(()) => { } |
041b39d2 | 2161 | Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } |
a7813a04 | 2162 | } |
d9579d0f AL |
2163 | } |
2164 | ||
2165 | /// Select as many obligations as we can at present. | |
2166 | fn select_obligations_where_possible(&self) { | |
a7813a04 | 2167 | match self.fulfillment_cx.borrow_mut().select_where_possible(self) { |
d9579d0f | 2168 | Ok(()) => { } |
041b39d2 | 2169 | Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } |
d9579d0f AL |
2170 | } |
2171 | } | |
62682a34 | 2172 | |
a7813a04 XL |
2173 | /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait |
2174 | /// returns a type of `&T`, but the actual type we assign to the | |
2175 | /// *expression* is `T`. So this function just peels off the return | |
2176 | /// type by one layer to yield `T`. | |
2177 | fn make_overloaded_lvalue_return_type(&self, | |
2178 | method: MethodCallee<'tcx>) | |
2179 | -> ty::TypeAndMut<'tcx> | |
2180 | { | |
2181 | // extract method return type, which will be &T; | |
7cac9316 | 2182 | let ret_ty = method.sig.output(); |
a7813a04 XL |
2183 | |
2184 | // method returns &T, but the type as visible to user is T, so deref | |
2185 | ret_ty.builtin_deref(true, NoPreference).unwrap() | |
2186 | } | |
2187 | ||
2188 | fn lookup_indexing(&self, | |
2189 | expr: &hir::Expr, | |
2190 | base_expr: &'gcx hir::Expr, | |
2191 | base_ty: Ty<'tcx>, | |
2192 | idx_ty: Ty<'tcx>, | |
2193 | lvalue_pref: LvaluePreference) | |
2194 | -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> | |
2195 | { | |
2196 | // FIXME(#18741) -- this is almost but not quite the same as the | |
2197 | // autoderef that normal method probing does. They could likely be | |
2198 | // consolidated. | |
2199 | ||
3157f602 | 2200 | let mut autoderef = self.autoderef(base_expr.span, base_ty); |
7cac9316 XL |
2201 | let mut result = None; |
2202 | while result.is_none() && autoderef.next().is_some() { | |
2203 | result = self.try_index_step(expr, base_expr, &autoderef, lvalue_pref, idx_ty); | |
1a4d82fc | 2204 | } |
7cac9316 XL |
2205 | autoderef.finalize(); |
2206 | result | |
1a4d82fc | 2207 | } |
1a4d82fc | 2208 | |
a7813a04 XL |
2209 | /// To type-check `base_expr[index_expr]`, we progressively autoderef |
2210 | /// (and otherwise adjust) `base_expr`, looking for a type which either | |
2211 | /// supports builtin indexing or overloaded indexing. | |
2212 | /// This loop implements one step in that search; the autoderef loop | |
2213 | /// is implemented by `lookup_indexing`. | |
2214 | fn try_index_step(&self, | |
a7813a04 | 2215 | expr: &hir::Expr, |
7cac9316 XL |
2216 | base_expr: &hir::Expr, |
2217 | autoderef: &Autoderef<'a, 'gcx, 'tcx>, | |
a7813a04 XL |
2218 | lvalue_pref: LvaluePreference, |
2219 | index_ty: Ty<'tcx>) | |
2220 | -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> | |
2221 | { | |
7cac9316 | 2222 | let adjusted_ty = autoderef.unambiguous_final_ty(); |
cc61c64b XL |
2223 | debug!("try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ |
2224 | index_ty={:?})", | |
a7813a04 XL |
2225 | expr, |
2226 | base_expr, | |
2227 | adjusted_ty, | |
a7813a04 XL |
2228 | index_ty); |
2229 | ||
a7813a04 XL |
2230 | // First, try built-in indexing. |
2231 | match (adjusted_ty.builtin_index(), &index_ty.sty) { | |
2232 | (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => { | |
2233 | debug!("try_index_step: success, using built-in indexing"); | |
7cac9316 XL |
2234 | let adjustments = autoderef.adjust_steps(lvalue_pref); |
2235 | self.apply_adjustments(base_expr, adjustments); | |
2236 | return Some((self.tcx.types.usize, ty)); | |
a7813a04 XL |
2237 | } |
2238 | _ => {} | |
1a4d82fc | 2239 | } |
1a4d82fc | 2240 | |
7cac9316 XL |
2241 | for &unsize in &[false, true] { |
2242 | let mut self_ty = adjusted_ty; | |
2243 | if unsize { | |
2244 | // We only unsize arrays here. | |
2245 | if let ty::TyArray(element_ty, _) = adjusted_ty.sty { | |
2246 | self_ty = self.tcx.mk_slice(element_ty); | |
2247 | } else { | |
2248 | continue; | |
2249 | } | |
2250 | } | |
2251 | ||
2252 | // If some lookup succeeds, write callee into table and extract index/element | |
2253 | // type from the method signature. | |
2254 | // If some lookup succeeded, install method in table | |
2255 | let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span)); | |
2256 | let method = self.try_overloaded_lvalue_op( | |
2257 | expr.span, self_ty, &[input_ty], lvalue_pref, LvalueOp::Index); | |
2258 | ||
2259 | let result = method.map(|ok| { | |
2260 | debug!("try_index_step: success, using overloaded indexing"); | |
2261 | let method = self.register_infer_ok_obligations(ok); | |
2262 | ||
2263 | let mut adjustments = autoderef.adjust_steps(lvalue_pref); | |
2264 | if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { | |
2265 | adjustments.push(Adjustment { | |
2266 | kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), | |
2267 | target: self.tcx.mk_ref(region, ty::TypeAndMut { | |
2268 | mutbl: mt.mutbl, | |
2269 | ty: adjusted_ty | |
2270 | }) | |
2271 | }); | |
2272 | } | |
2273 | if unsize { | |
2274 | adjustments.push(Adjustment { | |
2275 | kind: Adjust::Unsize, | |
2276 | target: method.sig.inputs()[0] | |
2277 | }); | |
2278 | } | |
2279 | self.apply_adjustments(base_expr, adjustments); | |
2280 | ||
3b2f2976 | 2281 | self.write_method_call(expr.hir_id, method); |
7cac9316 XL |
2282 | (input_ty, self.make_overloaded_lvalue_return_type(method).ty) |
2283 | }); | |
2284 | if result.is_some() { | |
2285 | return result; | |
2286 | } | |
2287 | } | |
2288 | ||
2289 | None | |
cc61c64b XL |
2290 | } |
2291 | ||
2292 | fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option<DefId>, Symbol) { | |
2293 | let (tr, name) = match (op, is_mut) { | |
2294 | (LvalueOp::Deref, false) => | |
ea8adc8c | 2295 | (self.tcx.lang_items().deref_trait(), "deref"), |
cc61c64b | 2296 | (LvalueOp::Deref, true) => |
ea8adc8c | 2297 | (self.tcx.lang_items().deref_mut_trait(), "deref_mut"), |
cc61c64b | 2298 | (LvalueOp::Index, false) => |
ea8adc8c | 2299 | (self.tcx.lang_items().index_trait(), "index"), |
cc61c64b | 2300 | (LvalueOp::Index, true) => |
ea8adc8c | 2301 | (self.tcx.lang_items().index_mut_trait(), "index_mut"), |
cc61c64b XL |
2302 | }; |
2303 | (tr, Symbol::intern(name)) | |
2304 | } | |
2305 | ||
2306 | fn try_overloaded_lvalue_op(&self, | |
2307 | span: Span, | |
cc61c64b XL |
2308 | base_ty: Ty<'tcx>, |
2309 | arg_tys: &[Ty<'tcx>], | |
2310 | lvalue_pref: LvaluePreference, | |
2311 | op: LvalueOp) | |
2312 | -> Option<InferOk<'tcx, MethodCallee<'tcx>>> | |
2313 | { | |
7cac9316 | 2314 | debug!("try_overloaded_lvalue_op({:?},{:?},{:?},{:?})", |
cc61c64b | 2315 | span, |
cc61c64b XL |
2316 | base_ty, |
2317 | lvalue_pref, | |
2318 | op); | |
2319 | ||
2320 | // Try Mut first, if preferred. | |
2321 | let (mut_tr, mut_op) = self.resolve_lvalue_op(op, true); | |
2322 | let method = match (lvalue_pref, mut_tr) { | |
a7813a04 | 2323 | (PreferMutLvalue, Some(trait_did)) => { |
7cac9316 | 2324 | self.lookup_method_in_trait(span, mut_op, trait_did, base_ty, Some(arg_tys)) |
a7813a04 XL |
2325 | } |
2326 | _ => None, | |
1a4d82fc JJ |
2327 | }; |
2328 | ||
cc61c64b XL |
2329 | // Otherwise, fall back to the immutable version. |
2330 | let (imm_tr, imm_op) = self.resolve_lvalue_op(op, false); | |
2331 | let method = match (method, imm_tr) { | |
a7813a04 | 2332 | (None, Some(trait_did)) => { |
7cac9316 | 2333 | self.lookup_method_in_trait(span, imm_op, trait_did, base_ty, Some(arg_tys)) |
1a4d82fc | 2334 | } |
a7813a04 XL |
2335 | (method, _) => method, |
2336 | }; | |
2337 | ||
cc61c64b | 2338 | method |
a7813a04 XL |
2339 | } |
2340 | ||
2341 | fn check_method_argument_types(&self, | |
2342 | sp: Span, | |
abe05a73 | 2343 | expr_sp: Span, |
7cac9316 | 2344 | method: Result<MethodCallee<'tcx>, ()>, |
476ff2be | 2345 | args_no_rcvr: &'gcx [hir::Expr], |
a7813a04 XL |
2346 | tuple_arguments: TupleArgumentsFlag, |
2347 | expected: Expectation<'tcx>) | |
5bcae85e | 2348 | -> Ty<'tcx> { |
7cac9316 XL |
2349 | let has_error = match method { |
2350 | Ok(method) => { | |
2351 | method.substs.references_error() || method.sig.references_error() | |
2352 | } | |
2353 | Err(_) => true | |
2354 | }; | |
2355 | if has_error { | |
a7813a04 XL |
2356 | let err_inputs = self.err_args(args_no_rcvr.len()); |
2357 | ||
2358 | let err_inputs = match tuple_arguments { | |
2359 | DontTupleArguments => err_inputs, | |
8bb4bdeb | 2360 | TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], |
a7813a04 XL |
2361 | }; |
2362 | ||
abe05a73 | 2363 | self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr, |
476ff2be | 2364 | false, tuple_arguments, None); |
7cac9316 | 2365 | return self.tcx.types.err; |
1a4d82fc | 2366 | } |
7cac9316 XL |
2367 | |
2368 | let method = method.unwrap(); | |
2369 | // HACK(eddyb) ignore self in the definition (see above). | |
2370 | let expected_arg_tys = self.expected_inputs_for_expected_output( | |
2371 | sp, | |
2372 | expected, | |
2373 | method.sig.output(), | |
2374 | &method.sig.inputs()[1..] | |
2375 | ); | |
abe05a73 | 2376 | self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..], |
7cac9316 XL |
2377 | args_no_rcvr, method.sig.variadic, tuple_arguments, |
2378 | self.tcx.hir.span_if_local(method.def_id)); | |
2379 | method.sig.output() | |
1a4d82fc | 2380 | } |
1a4d82fc | 2381 | |
a7813a04 XL |
2382 | /// Generic function that factors out common logic from function calls, |
2383 | /// method calls and overloaded operators. | |
2384 | fn check_argument_types(&self, | |
2385 | sp: Span, | |
abe05a73 | 2386 | expr_sp: Span, |
a7813a04 XL |
2387 | fn_inputs: &[Ty<'tcx>], |
2388 | expected_arg_tys: &[Ty<'tcx>], | |
476ff2be | 2389 | args: &'gcx [hir::Expr], |
a7813a04 | 2390 | variadic: bool, |
476ff2be SL |
2391 | tuple_arguments: TupleArgumentsFlag, |
2392 | def_span: Option<Span>) { | |
a7813a04 XL |
2393 | let tcx = self.tcx; |
2394 | ||
2395 | // Grab the argument types, supplying fresh type variables | |
2396 | // if the wrong number of arguments were supplied | |
2397 | let supplied_arg_count = if tuple_arguments == DontTupleArguments { | |
2398 | args.len() | |
2399 | } else { | |
2400 | 1 | |
2401 | }; | |
1a4d82fc | 2402 | |
a7813a04 XL |
2403 | // All the input types from the fn signature must outlive the call |
2404 | // so as to validate implied bounds. | |
2405 | for &fn_input_ty in fn_inputs { | |
2406 | self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation); | |
2407 | } | |
2408 | ||
2409 | let mut expected_arg_tys = expected_arg_tys; | |
2410 | let expected_arg_count = fn_inputs.len(); | |
3157f602 | 2411 | |
c30ab7b3 SL |
2412 | let sp_args = if args.len() > 0 { |
2413 | let (first, args) = args.split_at(1); | |
2414 | let mut sp_tmp = first[0].span; | |
2415 | for arg in args { | |
2416 | let sp_opt = self.sess().codemap().merge_spans(sp_tmp, arg.span); | |
2417 | if ! sp_opt.is_some() { | |
2418 | break; | |
2419 | } | |
2420 | sp_tmp = sp_opt.unwrap(); | |
2421 | }; | |
2422 | sp_tmp | |
2423 | } else { | |
2424 | sp | |
2425 | }; | |
2426 | ||
abe05a73 XL |
2427 | fn parameter_count_error<'tcx>(sess: &Session, |
2428 | sp: Span, | |
2429 | expr_sp: Span, | |
2430 | expected_count: usize, | |
2431 | arg_count: usize, | |
2432 | error_code: &str, | |
2433 | variadic: bool, | |
2434 | def_span: Option<Span>, | |
2435 | sugg_unit: bool) { | |
3157f602 XL |
2436 | let mut err = sess.struct_span_err_with_code(sp, |
2437 | &format!("this function takes {}{} parameter{} but {} parameter{} supplied", | |
2438 | if variadic {"at least "} else {""}, | |
2439 | expected_count, | |
2440 | if expected_count == 1 {""} else {"s"}, | |
2441 | arg_count, | |
2442 | if arg_count == 1 {" was"} else {"s were"}), | |
abe05a73 | 2443 | DiagnosticId::Error(error_code.to_owned())); |
5bcae85e | 2444 | |
476ff2be | 2445 | if let Some(def_s) = def_span { |
7cac9316 | 2446 | err.span_label(def_s, "defined here"); |
3157f602 | 2447 | } |
ea8adc8c | 2448 | if sugg_unit { |
abe05a73 | 2449 | let sugg_span = expr_sp.end_point(); |
ea8adc8c XL |
2450 | // remove closing `)` from the span |
2451 | let sugg_span = sugg_span.with_hi(sugg_span.lo()); | |
2452 | err.span_suggestion( | |
2453 | sugg_span, | |
abe05a73 | 2454 | "expected the unit value `()`; create it with empty parentheses", |
ea8adc8c XL |
2455 | String::from("()")); |
2456 | } else { | |
2457 | err.span_label(sp, format!("expected {}{} parameter{}", | |
2458 | if variadic {"at least "} else {""}, | |
2459 | expected_count, | |
2460 | if expected_count == 1 {""} else {"s"})); | |
2461 | } | |
3157f602 XL |
2462 | err.emit(); |
2463 | } | |
2464 | ||
a7813a04 XL |
2465 | let formal_tys = if tuple_arguments == TupleArguments { |
2466 | let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); | |
2467 | match tuple_type.sty { | |
8bb4bdeb | 2468 | ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { |
abe05a73 | 2469 | parameter_count_error(tcx.sess, sp_args, expr_sp, arg_types.len(), args.len(), |
ea8adc8c | 2470 | "E0057", false, def_span, false); |
3157f602 XL |
2471 | expected_arg_tys = &[]; |
2472 | self.err_args(args.len()) | |
2473 | } | |
8bb4bdeb | 2474 | ty::TyTuple(arg_types, _) => { |
3157f602 XL |
2475 | expected_arg_tys = match expected_arg_tys.get(0) { |
2476 | Some(&ty) => match ty.sty { | |
8bb4bdeb | 2477 | ty::TyTuple(ref tys, _) => &tys, |
3157f602 XL |
2478 | _ => &[] |
2479 | }, | |
2480 | None => &[] | |
2481 | }; | |
2482 | arg_types.to_vec() | |
a7813a04 XL |
2483 | } |
2484 | _ => { | |
2485 | span_err!(tcx.sess, sp, E0059, | |
2486 | "cannot use call notation; the first type parameter \ | |
2487 | for the function trait is neither a tuple nor unit"); | |
c34b1796 | 2488 | expected_arg_tys = &[]; |
a7813a04 | 2489 | self.err_args(args.len()) |
1a4d82fc JJ |
2490 | } |
2491 | } | |
a7813a04 XL |
2492 | } else if expected_arg_count == supplied_arg_count { |
2493 | fn_inputs.to_vec() | |
2494 | } else if variadic { | |
2495 | if supplied_arg_count >= expected_arg_count { | |
2496 | fn_inputs.to_vec() | |
2497 | } else { | |
abe05a73 | 2498 | parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, |
ea8adc8c | 2499 | supplied_arg_count, "E0060", true, def_span, false); |
c34b1796 | 2500 | expected_arg_tys = &[]; |
a7813a04 | 2501 | self.err_args(supplied_arg_count) |
1a4d82fc | 2502 | } |
1a4d82fc | 2503 | } else { |
ea8adc8c XL |
2504 | // is the missing argument of type `()`? |
2505 | let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { | |
2506 | self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_nil() | |
2507 | } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { | |
2508 | self.resolve_type_vars_if_possible(&fn_inputs[0]).is_nil() | |
2509 | } else { | |
2510 | false | |
2511 | }; | |
abe05a73 | 2512 | parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, |
ea8adc8c | 2513 | supplied_arg_count, "E0061", false, def_span, sugg_unit); |
c34b1796 | 2514 | expected_arg_tys = &[]; |
a7813a04 | 2515 | self.err_args(supplied_arg_count) |
1a4d82fc | 2516 | }; |
a7813a04 XL |
2517 | |
2518 | debug!("check_argument_types: formal_tys={:?}", | |
2519 | formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>()); | |
2520 | ||
2521 | // Check the arguments. | |
2522 | // We do this in a pretty awful way: first we typecheck any arguments | |
476ff2be SL |
2523 | // that are not closures, then we typecheck the closures. This is so |
2524 | // that we have more information about the types of arguments when we | |
2525 | // typecheck the functions. This isn't really the right way to do this. | |
2526 | for &check_closures in &[false, true] { | |
2527 | debug!("check_closures={}", check_closures); | |
a7813a04 XL |
2528 | |
2529 | // More awful hacks: before we check argument types, try to do | |
2530 | // an "opportunistic" vtable resolution of any trait bounds on | |
2531 | // the call. This helps coercions. | |
476ff2be | 2532 | if check_closures { |
a7813a04 | 2533 | self.select_obligations_where_possible(); |
92a42be0 | 2534 | } |
a7813a04 XL |
2535 | |
2536 | // For variadic functions, we don't have a declared type for all of | |
2537 | // the arguments hence we only do our usual type checking with | |
2538 | // the arguments who's types we do know. | |
2539 | let t = if variadic { | |
2540 | expected_arg_count | |
2541 | } else if tuple_arguments == TupleArguments { | |
2542 | args.len() | |
2543 | } else { | |
2544 | supplied_arg_count | |
1a4d82fc | 2545 | }; |
a7813a04 | 2546 | for (i, arg) in args.iter().take(t).enumerate() { |
476ff2be SL |
2547 | // Warn only for the first loop (the "no closures" one). |
2548 | // Closure arguments themselves can't be diverging, but | |
2549 | // a previous argument can, e.g. `foo(panic!(), || {})`. | |
2550 | if !check_closures { | |
2551 | self.warn_if_unreachable(arg.id, arg.span, "expression"); | |
a7813a04 | 2552 | } |
476ff2be SL |
2553 | |
2554 | let is_closure = match arg.node { | |
a7813a04 XL |
2555 | hir::ExprClosure(..) => true, |
2556 | _ => false | |
2557 | }; | |
1a4d82fc | 2558 | |
476ff2be SL |
2559 | if is_closure != check_closures { |
2560 | continue; | |
2561 | } | |
1a4d82fc | 2562 | |
476ff2be SL |
2563 | debug!("checking the argument"); |
2564 | let formal_ty = formal_tys[i]; | |
85aaf69f | 2565 | |
476ff2be SL |
2566 | // The special-cased logic below has three functions: |
2567 | // 1. Provide as good of an expected type as possible. | |
2568 | let expected = expected_arg_tys.get(i).map(|&ty| { | |
2569 | Expectation::rvalue_hint(self, ty) | |
2570 | }); | |
92a42be0 | 2571 | |
cc61c64b XL |
2572 | let checked_ty = self.check_expr_with_expectation( |
2573 | &arg, | |
2574 | expected.unwrap_or(ExpectHasType(formal_ty))); | |
2575 | ||
476ff2be SL |
2576 | // 2. Coerce to the most detailed type that could be coerced |
2577 | // to, which is `expected_ty` if `rvalue_hint` returns an | |
2578 | // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. | |
2579 | let coerce_ty = expected.and_then(|e| e.only_has_type(self)); | |
2580 | self.demand_coerce(&arg, checked_ty, coerce_ty.unwrap_or(formal_ty)); | |
2581 | ||
2582 | // 3. Relate the expected type and the formal one, | |
2583 | // if the expected type was used for the coercion. | |
2584 | coerce_ty.map(|ty| self.demand_suptype(arg.span, formal_ty, ty)); | |
92a42be0 | 2585 | } |
92a42be0 SL |
2586 | } |
2587 | ||
a7813a04 XL |
2588 | // We also need to make sure we at least write the ty of the other |
2589 | // arguments which we skipped above. | |
2590 | if variadic { | |
041b39d2 XL |
2591 | fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) { |
2592 | type_error_struct!(s, span, t, E0617, | |
2593 | "can't pass `{}` to variadic function, cast to `{}`", | |
2594 | t, cast_ty).emit(); | |
2595 | } | |
2596 | ||
a7813a04 | 2597 | for arg in args.iter().skip(expected_arg_count) { |
9e0c209e | 2598 | let arg_ty = self.check_expr(&arg); |
1a4d82fc | 2599 | |
a7813a04 XL |
2600 | // There are a few types which get autopromoted when passed via varargs |
2601 | // in C but we just error out instead and require explicit casts. | |
041b39d2 | 2602 | let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); |
a7813a04 XL |
2603 | match arg_ty.sty { |
2604 | ty::TyFloat(ast::FloatTy::F32) => { | |
041b39d2 | 2605 | variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); |
a7813a04 XL |
2606 | } |
2607 | ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => { | |
041b39d2 | 2608 | variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); |
a7813a04 XL |
2609 | } |
2610 | ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { | |
041b39d2 | 2611 | variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); |
a7813a04 | 2612 | } |
041b39d2 XL |
2613 | ty::TyFnDef(..) => { |
2614 | let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); | |
a7813a04 | 2615 | let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); |
041b39d2 | 2616 | variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); |
a7813a04 XL |
2617 | } |
2618 | _ => {} | |
54a0048b | 2619 | } |
1a4d82fc JJ |
2620 | } |
2621 | } | |
2622 | } | |
1a4d82fc | 2623 | |
a7813a04 XL |
2624 | fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> { |
2625 | (0..len).map(|_| self.tcx.types.err).collect() | |
1a4d82fc | 2626 | } |
1a4d82fc | 2627 | |
a7813a04 XL |
2628 | // AST fragment checking |
2629 | fn check_lit(&self, | |
2630 | lit: &ast::Lit, | |
2631 | expected: Expectation<'tcx>) | |
2632 | -> Ty<'tcx> | |
2633 | { | |
2634 | let tcx = self.tcx; | |
85aaf69f | 2635 | |
a7813a04 XL |
2636 | match lit.node { |
2637 | ast::LitKind::Str(..) => tcx.mk_static_str(), | |
2638 | ast::LitKind::ByteStr(ref v) => { | |
cc61c64b | 2639 | tcx.mk_imm_ref(tcx.types.re_static, |
ea8adc8c | 2640 | tcx.mk_array(tcx.types.u8, v.len() as u64)) |
a7813a04 XL |
2641 | } |
2642 | ast::LitKind::Byte(_) => tcx.types.u8, | |
2643 | ast::LitKind::Char(_) => tcx.types.char, | |
2644 | ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(t), | |
2645 | ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(t), | |
2646 | ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { | |
2647 | let opt_ty = expected.to_option(self).and_then(|ty| { | |
2648 | match ty.sty { | |
2649 | ty::TyInt(_) | ty::TyUint(_) => Some(ty), | |
2650 | ty::TyChar => Some(tcx.types.u8), | |
2651 | ty::TyRawPtr(..) => Some(tcx.types.usize), | |
2652 | ty::TyFnDef(..) | ty::TyFnPtr(_) => Some(tcx.types.usize), | |
2653 | _ => None | |
2654 | } | |
2655 | }); | |
2656 | opt_ty.unwrap_or_else( | |
2657 | || tcx.mk_int_var(self.next_int_var_id())) | |
2658 | } | |
2659 | ast::LitKind::Float(_, t) => tcx.mk_mach_float(t), | |
2660 | ast::LitKind::FloatUnsuffixed(_) => { | |
2661 | let opt_ty = expected.to_option(self).and_then(|ty| { | |
2662 | match ty.sty { | |
2663 | ty::TyFloat(_) => Some(ty), | |
2664 | _ => None | |
2665 | } | |
2666 | }); | |
2667 | opt_ty.unwrap_or_else( | |
2668 | || tcx.mk_float_var(self.next_float_var_id())) | |
2669 | } | |
2670 | ast::LitKind::Bool(_) => tcx.types.bool | |
2671 | } | |
2672 | } | |
2673 | ||
2674 | fn check_expr_eq_type(&self, | |
2675 | expr: &'gcx hir::Expr, | |
2676 | expected: Ty<'tcx>) { | |
9e0c209e SL |
2677 | let ty = self.check_expr_with_hint(expr, expected); |
2678 | self.demand_eqtype(expr.span, expected, ty); | |
a7813a04 XL |
2679 | } |
2680 | ||
041b39d2 XL |
2681 | pub fn check_expr_has_type_or_error(&self, |
2682 | expr: &'gcx hir::Expr, | |
2683 | expected: Ty<'tcx>) -> Ty<'tcx> { | |
2684 | self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected)) | |
2685 | } | |
2686 | ||
2687 | fn check_expr_meets_expectation_or_error(&self, | |
2688 | expr: &'gcx hir::Expr, | |
2689 | expected: Expectation<'tcx>) -> Ty<'tcx> { | |
2690 | let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); | |
2691 | let mut ty = self.check_expr_with_expectation(expr, expected); | |
cc61c64b XL |
2692 | |
2693 | // While we don't allow *arbitrary* coercions here, we *do* allow | |
2694 | // coercions from ! to `expected`. | |
2695 | if ty.is_never() { | |
3b2f2976 | 2696 | assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id), |
cc61c64b XL |
2697 | "expression with never type wound up being adjusted"); |
2698 | let adj_ty = self.next_diverging_ty_var( | |
2699 | TypeVariableOrigin::AdjustmentType(expr.span)); | |
7cac9316 | 2700 | self.apply_adjustments(expr, vec![Adjustment { |
cc61c64b XL |
2701 | kind: Adjust::NeverToAny, |
2702 | target: adj_ty | |
7cac9316 | 2703 | }]); |
cc61c64b XL |
2704 | ty = adj_ty; |
2705 | } | |
2706 | ||
041b39d2 XL |
2707 | if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { |
2708 | // Add help to type error if this is an `if` condition with an assignment | |
2709 | match (expected, &expr.node) { | |
2710 | (ExpectIfCondition, &hir::ExprAssign(ref lhs, ref rhs)) => { | |
3b2f2976 | 2711 | let msg = "try comparing for equality"; |
041b39d2 XL |
2712 | if let (Ok(left), Ok(right)) = ( |
2713 | self.tcx.sess.codemap().span_to_snippet(lhs.span), | |
2714 | self.tcx.sess.codemap().span_to_snippet(rhs.span)) | |
2715 | { | |
2716 | err.span_suggestion(expr.span, msg, format!("{} == {}", left, right)); | |
2717 | } else { | |
2718 | err.help(msg); | |
2719 | } | |
2720 | } | |
2721 | _ => (), | |
2722 | } | |
2723 | err.emit(); | |
2724 | } | |
9e0c209e | 2725 | ty |
a7813a04 XL |
2726 | } |
2727 | ||
2728 | fn check_expr_coercable_to_type(&self, | |
2729 | expr: &'gcx hir::Expr, | |
9e0c209e | 2730 | expected: Ty<'tcx>) -> Ty<'tcx> { |
abe05a73 XL |
2731 | self.check_expr_coercable_to_type_with_lvalue_pref(expr, expected, NoPreference) |
2732 | } | |
2733 | ||
2734 | fn check_expr_coercable_to_type_with_lvalue_pref(&self, | |
2735 | expr: &'gcx hir::Expr, | |
2736 | expected: Ty<'tcx>, | |
2737 | lvalue_pref: LvaluePreference) | |
2738 | -> Ty<'tcx> { | |
2739 | let ty = self.check_expr_with_expectation_and_lvalue_pref( | |
2740 | expr, | |
2741 | ExpectHasType(expected), | |
2742 | lvalue_pref); | |
2743 | self.demand_coerce(expr, ty, expected) | |
a7813a04 XL |
2744 | } |
2745 | ||
2746 | fn check_expr_with_hint(&self, expr: &'gcx hir::Expr, | |
9e0c209e | 2747 | expected: Ty<'tcx>) -> Ty<'tcx> { |
a7813a04 XL |
2748 | self.check_expr_with_expectation(expr, ExpectHasType(expected)) |
2749 | } | |
2750 | ||
2751 | fn check_expr_with_expectation(&self, | |
2752 | expr: &'gcx hir::Expr, | |
9e0c209e | 2753 | expected: Expectation<'tcx>) -> Ty<'tcx> { |
a7813a04 XL |
2754 | self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference) |
2755 | } | |
2756 | ||
9e0c209e | 2757 | fn check_expr(&self, expr: &'gcx hir::Expr) -> Ty<'tcx> { |
a7813a04 XL |
2758 | self.check_expr_with_expectation(expr, NoExpectation) |
2759 | } | |
2760 | ||
2761 | fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr, | |
9e0c209e | 2762 | lvalue_pref: LvaluePreference) -> Ty<'tcx> { |
a7813a04 XL |
2763 | self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref) |
2764 | } | |
2765 | ||
2766 | // determine the `self` type, using fresh variables for all variables | |
2767 | // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>` | |
2768 | // would return ($0, $1) where $0 and $1 are freshly instantiated type | |
2769 | // variables. | |
2770 | pub fn impl_self_ty(&self, | |
2771 | span: Span, // (potential) receiver for this impl | |
2772 | did: DefId) | |
2773 | -> TypeAndSubsts<'tcx> { | |
7cac9316 | 2774 | let ity = self.tcx.type_of(did); |
9e0c209e | 2775 | debug!("impl_self_ty: ity={:?}", ity); |
a7813a04 | 2776 | |
9e0c209e | 2777 | let substs = self.fresh_substs_for_item(span, did); |
476ff2be | 2778 | let substd_ty = self.instantiate_type_scheme(span, &substs, &ity); |
a7813a04 XL |
2779 | |
2780 | TypeAndSubsts { substs: substs, ty: substd_ty } | |
2781 | } | |
2782 | ||
32a655c1 SL |
2783 | /// Unifies the output type with the expected type early, for more coercions |
2784 | /// and forward type information on the input expressions. | |
2785 | fn expected_inputs_for_expected_output(&self, | |
2786 | call_span: Span, | |
2787 | expected_ret: Expectation<'tcx>, | |
2788 | formal_ret: Ty<'tcx>, | |
2789 | formal_args: &[Ty<'tcx>]) | |
2790 | -> Vec<Ty<'tcx>> { | |
ea8adc8c | 2791 | let formal_ret = self.resolve_type_vars_with_obligations(formal_ret); |
a7813a04 | 2792 | let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| { |
476ff2be | 2793 | self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || { |
5bcae85e SL |
2794 | // Attempt to apply a subtyping relationship between the formal |
2795 | // return type (likely containing type variables if the function | |
2796 | // is polymorphic) and the expected return type. | |
2797 | // No argument expectations are produced if unification fails. | |
476ff2be | 2798 | let origin = self.misc(call_span); |
7cac9316 | 2799 | let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret); |
cc61c64b | 2800 | |
5bcae85e SL |
2801 | // FIXME(#15760) can't use try! here, FromError doesn't default |
2802 | // to identity so the resulting type is not constrained. | |
2803 | match ures { | |
cc61c64b XL |
2804 | Ok(ok) => { |
2805 | // Process any obligations locally as much as | |
2806 | // we can. We don't care if some things turn | |
2807 | // out unconstrained or ambiguous, as we're | |
2808 | // just trying to get hints here. | |
2809 | let result = self.save_and_restore_in_snapshot_flag(|_| { | |
2810 | let mut fulfill = FulfillmentContext::new(); | |
2811 | let ok = ok; // FIXME(#30046) | |
2812 | for obligation in ok.obligations { | |
2813 | fulfill.register_predicate_obligation(self, obligation); | |
2814 | } | |
2815 | fulfill.select_where_possible(self) | |
2816 | }); | |
2817 | ||
2818 | match result { | |
2819 | Ok(()) => { } | |
2820 | Err(_) => return Err(()), | |
2821 | } | |
2822 | } | |
2823 | Err(_) => return Err(()), | |
5bcae85e | 2824 | } |
85aaf69f | 2825 | |
5bcae85e SL |
2826 | // Record all the argument types, with the substitutions |
2827 | // produced from the above subtyping unification. | |
2828 | Ok(formal_args.iter().map(|ty| { | |
2829 | self.resolve_type_vars_if_possible(ty) | |
2830 | }).collect()) | |
2831 | }).ok() | |
a7813a04 | 2832 | }).unwrap_or(vec![]); |
32a655c1 | 2833 | debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})", |
a7813a04 XL |
2834 | formal_args, formal_ret, |
2835 | expected_args, expected_ret); | |
2836 | expected_args | |
2837 | } | |
1a4d82fc JJ |
2838 | |
2839 | // Checks a method call. | |
a7813a04 XL |
2840 | fn check_method_call(&self, |
2841 | expr: &'gcx hir::Expr, | |
041b39d2 XL |
2842 | segment: &hir::PathSegment, |
2843 | span: Span, | |
476ff2be | 2844 | args: &'gcx [hir::Expr], |
a7813a04 | 2845 | expected: Expectation<'tcx>, |
9e0c209e | 2846 | lvalue_pref: LvaluePreference) -> Ty<'tcx> { |
7453a54e | 2847 | let rcvr = &args[0]; |
9e0c209e | 2848 | let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref); |
1a4d82fc | 2849 | // no need to check for bot/err -- callee does that |
041b39d2 | 2850 | let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t); |
a7813a04 | 2851 | |
041b39d2 XL |
2852 | let method = match self.lookup_method(rcvr_t, |
2853 | segment, | |
2854 | span, | |
7cac9316 XL |
2855 | expr, |
2856 | rcvr) { | |
1a4d82fc | 2857 | Ok(method) => { |
3b2f2976 | 2858 | self.write_method_call(expr.hir_id, method); |
7cac9316 | 2859 | Ok(method) |
1a4d82fc JJ |
2860 | } |
2861 | Err(error) => { | |
041b39d2 XL |
2862 | if segment.name != keywords::Invalid.name() { |
2863 | self.report_method_error(span, | |
2864 | rcvr_t, | |
2865 | segment.name, | |
32a655c1 SL |
2866 | Some(rcvr), |
2867 | error, | |
2868 | Some(args)); | |
7453a54e | 2869 | } |
7cac9316 | 2870 | Err(()) |
1a4d82fc JJ |
2871 | } |
2872 | }; | |
2873 | ||
2874 | // Call the generic checker. | |
abe05a73 XL |
2875 | self.check_method_argument_types(span, |
2876 | expr.span, | |
2877 | method, | |
7cac9316 XL |
2878 | &args[1..], |
2879 | DontTupleArguments, | |
2880 | expected) | |
1a4d82fc JJ |
2881 | } |
2882 | ||
cc61c64b XL |
2883 | fn check_return_expr(&self, return_expr: &'gcx hir::Expr) { |
2884 | let ret_coercion = | |
2885 | self.ret_coercion | |
2886 | .as_ref() | |
2887 | .unwrap_or_else(|| span_bug!(return_expr.span, | |
2888 | "check_return_expr called outside fn body")); | |
2889 | ||
2890 | let ret_ty = ret_coercion.borrow().expected_ty(); | |
041b39d2 | 2891 | let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); |
cc61c64b XL |
2892 | ret_coercion.borrow_mut() |
2893 | .coerce(self, | |
041b39d2 XL |
2894 | &self.cause(return_expr.span, |
2895 | ObligationCauseCode::ReturnType(return_expr.id)), | |
cc61c64b XL |
2896 | return_expr, |
2897 | return_expr_ty, | |
2898 | self.diverges.get()); | |
2899 | } | |
2900 | ||
2901 | ||
1a4d82fc JJ |
2902 | // A generic function for checking the then and else in an if |
2903 | // or if-else. | |
a7813a04 XL |
2904 | fn check_then_else(&self, |
2905 | cond_expr: &'gcx hir::Expr, | |
cc61c64b | 2906 | then_expr: &'gcx hir::Expr, |
a7813a04 | 2907 | opt_else_expr: Option<&'gcx hir::Expr>, |
a7813a04 | 2908 | sp: Span, |
9e0c209e | 2909 | expected: Expectation<'tcx>) -> Ty<'tcx> { |
041b39d2 | 2910 | let cond_ty = self.check_expr_meets_expectation_or_error(cond_expr, ExpectIfCondition); |
476ff2be SL |
2911 | let cond_diverges = self.diverges.get(); |
2912 | self.diverges.set(Diverges::Maybe); | |
a7813a04 XL |
2913 | |
2914 | let expected = expected.adjust_for_branches(self); | |
cc61c64b | 2915 | let then_ty = self.check_expr_with_expectation(then_expr, expected); |
476ff2be SL |
2916 | let then_diverges = self.diverges.get(); |
2917 | self.diverges.set(Diverges::Maybe); | |
a7813a04 | 2918 | |
cc61c64b XL |
2919 | // We've already taken the expected type's preferences |
2920 | // into account when typing the `then` branch. To figure | |
2921 | // out the initial shot at a LUB, we thus only consider | |
2922 | // `expected` if it represents a *hard* constraint | |
2923 | // (`only_has_type`); otherwise, we just go with a | |
2924 | // fresh type variable. | |
2925 | let coerce_to_ty = expected.coercion_target_type(self, sp); | |
2926 | let mut coerce: DynamicCoerceMany = CoerceMany::new(coerce_to_ty); | |
2927 | ||
2928 | let if_cause = self.cause(sp, ObligationCauseCode::IfExpression); | |
2929 | coerce.coerce(self, &if_cause, then_expr, then_ty, then_diverges); | |
2930 | ||
54a0048b | 2931 | if let Some(else_expr) = opt_else_expr { |
9e0c209e | 2932 | let else_ty = self.check_expr_with_expectation(else_expr, expected); |
476ff2be | 2933 | let else_diverges = self.diverges.get(); |
1a4d82fc | 2934 | |
cc61c64b | 2935 | coerce.coerce(self, &if_cause, else_expr, else_ty, else_diverges); |
476ff2be SL |
2936 | |
2937 | // We won't diverge unless both branches do (or the condition does). | |
2938 | self.diverges.set(cond_diverges | then_diverges & else_diverges); | |
1a4d82fc | 2939 | } else { |
cc61c64b | 2940 | let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse); |
7cac9316 | 2941 | coerce.coerce_forced_unit(self, &else_cause, &mut |_| (), true); |
cc61c64b | 2942 | |
476ff2be SL |
2943 | // If the condition is false we can't diverge. |
2944 | self.diverges.set(cond_diverges); | |
476ff2be | 2945 | } |
54a0048b | 2946 | |
cc61c64b XL |
2947 | let result_ty = coerce.complete(self); |
2948 | if cond_ty.references_error() { | |
2949 | self.tcx.types.err | |
2950 | } else { | |
2951 | result_ty | |
9e0c209e | 2952 | } |
1a4d82fc JJ |
2953 | } |
2954 | ||
1a4d82fc | 2955 | // Check field access expressions |
a7813a04 XL |
2956 | fn check_field(&self, |
2957 | expr: &'gcx hir::Expr, | |
2958 | lvalue_pref: LvaluePreference, | |
2959 | base: &'gcx hir::Expr, | |
9e0c209e SL |
2960 | field: &Spanned<ast::Name>) -> Ty<'tcx> { |
2961 | let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); | |
a7813a04 | 2962 | let expr_t = self.structurally_resolved_type(expr.span, |
9e0c209e | 2963 | expr_t); |
54a0048b | 2964 | let mut private_candidate = None; |
3157f602 | 2965 | let mut autoderef = self.autoderef(expr.span, expr_t); |
7cac9316 | 2966 | while let Some((base_t, _)) = autoderef.next() { |
9e0c209e SL |
2967 | match base_t.sty { |
2968 | ty::TyAdt(base_def, substs) if !base_def.is_enum() => { | |
2969 | debug!("struct named {:?}", base_t); | |
7cac9316 XL |
2970 | let (ident, def_scope) = |
2971 | self.tcx.adjust(field.node, base_def.did, self.body_id); | |
2972 | let fields = &base_def.struct_variant().fields; | |
2973 | if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { | |
9e0c209e | 2974 | let field_ty = self.field_ty(expr.span, field, substs); |
7cac9316 XL |
2975 | if field.vis.is_accessible_from(def_scope, self.tcx) { |
2976 | let adjustments = autoderef.adjust_steps(lvalue_pref); | |
2977 | self.apply_adjustments(base, adjustments); | |
2978 | autoderef.finalize(); | |
476ff2be SL |
2979 | |
2980 | self.tcx.check_stability(field.did, expr.id, expr.span); | |
2981 | ||
9e0c209e SL |
2982 | return field_ty; |
2983 | } | |
2984 | private_candidate = Some((base_def.did, field_ty)); | |
1a4d82fc | 2985 | } |
1a4d82fc | 2986 | } |
9e0c209e | 2987 | _ => {} |
1a4d82fc | 2988 | } |
1a4d82fc | 2989 | } |
3157f602 | 2990 | autoderef.unambiguous_final_ty(); |
1a4d82fc | 2991 | |
54a0048b | 2992 | if let Some((did, field_ty)) = private_candidate { |
a7813a04 | 2993 | let struct_path = self.tcx().item_path_str(did); |
041b39d2 XL |
2994 | let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616, |
2995 | "field `{}` of struct `{}` is private", | |
2996 | field.node, struct_path); | |
a7813a04 XL |
2997 | // Also check if an accessible method exists, which is often what is meant. |
2998 | if self.method_exists(field.span, field.node, expr_t, expr.id, false) { | |
2999 | err.note(&format!("a method `{}` also exists, perhaps you wish to call it", | |
3000 | field.node)); | |
3001 | } | |
3002 | err.emit(); | |
9e0c209e | 3003 | field_ty |
a7813a04 | 3004 | } else if field.node == keywords::Invalid.name() { |
9e0c209e | 3005 | self.tcx().types.err |
a7813a04 | 3006 | } else if self.method_exists(field.span, field.node, expr_t, expr.id, true) { |
041b39d2 XL |
3007 | type_error_struct!(self.tcx().sess, field.span, expr_t, E0615, |
3008 | "attempted to take value of method `{}` on type `{}`", | |
3009 | field.node, expr_t) | |
3b2f2976 | 3010 | .help("maybe a `()` to call it is missing?") |
9cc50fc6 | 3011 | .emit(); |
9e0c209e | 3012 | self.tcx().types.err |
1a4d82fc | 3013 | } else { |
041b39d2 XL |
3014 | if !expr_t.is_primitive_ty() { |
3015 | let mut err = self.no_such_field_err(field.span, &field.node, expr_t); | |
3016 | ||
3017 | match expr_t.sty { | |
3018 | ty::TyAdt(def, _) if !def.is_enum() => { | |
3019 | if let Some(suggested_field_name) = | |
3020 | Self::suggest_field_name(def.struct_variant(), field, vec![]) { | |
3021 | err.span_label(field.span, | |
3022 | format!("did you mean `{}`?", suggested_field_name)); | |
3023 | } else { | |
3024 | err.span_label(field.span, "unknown field"); | |
3b2f2976 XL |
3025 | let struct_variant_def = def.struct_variant(); |
3026 | let field_names = self.available_field_names(struct_variant_def); | |
3027 | if !field_names.is_empty() { | |
3028 | err.note(&format!("available fields are: {}", | |
3029 | self.name_series_display(field_names))); | |
3030 | } | |
041b39d2 XL |
3031 | }; |
3032 | } | |
3033 | ty::TyRawPtr(..) => { | |
3034 | err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \ | |
3035 | with `(*{0}).{1}`", | |
3036 | self.tcx.hir.node_to_pretty_string(base.id), | |
3037 | field.node)); | |
3038 | } | |
3039 | _ => {} | |
9e0c209e | 3040 | } |
041b39d2 XL |
3041 | err |
3042 | } else { | |
3043 | type_error_struct!(self.tcx().sess, field.span, expr_t, E0610, | |
3044 | "`{}` is a primitive type and therefore doesn't have fields", | |
3045 | expr_t) | |
3046 | }.emit(); | |
9e0c209e | 3047 | self.tcx().types.err |
1a4d82fc | 3048 | } |
1a4d82fc JJ |
3049 | } |
3050 | ||
9e0c209e | 3051 | // Return an hint about the closest match in field names |
476ff2be | 3052 | fn suggest_field_name(variant: &'tcx ty::VariantDef, |
9e0c209e | 3053 | field: &Spanned<ast::Name>, |
3b2f2976 | 3054 | skip: Vec<InternedString>) |
476ff2be | 3055 | -> Option<Symbol> { |
b039eaaf | 3056 | let name = field.node.as_str(); |
a7813a04 XL |
3057 | let names = variant.fields.iter().filter_map(|field| { |
3058 | // ignore already set fields and private fields from non-local crates | |
3059 | if skip.iter().any(|x| *x == field.name.as_str()) || | |
3060 | (variant.did.krate != LOCAL_CRATE && field.vis != Visibility::Public) { | |
3061 | None | |
3062 | } else { | |
3063 | Some(&field.name) | |
3064 | } | |
3065 | }); | |
9cc50fc6 | 3066 | |
3b2f2976 XL |
3067 | find_best_match_for_name(names, &name, None) |
3068 | } | |
3069 | ||
3070 | fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> { | |
3071 | let mut available = Vec::new(); | |
3072 | for field in variant.fields.iter() { | |
3073 | let (_, def_scope) = self.tcx.adjust(field.name, variant.did, self.body_id); | |
3074 | if field.vis.is_accessible_from(def_scope, self.tcx) { | |
3075 | available.push(field.name); | |
3076 | } | |
3077 | } | |
3078 | available | |
3079 | } | |
3080 | ||
3081 | fn name_series_display(&self, names: Vec<ast::Name>) -> String { | |
3082 | // dynamic limit, to never omit just one field | |
3083 | let limit = if names.len() == 6 { 6 } else { 5 }; | |
3084 | let mut display = names.iter().take(limit) | |
3085 | .map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", "); | |
3086 | if names.len() > limit { | |
3087 | display = format!("{} ... and {} others", display, names.len() - limit); | |
3088 | } | |
3089 | display | |
85aaf69f SL |
3090 | } |
3091 | ||
1a4d82fc | 3092 | // Check tuple index expressions |
a7813a04 XL |
3093 | fn check_tup_field(&self, |
3094 | expr: &'gcx hir::Expr, | |
3095 | lvalue_pref: LvaluePreference, | |
3096 | base: &'gcx hir::Expr, | |
9e0c209e SL |
3097 | idx: codemap::Spanned<usize>) -> Ty<'tcx> { |
3098 | let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); | |
a7813a04 | 3099 | let expr_t = self.structurally_resolved_type(expr.span, |
9e0c209e | 3100 | expr_t); |
54a0048b | 3101 | let mut private_candidate = None; |
1a4d82fc | 3102 | let mut tuple_like = false; |
3157f602 | 3103 | let mut autoderef = self.autoderef(expr.span, expr_t); |
7cac9316 | 3104 | while let Some((base_t, _)) = autoderef.next() { |
3157f602 | 3105 | let field = match base_t.sty { |
9e0c209e | 3106 | ty::TyAdt(base_def, substs) if base_def.is_struct() => { |
c30ab7b3 | 3107 | tuple_like = base_def.struct_variant().ctor_kind == CtorKind::Fn; |
3157f602 XL |
3108 | if !tuple_like { continue } |
3109 | ||
3110 | debug!("tuple struct named {:?}", base_t); | |
7cac9316 XL |
3111 | let ident = ast::Ident { |
3112 | name: Symbol::intern(&idx.node.to_string()), | |
ea8adc8c | 3113 | ctxt: idx.span.ctxt().modern(), |
7cac9316 XL |
3114 | }; |
3115 | let (ident, def_scope) = | |
3116 | self.tcx.adjust_ident(ident, base_def.did, self.body_id); | |
3117 | let fields = &base_def.struct_variant().fields; | |
3118 | if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { | |
3157f602 | 3119 | let field_ty = self.field_ty(expr.span, field, substs); |
7cac9316 | 3120 | if field.vis.is_accessible_from(def_scope, self.tcx) { |
476ff2be | 3121 | self.tcx.check_stability(field.did, expr.id, expr.span); |
3157f602 XL |
3122 | Some(field_ty) |
3123 | } else { | |
7cac9316 | 3124 | private_candidate = Some((base_def.did, field_ty)); |
3157f602 XL |
3125 | None |
3126 | } | |
7cac9316 XL |
3127 | } else { |
3128 | None | |
3129 | } | |
1a4d82fc | 3130 | } |
8bb4bdeb | 3131 | ty::TyTuple(ref v, _) => { |
3157f602 XL |
3132 | tuple_like = true; |
3133 | v.get(idx.node).cloned() | |
3134 | } | |
3135 | _ => continue | |
3136 | }; | |
3137 | ||
3138 | if let Some(field_ty) = field { | |
7cac9316 XL |
3139 | let adjustments = autoderef.adjust_steps(lvalue_pref); |
3140 | self.apply_adjustments(base, adjustments); | |
3141 | autoderef.finalize(); | |
9e0c209e | 3142 | return field_ty; |
1a4d82fc | 3143 | } |
1a4d82fc | 3144 | } |
3157f602 | 3145 | autoderef.unambiguous_final_ty(); |
54a0048b SL |
3146 | |
3147 | if let Some((did, field_ty)) = private_candidate { | |
a7813a04 | 3148 | let struct_path = self.tcx().item_path_str(did); |
041b39d2 XL |
3149 | struct_span_err!(self.tcx().sess, expr.span, E0611, |
3150 | "field `{}` of tuple-struct `{}` is private", | |
3151 | idx.node, struct_path).emit(); | |
9e0c209e | 3152 | return field_ty; |
54a0048b SL |
3153 | } |
3154 | ||
041b39d2 XL |
3155 | if tuple_like { |
3156 | type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612, | |
ea8adc8c XL |
3157 | "attempted out-of-bounds tuple index `{}` on type `{}`", |
3158 | idx.node, expr_t).emit(); | |
041b39d2 XL |
3159 | } else { |
3160 | self.no_such_field_err(expr.span, idx.node, expr_t).emit(); | |
3161 | } | |
1a4d82fc | 3162 | |
9e0c209e | 3163 | self.tcx().types.err |
1a4d82fc JJ |
3164 | } |
3165 | ||
041b39d2 XL |
3166 | fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS) |
3167 | -> DiagnosticBuilder { | |
3168 | type_error_struct!(self.tcx().sess, span, expr_t, E0609, | |
3169 | "no field `{}` on type `{}`", | |
3170 | field, expr_t) | |
3171 | } | |
3172 | ||
a7813a04 XL |
3173 | fn report_unknown_field(&self, |
3174 | ty: Ty<'tcx>, | |
476ff2be | 3175 | variant: &'tcx ty::VariantDef, |
a7813a04 | 3176 | field: &hir::Field, |
9e0c209e SL |
3177 | skip_fields: &[hir::Field], |
3178 | kind_name: &str) { | |
5bcae85e | 3179 | let mut err = self.type_error_struct_with_diag( |
b039eaaf | 3180 | field.name.span, |
9e0c209e SL |
3181 | |actual| match ty.sty { |
3182 | ty::TyAdt(adt, ..) if adt.is_enum() => { | |
3183 | struct_span_err!(self.tcx.sess, field.name.span, E0559, | |
3184 | "{} `{}::{}` has no field named `{}`", | |
476ff2be | 3185 | kind_name, actual, variant.name, field.name.node) |
9e0c209e SL |
3186 | } |
3187 | _ => { | |
3188 | struct_span_err!(self.tcx.sess, field.name.span, E0560, | |
3189 | "{} `{}` has no field named `{}`", | |
3190 | kind_name, actual, field.name.node) | |
3191 | } | |
e9174d1e | 3192 | }, |
5bcae85e | 3193 | ty); |
e9174d1e | 3194 | // prevent all specified fields from being suggested |
b039eaaf | 3195 | let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str()); |
9e0c209e SL |
3196 | if let Some(field_name) = Self::suggest_field_name(variant, |
3197 | &field.name, | |
3198 | skip_fields.collect()) { | |
3199 | err.span_label(field.name.span, | |
7cac9316 | 3200 | format!("field does not exist - did you mean `{}`?", field_name)); |
9e0c209e SL |
3201 | } else { |
3202 | match ty.sty { | |
3b2f2976 XL |
3203 | ty::TyAdt(adt, ..) => { |
3204 | if adt.is_enum() { | |
3205 | err.span_label(field.name.span, | |
3206 | format!("`{}::{}` does not have this field", | |
3207 | ty, variant.name)); | |
3208 | } else { | |
3209 | err.span_label(field.name.span, | |
3210 | format!("`{}` does not have this field", ty)); | |
3211 | } | |
3212 | let available_field_names = self.available_field_names(variant); | |
3213 | if !available_field_names.is_empty() { | |
3214 | err.note(&format!("available fields are: {}", | |
3215 | self.name_series_display(available_field_names))); | |
3216 | } | |
9e0c209e | 3217 | } |
3b2f2976 | 3218 | _ => bug!("non-ADT passed to report_unknown_field") |
9e0c209e SL |
3219 | } |
3220 | }; | |
9cc50fc6 | 3221 | err.emit(); |
e9174d1e SL |
3222 | } |
3223 | ||
a7813a04 XL |
3224 | fn check_expr_struct_fields(&self, |
3225 | adt_ty: Ty<'tcx>, | |
32a655c1 | 3226 | expected: Expectation<'tcx>, |
476ff2be | 3227 | expr_id: ast::NodeId, |
a7813a04 | 3228 | span: Span, |
476ff2be | 3229 | variant: &'tcx ty::VariantDef, |
a7813a04 XL |
3230 | ast_fields: &'gcx [hir::Field], |
3231 | check_completeness: bool) { | |
3232 | let tcx = self.tcx; | |
32a655c1 SL |
3233 | |
3234 | let adt_ty_hint = | |
3235 | self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) | |
ea8adc8c | 3236 | .get(0).cloned().unwrap_or(adt_ty); |
041b39d2 XL |
3237 | // re-link the regions that EIfEO can erase. |
3238 | self.demand_eqtype(span, adt_ty_hint, adt_ty); | |
32a655c1 | 3239 | |
041b39d2 XL |
3240 | let (substs, adt_kind, kind_name) = match &adt_ty.sty{ |
3241 | &ty::TyAdt(adt, substs) => { | |
3242 | (substs, adt.adt_kind(), adt.variant_descr()) | |
32a655c1 | 3243 | } |
54a0048b | 3244 | _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") |
e9174d1e | 3245 | }; |
1a4d82fc | 3246 | |
476ff2be | 3247 | let mut remaining_fields = FxHashMap(); |
e9174d1e | 3248 | for field in &variant.fields { |
7cac9316 | 3249 | remaining_fields.insert(field.name.to_ident(), field); |
1a4d82fc JJ |
3250 | } |
3251 | ||
476ff2be | 3252 | let mut seen_fields = FxHashMap(); |
5bcae85e | 3253 | |
1a4d82fc JJ |
3254 | let mut error_happened = false; |
3255 | ||
3256 | // Typecheck each field. | |
85aaf69f | 3257 | for field in ast_fields { |
7cac9316 | 3258 | let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0; |
041b39d2 | 3259 | let field_type = if let Some(v_field) = remaining_fields.remove(&ident) { |
5bcae85e | 3260 | seen_fields.insert(field.name.node, field.span); |
476ff2be SL |
3261 | |
3262 | // we don't look at stability attributes on | |
3263 | // struct-like enums (yet...), but it's definitely not | |
3264 | // a bug to have construct one. | |
3265 | if adt_kind != ty::AdtKind::Enum { | |
3266 | tcx.check_stability(v_field.did, expr_id, field.span); | |
3267 | } | |
041b39d2 XL |
3268 | |
3269 | self.field_ty(field.span, v_field, substs) | |
e9174d1e SL |
3270 | } else { |
3271 | error_happened = true; | |
b039eaaf | 3272 | if let Some(_) = variant.find_field_named(field.name.node) { |
5bcae85e | 3273 | let mut err = struct_span_err!(self.tcx.sess, |
ea8adc8c XL |
3274 | field.name.span, |
3275 | E0062, | |
3276 | "field `{}` specified more than once", | |
3277 | field.name.node); | |
5bcae85e | 3278 | |
7cac9316 | 3279 | err.span_label(field.name.span, "used more than once"); |
5bcae85e SL |
3280 | |
3281 | if let Some(prev_span) = seen_fields.get(&field.name.node) { | |
7cac9316 | 3282 | err.span_label(*prev_span, format!("first use of `{}`", field.name.node)); |
5bcae85e SL |
3283 | } |
3284 | ||
3285 | err.emit(); | |
e9174d1e | 3286 | } else { |
9e0c209e | 3287 | self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); |
1a4d82fc | 3288 | } |
041b39d2 XL |
3289 | |
3290 | tcx.types.err | |
3291 | }; | |
1a4d82fc JJ |
3292 | |
3293 | // Make sure to give a type to the field even if there's | |
3294 | // an error, so we can continue typechecking | |
041b39d2 | 3295 | self.check_expr_coercable_to_type(&field.expr, field_type); |
1a4d82fc JJ |
3296 | } |
3297 | ||
9e0c209e SL |
3298 | // Make sure the programmer specified correct number of fields. |
3299 | if kind_name == "union" { | |
3300 | if ast_fields.len() != 1 { | |
3301 | tcx.sess.span_err(span, "union expressions should have exactly one field"); | |
3302 | } | |
3303 | } else if check_completeness && !error_happened && !remaining_fields.is_empty() { | |
3304 | let len = remaining_fields.len(); | |
3305 | ||
3306 | let mut displayable_field_names = remaining_fields | |
3307 | .keys() | |
7cac9316 | 3308 | .map(|ident| ident.name.as_str()) |
9e0c209e SL |
3309 | .collect::<Vec<_>>(); |
3310 | ||
3311 | displayable_field_names.sort(); | |
3312 | ||
3313 | let truncated_fields_error = if len <= 3 { | |
3314 | "".to_string() | |
3315 | } else { | |
3316 | format!(" and {} other field{}", (len - 3), if len - 3 == 1 {""} else {"s"}) | |
3317 | }; | |
1a4d82fc | 3318 | |
9e0c209e SL |
3319 | let remaining_fields_names = displayable_field_names.iter().take(3) |
3320 | .map(|n| format!("`{}`", n)) | |
3321 | .collect::<Vec<_>>() | |
3322 | .join(", "); | |
3323 | ||
3324 | struct_span_err!(tcx.sess, span, E0063, | |
041b39d2 XL |
3325 | "missing field{} {}{} in initializer of `{}`", |
3326 | if remaining_fields.len() == 1 { "" } else { "s" }, | |
3327 | remaining_fields_names, | |
3328 | truncated_fields_error, | |
3329 | adt_ty) | |
ea8adc8c XL |
3330 | .span_label(span, format!("missing {}{}", |
3331 | remaining_fields_names, | |
3332 | truncated_fields_error)) | |
3333 | .emit(); | |
9e0c209e | 3334 | } |
1a4d82fc JJ |
3335 | } |
3336 | ||
a7813a04 | 3337 | fn check_struct_fields_on_error(&self, |
a7813a04 XL |
3338 | fields: &'gcx [hir::Field], |
3339 | base_expr: &'gcx Option<P<hir::Expr>>) { | |
85aaf69f | 3340 | for field in fields { |
a7813a04 | 3341 | self.check_expr(&field.expr); |
1a4d82fc JJ |
3342 | } |
3343 | match *base_expr { | |
9e0c209e SL |
3344 | Some(ref base) => { |
3345 | self.check_expr(&base); | |
3346 | }, | |
1a4d82fc JJ |
3347 | None => {} |
3348 | } | |
3349 | } | |
3350 | ||
5bcae85e | 3351 | pub fn check_struct_path(&self, |
476ff2be | 3352 | qpath: &hir::QPath, |
c30ab7b3 | 3353 | node_id: ast::NodeId) |
476ff2be SL |
3354 | -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { |
3355 | let path_span = match *qpath { | |
3356 | hir::QPath::Resolved(_, ref path) => path.span, | |
3357 | hir::QPath::TypeRelative(ref qself, _) => qself.span | |
3358 | }; | |
3359 | let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, node_id); | |
5bcae85e SL |
3360 | let variant = match def { |
3361 | Def::Err => { | |
3362 | self.set_tainted_by_errors(); | |
3363 | return None; | |
3364 | } | |
c30ab7b3 SL |
3365 | Def::Variant(..) => { |
3366 | match ty.sty { | |
3367 | ty::TyAdt(adt, substs) => { | |
3368 | Some((adt.variant_of_def(def), adt.did, substs)) | |
3369 | } | |
3370 | _ => bug!("unexpected type: {:?}", ty.sty) | |
3371 | } | |
9e0c209e | 3372 | } |
c30ab7b3 SL |
3373 | Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | |
3374 | Def::AssociatedTy(..) | Def::SelfTy(..) => { | |
c30ab7b3 SL |
3375 | match ty.sty { |
3376 | ty::TyAdt(adt, substs) if !adt.is_enum() => { | |
3377 | Some((adt.struct_variant(), adt.did, substs)) | |
9e0c209e SL |
3378 | } |
3379 | _ => None, | |
5bcae85e SL |
3380 | } |
3381 | } | |
c30ab7b3 | 3382 | _ => bug!("unexpected definition: {:?}", def) |
5bcae85e SL |
3383 | }; |
3384 | ||
c30ab7b3 | 3385 | if let Some((variant, did, substs)) = variant { |
c30ab7b3 | 3386 | // Check bounds on type arguments used in the path. |
476ff2be SL |
3387 | let bounds = self.instantiate_bounds(path_span, did, substs); |
3388 | let cause = traits::ObligationCause::new(path_span, self.body_id, | |
c30ab7b3 SL |
3389 | traits::ItemObligation(did)); |
3390 | self.add_obligations_for_parameters(cause, &bounds); | |
3391 | ||
5bcae85e SL |
3392 | Some((variant, ty)) |
3393 | } else { | |
476ff2be | 3394 | struct_span_err!(self.tcx.sess, path_span, E0071, |
c30ab7b3 SL |
3395 | "expected struct, variant or union type, found {}", |
3396 | ty.sort_string(self.tcx)) | |
7cac9316 | 3397 | .span_label(path_span, "not a struct") |
5bcae85e SL |
3398 | .emit(); |
3399 | None | |
3400 | } | |
3401 | } | |
3402 | ||
a7813a04 XL |
3403 | fn check_expr_struct(&self, |
3404 | expr: &hir::Expr, | |
32a655c1 | 3405 | expected: Expectation<'tcx>, |
476ff2be | 3406 | qpath: &hir::QPath, |
a7813a04 | 3407 | fields: &'gcx [hir::Field], |
9e0c209e | 3408 | base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx> |
e9174d1e | 3409 | { |
e9174d1e | 3410 | // Find the relevant variant |
476ff2be SL |
3411 | let (variant, struct_ty) = |
3412 | if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) { | |
5bcae85e SL |
3413 | variant_ty |
3414 | } else { | |
9e0c209e | 3415 | self.check_struct_fields_on_error(fields, base_expr); |
c30ab7b3 | 3416 | return self.tcx.types.err; |
e9174d1e SL |
3417 | }; |
3418 | ||
476ff2be SL |
3419 | let path_span = match *qpath { |
3420 | hir::QPath::Resolved(_, ref path) => path.span, | |
3421 | hir::QPath::TypeRelative(ref qself, _) => qself.span | |
3422 | }; | |
3423 | ||
abe05a73 XL |
3424 | // Prohibit struct expressions when non exhaustive flag is set. |
3425 | if let ty::TyAdt(adt, _) = struct_ty.sty { | |
3426 | if !adt.did.is_local() && adt.is_non_exhaustive() { | |
3427 | span_err!(self.tcx.sess, expr.span, E0639, | |
3428 | "cannot create non-exhaustive {} using struct expression", | |
3429 | adt.variant_descr()); | |
3430 | } | |
3431 | } | |
3432 | ||
32a655c1 | 3433 | self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields, |
a7813a04 | 3434 | base_expr.is_none()); |
e9174d1e | 3435 | if let &Some(ref base_expr) = base_expr { |
041b39d2 | 3436 | self.check_expr_has_type_or_error(base_expr, struct_ty); |
9e0c209e SL |
3437 | match struct_ty.sty { |
3438 | ty::TyAdt(adt, substs) if adt.is_struct() => { | |
041b39d2 XL |
3439 | let fru_field_types = adt.struct_variant().fields.iter().map(|f| { |
3440 | self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) | |
3441 | }).collect(); | |
3b2f2976 XL |
3442 | |
3443 | self.tables | |
3444 | .borrow_mut() | |
3445 | .fru_field_types_mut() | |
3446 | .insert(expr.hir_id, fru_field_types); | |
7453a54e SL |
3447 | } |
3448 | _ => { | |
5bcae85e | 3449 | span_err!(self.tcx.sess, base_expr.span, E0436, |
7453a54e SL |
3450 | "functional record update syntax requires a struct"); |
3451 | } | |
e9174d1e SL |
3452 | } |
3453 | } | |
9e0c209e SL |
3454 | self.require_type_is_sized(struct_ty, expr.span, traits::StructInitializerSized); |
3455 | struct_ty | |
e9174d1e SL |
3456 | } |
3457 | ||
1a4d82fc | 3458 | |
a7813a04 XL |
3459 | /// Invariant: |
3460 | /// If an expression has any sub-expressions that result in a type error, | |
3461 | /// inspecting that expression's type with `ty.references_error()` will return | |
3462 | /// true. Likewise, if an expression is known to diverge, inspecting its | |
3463 | /// type with `ty::type_is_bot` will return true (n.b.: since Rust is | |
3464 | /// strict, _|_ can appear in the type of an expression that does not, | |
3465 | /// itself, diverge: for example, fn() -> _|_.) | |
3466 | /// Note that inspecting a type's structure *directly* may expose the fact | |
3467 | /// that there are actually multiple representations for `TyError`, so avoid | |
3468 | /// that when err needs to be handled differently. | |
3469 | fn check_expr_with_expectation_and_lvalue_pref(&self, | |
3470 | expr: &'gcx hir::Expr, | |
3471 | expected: Expectation<'tcx>, | |
9e0c209e | 3472 | lvalue_pref: LvaluePreference) -> Ty<'tcx> { |
a7813a04 XL |
3473 | debug!(">> typechecking: expr={:?} expected={:?}", |
3474 | expr, expected); | |
476ff2be SL |
3475 | |
3476 | // Warn for expressions after diverging siblings. | |
3477 | self.warn_if_unreachable(expr.id, expr.span, "expression"); | |
3478 | ||
3479 | // Hide the outer diverging and has_errors flags. | |
3480 | let old_diverges = self.diverges.get(); | |
3481 | let old_has_errors = self.has_errors.get(); | |
3482 | self.diverges.set(Diverges::Maybe); | |
3483 | self.has_errors.set(false); | |
3484 | ||
9e0c209e | 3485 | let ty = self.check_expr_kind(expr, expected, lvalue_pref); |
a7813a04 | 3486 | |
476ff2be SL |
3487 | // Warn for non-block expressions with diverging children. |
3488 | match expr.node { | |
3489 | hir::ExprBlock(_) | | |
3490 | hir::ExprLoop(..) | hir::ExprWhile(..) | | |
3491 | hir::ExprIf(..) | hir::ExprMatch(..) => {} | |
3492 | ||
3493 | _ => self.warn_if_unreachable(expr.id, expr.span, "expression") | |
3494 | } | |
3495 | ||
cc61c64b XL |
3496 | // Any expression that produces a value of type `!` must have diverged |
3497 | if ty.is_never() { | |
3498 | self.diverges.set(self.diverges.get() | Diverges::Always); | |
3499 | } | |
3500 | ||
476ff2be SL |
3501 | // Record the type, which applies it effects. |
3502 | // We need to do this after the warning above, so that | |
3503 | // we don't warn for the diverging expression itself. | |
3b2f2976 | 3504 | self.write_ty(expr.hir_id, ty); |
9e0c209e | 3505 | |
476ff2be SL |
3506 | // Combine the diverging and has_error flags. |
3507 | self.diverges.set(self.diverges.get() | old_diverges); | |
3508 | self.has_errors.set(self.has_errors.get() | old_has_errors); | |
3509 | ||
32a655c1 SL |
3510 | debug!("type of {} is...", self.tcx.hir.node_to_string(expr.id)); |
3511 | debug!("... {:?}, expected is {:?}", ty, expected); | |
9e0c209e | 3512 | |
9e0c209e SL |
3513 | ty |
3514 | } | |
3515 | ||
3516 | fn check_expr_kind(&self, | |
3517 | expr: &'gcx hir::Expr, | |
3518 | expected: Expectation<'tcx>, | |
3519 | lvalue_pref: LvaluePreference) -> Ty<'tcx> { | |
a7813a04 XL |
3520 | let tcx = self.tcx; |
3521 | let id = expr.id; | |
3522 | match expr.node { | |
3523 | hir::ExprBox(ref subexpr) => { | |
3524 | let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| { | |
3525 | match ty.sty { | |
32a655c1 SL |
3526 | ty::TyAdt(def, _) if def.is_box() |
3527 | => Expectation::rvalue_hint(self, ty.boxed_ty()), | |
a7813a04 XL |
3528 | _ => NoExpectation |
3529 | } | |
3530 | }); | |
9e0c209e SL |
3531 | let referent_ty = self.check_expr_with_expectation(subexpr, expected_inner); |
3532 | tcx.mk_box(referent_ty) | |
a7813a04 | 3533 | } |
1a4d82fc | 3534 | |
a7813a04 | 3535 | hir::ExprLit(ref lit) => { |
9e0c209e | 3536 | self.check_lit(&lit, expected) |
a7813a04 XL |
3537 | } |
3538 | hir::ExprBinary(op, ref lhs, ref rhs) => { | |
9e0c209e | 3539 | self.check_binop(expr, op, lhs, rhs) |
a7813a04 XL |
3540 | } |
3541 | hir::ExprAssignOp(op, ref lhs, ref rhs) => { | |
9e0c209e | 3542 | self.check_binop_assign(expr, op, lhs, rhs) |
a7813a04 XL |
3543 | } |
3544 | hir::ExprUnary(unop, ref oprnd) => { | |
3545 | let expected_inner = match unop { | |
3546 | hir::UnNot | hir::UnNeg => { | |
3547 | expected | |
3548 | } | |
e9174d1e | 3549 | hir::UnDeref => { |
a7813a04 | 3550 | NoExpectation |
1a4d82fc | 3551 | } |
a7813a04 XL |
3552 | }; |
3553 | let lvalue_pref = match unop { | |
3554 | hir::UnDeref => lvalue_pref, | |
3555 | _ => NoPreference | |
3556 | }; | |
9e0c209e SL |
3557 | let mut oprnd_t = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, |
3558 | expected_inner, | |
3559 | lvalue_pref); | |
a7813a04 XL |
3560 | |
3561 | if !oprnd_t.references_error() { | |
7cac9316 | 3562 | oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); |
a7813a04 XL |
3563 | match unop { |
3564 | hir::UnDeref => { | |
a7813a04 XL |
3565 | if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) { |
3566 | oprnd_t = mt.ty; | |
cc61c64b | 3567 | } else if let Some(ok) = self.try_overloaded_deref( |
7cac9316 | 3568 | expr.span, oprnd_t, lvalue_pref) { |
cc61c64b | 3569 | let method = self.register_infer_ok_obligations(ok); |
7cac9316 XL |
3570 | if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { |
3571 | self.apply_adjustments(oprnd, vec![Adjustment { | |
3572 | kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), | |
3573 | target: method.sig.inputs()[0] | |
3574 | }]); | |
3575 | } | |
a7813a04 | 3576 | oprnd_t = self.make_overloaded_lvalue_return_type(method).ty; |
3b2f2976 | 3577 | self.write_method_call(expr.hir_id, method); |
a7813a04 | 3578 | } else { |
041b39d2 XL |
3579 | type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, |
3580 | "type `{}` cannot be dereferenced", | |
3581 | oprnd_t).emit(); | |
a7813a04 XL |
3582 | oprnd_t = tcx.types.err; |
3583 | } | |
1a4d82fc | 3584 | } |
a7813a04 | 3585 | hir::UnNot => { |
7cac9316 | 3586 | let result = self.check_user_unop(expr, oprnd_t, unop); |
32a655c1 | 3587 | // If it's builtin, we can reuse the type, this helps inference. |
a7813a04 | 3588 | if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) { |
32a655c1 | 3589 | oprnd_t = result; |
a7813a04 | 3590 | } |
c34b1796 | 3591 | } |
a7813a04 | 3592 | hir::UnNeg => { |
7cac9316 | 3593 | let result = self.check_user_unop(expr, oprnd_t, unop); |
32a655c1 | 3594 | // If it's builtin, we can reuse the type, this helps inference. |
a7813a04 | 3595 | if !(oprnd_t.is_integral() || oprnd_t.is_fp()) { |
32a655c1 | 3596 | oprnd_t = result; |
a7813a04 | 3597 | } |
1a4d82fc JJ |
3598 | } |
3599 | } | |
1a4d82fc | 3600 | } |
9e0c209e | 3601 | oprnd_t |
a7813a04 XL |
3602 | } |
3603 | hir::ExprAddrOf(mutbl, ref oprnd) => { | |
3604 | let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { | |
3605 | match ty.sty { | |
3606 | ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => { | |
3607 | if self.tcx.expr_is_lval(&oprnd) { | |
3608 | // Lvalues may legitimately have unsized types. | |
3609 | // For example, dereferences of a fat pointer and | |
3610 | // the last field of a struct can be unsized. | |
3611 | ExpectHasType(mt.ty) | |
3612 | } else { | |
3613 | Expectation::rvalue_hint(self, mt.ty) | |
3614 | } | |
3615 | } | |
3616 | _ => NoExpectation | |
c34b1796 | 3617 | } |
a7813a04 XL |
3618 | }); |
3619 | let lvalue_pref = LvaluePreference::from_mutbl(mutbl); | |
9e0c209e | 3620 | let ty = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref); |
a7813a04 | 3621 | |
9e0c209e SL |
3622 | let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; |
3623 | if tm.ty.references_error() { | |
a7813a04 | 3624 | tcx.types.err |
c34b1796 | 3625 | } else { |
a7813a04 XL |
3626 | // Note: at this point, we cannot say what the best lifetime |
3627 | // is to use for resulting pointer. We want to use the | |
3628 | // shortest lifetime possible so as to avoid spurious borrowck | |
3629 | // errors. Moreover, the longest lifetime will depend on the | |
3630 | // precise details of the value whose address is being taken | |
3631 | // (and how long it is valid), which we don't know yet until type | |
3632 | // inference is complete. | |
3633 | // | |
3634 | // Therefore, here we simply generate a region variable. The | |
3635 | // region inferencer will then select the ultimate value. | |
3636 | // Finally, borrowck is charged with guaranteeing that the | |
3637 | // value whose address was taken can actually be made to live | |
3638 | // as long as it needs to live. | |
3639 | let region = self.next_region_var(infer::AddrOfRegion(expr.span)); | |
9e0c209e SL |
3640 | tcx.mk_ref(region, tm) |
3641 | } | |
c34b1796 | 3642 | } |
476ff2be SL |
3643 | hir::ExprPath(ref qpath) => { |
3644 | let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, | |
5bcae85e | 3645 | expr.id, expr.span); |
9e0c209e SL |
3646 | let ty = if def != Def::Err { |
3647 | self.instantiate_value_path(segments, opt_ty, def, expr.span, id) | |
5bcae85e SL |
3648 | } else { |
3649 | self.set_tainted_by_errors(); | |
9e0c209e SL |
3650 | tcx.types.err |
3651 | }; | |
1a4d82fc | 3652 | |
a7813a04 XL |
3653 | // We always require that the type provided as the value for |
3654 | // a type parameter outlives the moment of instantiation. | |
3b2f2976 | 3655 | let substs = self.tables.borrow().node_substs(expr.hir_id); |
7cac9316 | 3656 | self.add_wf_bounds(substs, expr); |
9e0c209e SL |
3657 | |
3658 | ty | |
1a4d82fc | 3659 | } |
a7813a04 XL |
3660 | hir::ExprInlineAsm(_, ref outputs, ref inputs) => { |
3661 | for output in outputs { | |
3662 | self.check_expr(output); | |
3663 | } | |
3664 | for input in inputs { | |
3665 | self.check_expr(input); | |
3666 | } | |
9e0c209e | 3667 | tcx.mk_nil() |
1a4d82fc | 3668 | } |
cc61c64b XL |
3669 | hir::ExprBreak(destination, ref expr_opt) => { |
3670 | if let Some(target_id) = destination.target_id.opt_id() { | |
3671 | let (e_ty, e_diverges, cause); | |
3672 | if let Some(ref e) = *expr_opt { | |
3673 | // If this is a break with a value, we need to type-check | |
3674 | // the expression. Get an expected type from the loop context. | |
3675 | let opt_coerce_to = { | |
3676 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
3677 | enclosing_breakables.find_breakable(target_id) | |
3678 | .coerce | |
3679 | .as_ref() | |
3680 | .map(|coerce| coerce.expected_ty()) | |
3681 | }; | |
3682 | ||
3683 | // If the loop context is not a `loop { }`, then break with | |
3684 | // a value is illegal, and `opt_coerce_to` will be `None`. | |
3685 | // Just set expectation to error in that case. | |
3686 | let coerce_to = opt_coerce_to.unwrap_or(tcx.types.err); | |
3687 | ||
3688 | // Recurse without `enclosing_breakables` borrowed. | |
3689 | e_ty = self.check_expr_with_hint(e, coerce_to); | |
3690 | e_diverges = self.diverges.get(); | |
3691 | cause = self.misc(e.span); | |
3692 | } else { | |
3693 | // Otherwise, this is a break *without* a value. That's | |
3694 | // always legal, and is equivalent to `break ()`. | |
3695 | e_ty = tcx.mk_nil(); | |
3696 | e_diverges = Diverges::Maybe; | |
3697 | cause = self.misc(expr.span); | |
3698 | } | |
476ff2be | 3699 | |
cc61c64b XL |
3700 | // Now that we have type-checked `expr_opt`, borrow |
3701 | // the `enclosing_loops` field and let's coerce the | |
3702 | // type of `expr_opt` into what is expected. | |
3703 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
3704 | let ctxt = enclosing_breakables.find_breakable(target_id); | |
3705 | if let Some(ref mut coerce) = ctxt.coerce { | |
3706 | if let Some(ref e) = *expr_opt { | |
3707 | coerce.coerce(self, &cause, e, e_ty, e_diverges); | |
3708 | } else { | |
3709 | assert!(e_ty.is_nil()); | |
7cac9316 | 3710 | coerce.coerce_forced_unit(self, &cause, &mut |_| (), true); |
cc61c64b XL |
3711 | } |
3712 | } else { | |
3713 | // If `ctxt.coerce` is `None`, we can just ignore | |
3714 | // the type of the expresison. This is because | |
3715 | // either this was a break *without* a value, in | |
3716 | // which case it is always a legal type (`()`), or | |
3717 | // else an error would have been flagged by the | |
3718 | // `loops` pass for using break with an expression | |
3719 | // where you are not supposed to. | |
3720 | assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0); | |
3721 | } | |
476ff2be | 3722 | |
cc61c64b XL |
3723 | ctxt.may_break = true; |
3724 | } else { | |
3725 | // Otherwise, we failed to find the enclosing loop; | |
3726 | // this can only happen if the `break` was not | |
3727 | // inside a loop at all, which is caught by the | |
3728 | // loop-checking pass. | |
3729 | assert!(self.tcx.sess.err_count() > 0); | |
3b2f2976 XL |
3730 | |
3731 | // We still need to assign a type to the inner expression to | |
3732 | // prevent the ICE in #43162. | |
3733 | if let Some(ref e) = *expr_opt { | |
3734 | self.check_expr_with_hint(e, tcx.types.err); | |
3735 | ||
3736 | // ... except when we try to 'break rust;'. | |
3737 | // ICE this expression in particular (see #43162). | |
3738 | if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = e.node { | |
3739 | if path.segments.len() == 1 && path.segments[0].name == "rust" { | |
3740 | fatally_break_rust(self.tcx.sess); | |
3741 | } | |
3742 | } | |
3743 | } | |
cc61c64b | 3744 | } |
476ff2be | 3745 | |
cc61c64b XL |
3746 | // the type of a `break` is always `!`, since it diverges |
3747 | tcx.types.never | |
476ff2be | 3748 | } |
9e0c209e | 3749 | hir::ExprAgain(_) => { tcx.types.never } |
a7813a04 | 3750 | hir::ExprRet(ref expr_opt) => { |
cc61c64b | 3751 | if self.ret_coercion.is_none() { |
476ff2be SL |
3752 | struct_span_err!(self.tcx.sess, expr.span, E0572, |
3753 | "return statement outside of function body").emit(); | |
3754 | } else if let Some(ref e) = *expr_opt { | |
cc61c64b | 3755 | self.check_return_expr(e); |
5bcae85e | 3756 | } else { |
cc61c64b XL |
3757 | let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); |
3758 | let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); | |
7cac9316 | 3759 | coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); |
1a4d82fc | 3760 | } |
9e0c209e | 3761 | tcx.types.never |
a7813a04 XL |
3762 | } |
3763 | hir::ExprAssign(ref lhs, ref rhs) => { | |
9e0c209e | 3764 | let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); |
1a4d82fc | 3765 | |
9e0c209e | 3766 | let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); |
1a4d82fc | 3767 | |
041b39d2 XL |
3768 | match expected { |
3769 | ExpectIfCondition => { | |
3770 | self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\ | |
3771 | expected error elsehwere"); | |
3772 | } | |
3773 | _ => { | |
3774 | // Only check this if not in an `if` condition, as the | |
3775 | // mistyped comparison help is more appropriate. | |
3776 | if !self.tcx.expr_is_lval(&lhs) { | |
ea8adc8c XL |
3777 | struct_span_err!(self.tcx.sess, expr.span, E0070, |
3778 | "invalid left-hand side expression") | |
3779 | .span_label(expr.span, "left-hand of expression not valid") | |
3780 | .emit(); | |
041b39d2 XL |
3781 | } |
3782 | } | |
3783 | } | |
3784 | ||
9e0c209e | 3785 | self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); |
e9174d1e | 3786 | |
a7813a04 | 3787 | if lhs_ty.references_error() || rhs_ty.references_error() { |
9e0c209e | 3788 | tcx.types.err |
a7813a04 | 3789 | } else { |
9e0c209e | 3790 | tcx.mk_nil() |
a7813a04 | 3791 | } |
e9174d1e | 3792 | } |
cc61c64b XL |
3793 | hir::ExprIf(ref cond, ref then_expr, ref opt_else_expr) => { |
3794 | self.check_then_else(&cond, then_expr, opt_else_expr.as_ref().map(|e| &**e), | |
3795 | expr.span, expected) | |
a7813a04 XL |
3796 | } |
3797 | hir::ExprWhile(ref cond, ref body, _) => { | |
cc61c64b XL |
3798 | let ctxt = BreakableCtxt { |
3799 | // cannot use break with a value from a while loop | |
3800 | coerce: None, | |
3801 | may_break: true, | |
3802 | }; | |
476ff2be | 3803 | |
cc61c64b | 3804 | self.with_breakable_ctxt(expr.id, ctxt, || { |
041b39d2 | 3805 | self.check_expr_has_type_or_error(&cond, tcx.types.bool); |
cc61c64b XL |
3806 | let cond_diverging = self.diverges.get(); |
3807 | self.check_block_no_value(&body); | |
476ff2be | 3808 | |
cc61c64b XL |
3809 | // We may never reach the body so it diverging means nothing. |
3810 | self.diverges.set(cond_diverging); | |
3811 | }); | |
3812 | ||
3813 | self.tcx.mk_nil() | |
a7813a04 | 3814 | } |
cc61c64b XL |
3815 | hir::ExprLoop(ref body, _, source) => { |
3816 | let coerce = match source { | |
3817 | // you can only use break with a value from a normal `loop { }` | |
3818 | hir::LoopSource::Loop => { | |
3819 | let coerce_to = expected.coercion_target_type(self, body.span); | |
3820 | Some(CoerceMany::new(coerce_to)) | |
3821 | } | |
476ff2be | 3822 | |
cc61c64b XL |
3823 | hir::LoopSource::WhileLet | |
3824 | hir::LoopSource::ForLoop => { | |
3825 | None | |
3826 | } | |
3827 | }; | |
476ff2be | 3828 | |
cc61c64b | 3829 | let ctxt = BreakableCtxt { |
3b2f2976 | 3830 | coerce, |
cc61c64b XL |
3831 | may_break: false, // will get updated if/when we find a `break` |
3832 | }; | |
3833 | ||
3834 | let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || { | |
3835 | self.check_block_no_value(&body); | |
3836 | }); | |
3837 | ||
3838 | if ctxt.may_break { | |
3839 | // No way to know whether it's diverging because | |
3840 | // of a `break` or an outer `break` or `return. | |
3841 | self.diverges.set(Diverges::Maybe); | |
3842 | } | |
3843 | ||
3844 | // If we permit break with a value, then result type is | |
3845 | // the LUB of the breaks (possibly ! if none); else, it | |
3846 | // is nil. This makes sense because infinite loops | |
3847 | // (which would have type !) are only possible iff we | |
3848 | // permit break with a value [1]. | |
3849 | assert!(ctxt.coerce.is_some() || ctxt.may_break); // [1] | |
3850 | ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil()) | |
a7813a04 XL |
3851 | } |
3852 | hir::ExprMatch(ref discrim, ref arms, match_src) => { | |
9e0c209e | 3853 | self.check_match(expr, &discrim, arms, expected, match_src) |
a7813a04 | 3854 | } |
ea8adc8c | 3855 | hir::ExprClosure(capture, ref decl, body_id, _, _) => { |
476ff2be | 3856 | self.check_expr_closure(expr, capture, &decl, body_id, expected) |
a7813a04 | 3857 | } |
cc61c64b XL |
3858 | hir::ExprBlock(ref body) => { |
3859 | self.check_block_with_expected(&body, expected) | |
a7813a04 XL |
3860 | } |
3861 | hir::ExprCall(ref callee, ref args) => { | |
476ff2be | 3862 | self.check_call(expr, &callee, args, expected) |
a7813a04 | 3863 | } |
041b39d2 XL |
3864 | hir::ExprMethodCall(ref segment, span, ref args) => { |
3865 | self.check_method_call(expr, segment, span, args, expected, lvalue_pref) | |
a7813a04 XL |
3866 | } |
3867 | hir::ExprCast(ref e, ref t) => { | |
a7813a04 XL |
3868 | // Find the type of `e`. Supply hints based on the type we are casting to, |
3869 | // if appropriate. | |
3870 | let t_cast = self.to_ty(t); | |
3871 | let t_cast = self.resolve_type_vars_if_possible(&t_cast); | |
9e0c209e | 3872 | let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); |
a7813a04 | 3873 | let t_cast = self.resolve_type_vars_if_possible(&t_cast); |
cc61c64b | 3874 | let diverges = self.diverges.get(); |
a7813a04 XL |
3875 | |
3876 | // Eagerly check for some obvious errors. | |
3877 | if t_expr.references_error() || t_cast.references_error() { | |
9e0c209e | 3878 | tcx.types.err |
54a0048b | 3879 | } else { |
a7813a04 XL |
3880 | // Defer other checks until we're done type checking. |
3881 | let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); | |
cc61c64b | 3882 | match cast::CastCheck::new(self, e, t_expr, diverges, t_cast, t.span, expr.span) { |
a7813a04 XL |
3883 | Ok(cast_check) => { |
3884 | deferred_cast_checks.push(cast_check); | |
9e0c209e | 3885 | t_cast |
a7813a04 XL |
3886 | } |
3887 | Err(ErrorReported) => { | |
9e0c209e | 3888 | tcx.types.err |
a7813a04 | 3889 | } |
1a4d82fc | 3890 | } |
1a4d82fc | 3891 | } |
a7813a04 XL |
3892 | } |
3893 | hir::ExprType(ref e, ref t) => { | |
3894 | let typ = self.to_ty(&t); | |
3895 | self.check_expr_eq_type(&e, typ); | |
9e0c209e | 3896 | typ |
a7813a04 | 3897 | } |
c30ab7b3 | 3898 | hir::ExprArray(ref args) => { |
cc61c64b XL |
3899 | let uty = expected.to_option(self).and_then(|uty| { |
3900 | match uty.sty { | |
3901 | ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty), | |
3902 | _ => None | |
3903 | } | |
3904 | }); | |
a7813a04 | 3905 | |
cc61c64b XL |
3906 | let element_ty = if !args.is_empty() { |
3907 | let coerce_to = uty.unwrap_or_else( | |
3908 | || self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))); | |
3909 | let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); | |
3910 | assert_eq!(self.diverges.get(), Diverges::Maybe); | |
3911 | for e in args { | |
3912 | let e_ty = self.check_expr_with_hint(e, coerce_to); | |
3913 | let cause = self.misc(e.span); | |
3914 | coerce.coerce(self, &cause, e, e_ty, self.diverges.get()); | |
3915 | } | |
3916 | coerce.complete(self) | |
3917 | } else { | |
3918 | self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)) | |
3919 | }; | |
ea8adc8c | 3920 | tcx.mk_array(element_ty, args.len() as u64) |
a7813a04 | 3921 | } |
32a655c1 | 3922 | hir::ExprRepeat(ref element, count) => { |
ea8adc8c XL |
3923 | let count_def_id = tcx.hir.body_owner_def_id(count); |
3924 | let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); | |
3925 | let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); | |
3926 | let count = tcx.const_eval(param_env.and((count_def_id, substs))); | |
3927 | ||
3928 | if let Err(ref err) = count { | |
3929 | err.report(tcx, tcx.def_span(count_def_id), "constant expression"); | |
3930 | } | |
a7813a04 XL |
3931 | |
3932 | let uty = match expected { | |
3933 | ExpectHasType(uty) => { | |
3934 | match uty.sty { | |
3935 | ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty), | |
3936 | _ => None | |
3937 | } | |
1a4d82fc | 3938 | } |
a7813a04 | 3939 | _ => None |
1a4d82fc | 3940 | }; |
1a4d82fc | 3941 | |
a7813a04 XL |
3942 | let (element_ty, t) = match uty { |
3943 | Some(uty) => { | |
3944 | self.check_expr_coercable_to_type(&element, uty); | |
3945 | (uty, uty) | |
3946 | } | |
3947 | None => { | |
476ff2be | 3948 | let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span)); |
041b39d2 | 3949 | let element_ty = self.check_expr_has_type_or_error(&element, t); |
9e0c209e | 3950 | (element_ty, t) |
a7813a04 XL |
3951 | } |
3952 | }; | |
1a4d82fc | 3953 | |
ea8adc8c XL |
3954 | if let Ok(count) = count { |
3955 | let zero_or_one = count.val.to_const_int().and_then(|count| { | |
3956 | count.to_u64().map(|count| count <= 1) | |
3957 | }).unwrap_or(false); | |
3958 | if !zero_or_one { | |
3959 | // For [foo, ..n] where n > 1, `foo` must have | |
3960 | // Copy type: | |
3961 | let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); | |
3962 | self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item); | |
3963 | } | |
a7813a04 | 3964 | } |
62682a34 | 3965 | |
a7813a04 | 3966 | if element_ty.references_error() { |
9e0c209e | 3967 | tcx.types.err |
ea8adc8c XL |
3968 | } else if let Ok(count) = count { |
3969 | tcx.mk_ty(ty::TyArray(t, count)) | |
a7813a04 | 3970 | } else { |
ea8adc8c | 3971 | tcx.types.err |
a7813a04 XL |
3972 | } |
3973 | } | |
3974 | hir::ExprTup(ref elts) => { | |
3975 | let flds = expected.only_has_type(self).and_then(|ty| { | |
ea8adc8c | 3976 | let ty = self.resolve_type_vars_with_obligations(ty); |
a7813a04 | 3977 | match ty.sty { |
8bb4bdeb | 3978 | ty::TyTuple(ref flds, _) => Some(&flds[..]), |
a7813a04 | 3979 | _ => None |
7453a54e | 3980 | } |
a7813a04 | 3981 | }); |
a7813a04 | 3982 | |
c30ab7b3 | 3983 | let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| { |
a7813a04 XL |
3984 | let t = match flds { |
3985 | Some(ref fs) if i < fs.len() => { | |
3986 | let ety = fs[i]; | |
3987 | self.check_expr_coercable_to_type(&e, ety); | |
3988 | ety | |
3989 | } | |
3990 | _ => { | |
9e0c209e | 3991 | self.check_expr_with_expectation(&e, NoExpectation) |
a7813a04 XL |
3992 | } |
3993 | }; | |
a7813a04 | 3994 | t |
c30ab7b3 | 3995 | }); |
8bb4bdeb | 3996 | let tuple = tcx.mk_tup(elt_ts_iter, false); |
c30ab7b3 | 3997 | if tuple.references_error() { |
9e0c209e | 3998 | tcx.types.err |
a7813a04 | 3999 | } else { |
041b39d2 | 4000 | self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); |
c30ab7b3 | 4001 | tuple |
d9579d0f | 4002 | } |
a7813a04 | 4003 | } |
476ff2be | 4004 | hir::ExprStruct(ref qpath, ref fields, ref base_expr) => { |
32a655c1 | 4005 | self.check_expr_struct(expr, expected, qpath, fields, base_expr) |
a7813a04 XL |
4006 | } |
4007 | hir::ExprField(ref base, ref field) => { | |
9e0c209e | 4008 | self.check_field(expr, lvalue_pref, &base, field) |
a7813a04 XL |
4009 | } |
4010 | hir::ExprTupField(ref base, idx) => { | |
9e0c209e | 4011 | self.check_tup_field(expr, lvalue_pref, &base, idx) |
a7813a04 XL |
4012 | } |
4013 | hir::ExprIndex(ref base, ref idx) => { | |
9e0c209e SL |
4014 | let base_t = self.check_expr_with_lvalue_pref(&base, lvalue_pref); |
4015 | let idx_t = self.check_expr(&idx); | |
1a4d82fc | 4016 | |
a7813a04 | 4017 | if base_t.references_error() { |
9e0c209e | 4018 | base_t |
a7813a04 | 4019 | } else if idx_t.references_error() { |
9e0c209e | 4020 | idx_t |
a7813a04 XL |
4021 | } else { |
4022 | let base_t = self.structurally_resolved_type(expr.span, base_t); | |
4023 | match self.lookup_indexing(expr, base, base_t, idx_t, lvalue_pref) { | |
4024 | Some((index_ty, element_ty)) => { | |
8bb4bdeb | 4025 | self.demand_coerce(idx, idx_t, index_ty); |
9e0c209e | 4026 | element_ty |
a7813a04 XL |
4027 | } |
4028 | None => { | |
041b39d2 XL |
4029 | let mut err = type_error_struct!(tcx.sess, expr.span, base_t, E0608, |
4030 | "cannot index into a value of type `{}`", | |
4031 | base_t); | |
a7813a04 | 4032 | // Try to give some advice about indexing tuples. |
8bb4bdeb | 4033 | if let ty::TyTuple(..) = base_t.sty { |
a7813a04 XL |
4034 | let mut needs_note = true; |
4035 | // If the index is an integer, we can show the actual | |
4036 | // fixed expression: | |
4037 | if let hir::ExprLit(ref lit) = idx.node { | |
4038 | if let ast::LitKind::Int(i, | |
4039 | ast::LitIntType::Unsuffixed) = lit.node { | |
4040 | let snip = tcx.sess.codemap().span_to_snippet(base.span); | |
4041 | if let Ok(snip) = snip { | |
4042 | err.span_suggestion(expr.span, | |
7cac9316 | 4043 | "to access tuple elements, use", |
a7813a04 XL |
4044 | format!("{}.{}", snip, i)); |
4045 | needs_note = false; | |
4046 | } | |
4047 | } | |
4048 | } | |
4049 | if needs_note { | |
4050 | err.help("to access tuple elements, use tuple indexing \ | |
4051 | syntax (e.g. `tuple.0`)"); | |
4052 | } | |
4053 | } | |
4054 | err.emit(); | |
c30ab7b3 | 4055 | self.tcx.types.err |
a7813a04 XL |
4056 | } |
4057 | } | |
4058 | } | |
4059 | } | |
ea8adc8c XL |
4060 | hir::ExprYield(ref value) => { |
4061 | match self.yield_ty { | |
4062 | Some(ty) => { | |
4063 | self.check_expr_coercable_to_type(&value, ty); | |
4064 | } | |
4065 | None => { | |
4066 | struct_span_err!(self.tcx.sess, expr.span, E0627, | |
4067 | "yield statement outside of generator literal").emit(); | |
4068 | } | |
4069 | } | |
4070 | tcx.mk_nil() | |
4071 | } | |
1a4d82fc | 4072 | } |
1a4d82fc JJ |
4073 | } |
4074 | ||
3157f602 | 4075 | // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. |
7cac9316 | 4076 | // The newly resolved definition is written into `type_dependent_defs`. |
c30ab7b3 | 4077 | fn finish_resolving_struct_path(&self, |
476ff2be SL |
4078 | qpath: &hir::QPath, |
4079 | path_span: Span, | |
c30ab7b3 SL |
4080 | node_id: ast::NodeId) |
4081 | -> (Def, Ty<'tcx>) | |
3157f602 | 4082 | { |
476ff2be SL |
4083 | match *qpath { |
4084 | hir::QPath::Resolved(ref maybe_qself, ref path) => { | |
4085 | let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); | |
32a655c1 | 4086 | let ty = AstConv::def_to_ty(self, opt_self_ty, path, true); |
476ff2be SL |
4087 | (path.def, ty) |
4088 | } | |
4089 | hir::QPath::TypeRelative(ref qself, ref segment) => { | |
4090 | let ty = self.to_ty(qself); | |
4091 | ||
4092 | let def = if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = qself.node { | |
4093 | path.def | |
4094 | } else { | |
4095 | Def::Err | |
4096 | }; | |
4097 | let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, | |
4098 | ty, def, segment); | |
4099 | ||
4100 | // Write back the new resolution. | |
3b2f2976 XL |
4101 | let hir_id = self.tcx.hir.node_to_hir_id(node_id); |
4102 | self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def); | |
476ff2be SL |
4103 | |
4104 | (def, ty) | |
4105 | } | |
3157f602 XL |
4106 | } |
4107 | } | |
4108 | ||
5bcae85e | 4109 | // Resolve associated value path into a base type and associated constant or method definition. |
7cac9316 | 4110 | // The newly resolved definition is written into `type_dependent_defs`. |
a7813a04 | 4111 | pub fn resolve_ty_and_def_ufcs<'b>(&self, |
476ff2be | 4112 | qpath: &'b hir::QPath, |
5bcae85e SL |
4113 | node_id: ast::NodeId, |
4114 | span: Span) | |
4115 | -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) | |
a7813a04 | 4116 | { |
476ff2be SL |
4117 | let (ty, item_segment) = match *qpath { |
4118 | hir::QPath::Resolved(ref opt_qself, ref path) => { | |
4119 | return (path.def, | |
4120 | opt_qself.as_ref().map(|qself| self.to_ty(qself)), | |
4121 | &path.segments[..]); | |
4122 | } | |
4123 | hir::QPath::TypeRelative(ref qself, ref segment) => { | |
4124 | (self.to_ty(qself), segment) | |
4125 | } | |
4126 | }; | |
ea8adc8c XL |
4127 | let hir_id = self.tcx.hir.node_to_hir_id(node_id); |
4128 | if let Some(cached_def) = self.tables.borrow().type_dependent_defs().get(hir_id) { | |
4129 | // Return directly on cache hit. This is useful to avoid doubly reporting | |
4130 | // errors with default match binding modes. See #44614. | |
4131 | return (*cached_def, Some(ty), slice::ref_slice(&**item_segment)) | |
4132 | } | |
476ff2be SL |
4133 | let item_name = item_segment.name; |
4134 | let def = match self.resolve_ufcs(span, item_name, ty, node_id) { | |
4135 | Ok(def) => def, | |
4136 | Err(error) => { | |
4137 | let def = match error { | |
3b2f2976 | 4138 | method::MethodError::PrivateMatch(def, _) => def, |
476ff2be SL |
4139 | _ => Def::Err, |
4140 | }; | |
4141 | if item_name != keywords::Invalid.name() { | |
32a655c1 | 4142 | self.report_method_error(span, ty, item_name, None, error, None); |
a7813a04 | 4143 | } |
476ff2be SL |
4144 | def |
4145 | } | |
4146 | }; | |
a7813a04 | 4147 | |
476ff2be | 4148 | // Write back the new resolution. |
3b2f2976 | 4149 | self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def); |
476ff2be | 4150 | (def, Some(ty), slice::ref_slice(&**item_segment)) |
1a4d82fc | 4151 | } |
1a4d82fc | 4152 | |
a7813a04 XL |
4153 | pub fn check_decl_initializer(&self, |
4154 | local: &'gcx hir::Local, | |
9e0c209e | 4155 | init: &'gcx hir::Expr) -> Ty<'tcx> |
a7813a04 | 4156 | { |
3b2f2976 | 4157 | // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed |
ea8adc8c XL |
4158 | // for #42640 (default match binding modes). |
4159 | // | |
4160 | // See #44848. | |
3b2f2976 | 4161 | let ref_bindings = local.pat.contains_explicit_ref_binding(); |
a7813a04 XL |
4162 | |
4163 | let local_ty = self.local_ty(init.span, local.id); | |
4164 | if let Some(m) = ref_bindings { | |
4165 | // Somewhat subtle: if we have a `ref` binding in the pattern, | |
4166 | // we want to avoid introducing coercions for the RHS. This is | |
4167 | // both because it helps preserve sanity and, in the case of | |
4168 | // ref mut, for soundness (issue #23116). In particular, in | |
4169 | // the latter case, we need to be clear that the type of the | |
4170 | // referent for the reference that results is *equal to* the | |
4171 | // type of the lvalue it is referencing, and not some | |
4172 | // supertype thereof. | |
9e0c209e | 4173 | let init_ty = self.check_expr_with_lvalue_pref(init, LvaluePreference::from_mutbl(m)); |
a7813a04 | 4174 | self.demand_eqtype(init.span, init_ty, local_ty); |
9e0c209e | 4175 | init_ty |
a7813a04 XL |
4176 | } else { |
4177 | self.check_expr_coercable_to_type(init, local_ty) | |
9e0c209e | 4178 | } |
a7813a04 | 4179 | } |
1a4d82fc | 4180 | |
a7813a04 | 4181 | pub fn check_decl_local(&self, local: &'gcx hir::Local) { |
a7813a04 | 4182 | let t = self.local_ty(local.span, local.id); |
3b2f2976 | 4183 | self.write_ty(local.hir_id, t); |
1a4d82fc | 4184 | |
a7813a04 | 4185 | if let Some(ref init) = local.init { |
9e0c209e | 4186 | let init_ty = self.check_decl_initializer(local, &init); |
a7813a04 | 4187 | if init_ty.references_error() { |
3b2f2976 | 4188 | self.write_ty(local.hir_id, init_ty); |
a7813a04 | 4189 | } |
1a4d82fc | 4190 | } |
1a4d82fc | 4191 | |
ea8adc8c XL |
4192 | self.check_pat_walk(&local.pat, t, |
4193 | ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), | |
4194 | true); | |
3b2f2976 | 4195 | let pat_ty = self.node_ty(local.pat.hir_id); |
a7813a04 | 4196 | if pat_ty.references_error() { |
3b2f2976 | 4197 | self.write_ty(local.hir_id, pat_ty); |
a7813a04 XL |
4198 | } |
4199 | } | |
4200 | ||
9e0c209e | 4201 | pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { |
476ff2be | 4202 | // Don't do all the complex logic below for DeclItem. |
a7813a04 | 4203 | match stmt.node { |
041b39d2 | 4204 | hir::StmtDecl(ref decl, _) => { |
476ff2be SL |
4205 | match decl.node { |
4206 | hir::DeclLocal(_) => {} | |
4207 | hir::DeclItem(_) => { | |
476ff2be SL |
4208 | return; |
4209 | } | |
4210 | } | |
a7813a04 | 4211 | } |
476ff2be | 4212 | hir::StmtExpr(..) | hir::StmtSemi(..) => {} |
1a4d82fc | 4213 | } |
476ff2be SL |
4214 | |
4215 | self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement"); | |
4216 | ||
4217 | // Hide the outer diverging and has_errors flags. | |
4218 | let old_diverges = self.diverges.get(); | |
4219 | let old_has_errors = self.has_errors.get(); | |
4220 | self.diverges.set(Diverges::Maybe); | |
4221 | self.has_errors.set(false); | |
4222 | ||
041b39d2 XL |
4223 | match stmt.node { |
4224 | hir::StmtDecl(ref decl, _) => { | |
4225 | match decl.node { | |
476ff2be SL |
4226 | hir::DeclLocal(ref l) => { |
4227 | self.check_decl_local(&l); | |
476ff2be | 4228 | } |
041b39d2 XL |
4229 | hir::DeclItem(_) => {/* ignore for now */} |
4230 | } | |
476ff2be | 4231 | } |
041b39d2 | 4232 | hir::StmtExpr(ref expr, _) => { |
476ff2be | 4233 | // Check with expected type of () |
041b39d2 | 4234 | self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil()); |
476ff2be | 4235 | } |
041b39d2 | 4236 | hir::StmtSemi(ref expr, _) => { |
476ff2be | 4237 | self.check_expr(&expr); |
476ff2be | 4238 | } |
a7813a04 | 4239 | } |
476ff2be SL |
4240 | |
4241 | // Combine the diverging and has_error flags. | |
4242 | self.diverges.set(self.diverges.get() | old_diverges); | |
4243 | self.has_errors.set(self.has_errors.get() | old_has_errors); | |
1a4d82fc | 4244 | } |
1a4d82fc | 4245 | |
a7813a04 | 4246 | pub fn check_block_no_value(&self, blk: &'gcx hir::Block) { |
476ff2be SL |
4247 | let unit = self.tcx.mk_nil(); |
4248 | let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); | |
cc61c64b XL |
4249 | |
4250 | // if the block produces a `!` value, that can always be | |
4251 | // (effectively) coerced to unit. | |
4252 | if !ty.is_never() { | |
4253 | self.demand_suptype(blk.span, unit, ty); | |
4254 | } | |
1a4d82fc | 4255 | } |
1a4d82fc | 4256 | |
a7813a04 XL |
4257 | fn check_block_with_expected(&self, |
4258 | blk: &'gcx hir::Block, | |
9e0c209e | 4259 | expected: Expectation<'tcx>) -> Ty<'tcx> { |
a7813a04 XL |
4260 | let prev = { |
4261 | let mut fcx_ps = self.ps.borrow_mut(); | |
4262 | let unsafety_state = fcx_ps.recurse(blk); | |
4263 | replace(&mut *fcx_ps, unsafety_state) | |
4264 | }; | |
1a4d82fc | 4265 | |
cc61c64b XL |
4266 | // In some cases, blocks have just one exit, but other blocks |
4267 | // can be targeted by multiple breaks. This cannot happen in | |
4268 | // normal Rust syntax today, but it can happen when we desugar | |
4269 | // a `do catch { ... }` expression. | |
4270 | // | |
4271 | // Example 1: | |
4272 | // | |
4273 | // 'a: { if true { break 'a Err(()); } Ok(()) } | |
4274 | // | |
4275 | // Here we would wind up with two coercions, one from | |
4276 | // `Err(())` and the other from the tail expression | |
4277 | // `Ok(())`. If the tail expression is omitted, that's a | |
4278 | // "forced unit" -- unless the block diverges, in which | |
4279 | // case we can ignore the tail expression (e.g., `'a: { | |
4280 | // break 'a 22; }` would not force the type of the block | |
4281 | // to be `()`). | |
4282 | let tail_expr = blk.expr.as_ref(); | |
4283 | let coerce_to_ty = expected.coercion_target_type(self, blk.span); | |
4284 | let coerce = if blk.targeted_by_break { | |
4285 | CoerceMany::new(coerce_to_ty) | |
4286 | } else { | |
4287 | let tail_expr: &[P<hir::Expr>] = match tail_expr { | |
4288 | Some(e) => ref_slice(e), | |
4289 | None => &[], | |
4290 | }; | |
4291 | CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr) | |
4292 | }; | |
476ff2be | 4293 | |
abe05a73 | 4294 | let prev_diverges = self.diverges.get(); |
cc61c64b XL |
4295 | let ctxt = BreakableCtxt { |
4296 | coerce: Some(coerce), | |
4297 | may_break: false, | |
476ff2be SL |
4298 | }; |
4299 | ||
cc61c64b XL |
4300 | let (ctxt, ()) = self.with_breakable_ctxt(blk.id, ctxt, || { |
4301 | for s in &blk.stmts { | |
4302 | self.check_stmt(s); | |
1a4d82fc | 4303 | } |
476ff2be | 4304 | |
cc61c64b XL |
4305 | // check the tail expression **without** holding the |
4306 | // `enclosing_breakables` lock below. | |
4307 | let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected)); | |
4308 | ||
4309 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
3b2f2976 XL |
4310 | let ctxt = enclosing_breakables.find_breakable(blk.id); |
4311 | let coerce = ctxt.coerce.as_mut().unwrap(); | |
cc61c64b XL |
4312 | if let Some(tail_expr_ty) = tail_expr_ty { |
4313 | let tail_expr = tail_expr.unwrap(); | |
041b39d2 XL |
4314 | let cause = self.cause(tail_expr.span, |
4315 | ObligationCauseCode::BlockTailExpression(blk.id)); | |
cc61c64b | 4316 | coerce.coerce(self, |
041b39d2 | 4317 | &cause, |
cc61c64b XL |
4318 | tail_expr, |
4319 | tail_expr_ty, | |
4320 | self.diverges.get()); | |
1a4d82fc | 4321 | } else { |
cc61c64b XL |
4322 | // Subtle: if there is no explicit tail expression, |
4323 | // that is typically equivalent to a tail expression | |
4324 | // of `()` -- except if the block diverges. In that | |
4325 | // case, there is no value supplied from the tail | |
4326 | // expression (assuming there are no other breaks, | |
4327 | // this implies that the type of the block will be | |
4328 | // `!`). | |
7cac9316 XL |
4329 | // |
4330 | // #41425 -- label the implicit `()` as being the | |
4331 | // "found type" here, rather than the "expected type". | |
cc61c64b XL |
4332 | if !self.diverges.get().always() { |
4333 | coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| { | |
4334 | if let Some(expected_ty) = expected.only_has_type(self) { | |
4335 | self.consider_hint_about_removing_semicolon(blk, | |
4336 | expected_ty, | |
4337 | err); | |
476ff2be | 4338 | } |
7cac9316 | 4339 | }, false); |
a7813a04 XL |
4340 | } |
4341 | } | |
cc61c64b | 4342 | }); |
476ff2be | 4343 | |
abe05a73 XL |
4344 | if ctxt.may_break { |
4345 | // If we can break from the block, then the block's exit is always reachable | |
4346 | // (... as long as the entry is reachable) - regardless of the tail of the block. | |
4347 | self.diverges.set(prev_diverges); | |
4348 | } | |
4349 | ||
cc61c64b | 4350 | let mut ty = ctxt.coerce.unwrap().complete(self); |
476ff2be SL |
4351 | |
4352 | if self.has_errors.get() || ty.references_error() { | |
4353 | ty = self.tcx.types.err | |
4354 | } | |
4355 | ||
3b2f2976 | 4356 | self.write_ty(blk.hir_id, ty); |
1a4d82fc | 4357 | |
a7813a04 | 4358 | *self.ps.borrow_mut() = prev; |
9e0c209e | 4359 | ty |
1a4d82fc | 4360 | } |
1a4d82fc | 4361 | |
3b2f2976 XL |
4362 | /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a |
4363 | /// suggestion can be made, `None` otherwise. | |
041b39d2 XL |
4364 | pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { |
4365 | // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or | |
4366 | // `while` before reaching it, as block tail returns are not available in them. | |
4367 | if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { | |
4368 | let parent = self.tcx.hir.get(fn_id); | |
4369 | ||
4370 | if let Node::NodeItem(&hir::Item { | |
4371 | name, node: hir::ItemFn(ref decl, ..), .. | |
4372 | }) = parent { | |
4373 | decl.clone().and_then(|decl| { | |
3b2f2976 XL |
4374 | // This is less than ideal, it will not suggest a return type span on any |
4375 | // method called `main`, regardless of whether it is actually the entry point, | |
4376 | // but it will still present it as the reason for the expected type. | |
4377 | Some((decl, name != Symbol::intern("main"))) | |
041b39d2 XL |
4378 | }) |
4379 | } else if let Node::NodeTraitItem(&hir::TraitItem { | |
4380 | node: hir::TraitItemKind::Method(hir::MethodSig { | |
4381 | ref decl, .. | |
4382 | }, ..), .. | |
3b2f2976 XL |
4383 | }) = parent { |
4384 | decl.clone().and_then(|decl| { | |
4385 | Some((decl, true)) | |
4386 | }) | |
4387 | } else if let Node::NodeImplItem(&hir::ImplItem { | |
4388 | node: hir::ImplItemKind::Method(hir::MethodSig { | |
4389 | ref decl, .. | |
4390 | }, ..), .. | |
041b39d2 XL |
4391 | }) = parent { |
4392 | decl.clone().and_then(|decl| { | |
4393 | Some((decl, false)) | |
4394 | }) | |
4395 | } else { | |
4396 | None | |
4397 | } | |
4398 | } else { | |
4399 | None | |
4400 | } | |
4401 | } | |
4402 | ||
4403 | /// On implicit return expressions with mismatched types, provide the following suggestions: | |
4404 | /// | |
4405 | /// - Point out the method's return type as the reason for the expected type | |
4406 | /// - Possible missing semicolon | |
4407 | /// - Possible missing return type if the return type is the default, and not `fn main()` | |
4408 | pub fn suggest_mismatched_types_on_tail(&self, | |
4409 | err: &mut DiagnosticBuilder<'tcx>, | |
4410 | expression: &'gcx hir::Expr, | |
4411 | expected: Ty<'tcx>, | |
4412 | found: Ty<'tcx>, | |
4413 | cause_span: Span, | |
4414 | blk_id: ast::NodeId) { | |
4415 | self.suggest_missing_semicolon(err, expression, expected, cause_span); | |
4416 | ||
3b2f2976 XL |
4417 | if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { |
4418 | self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); | |
041b39d2 XL |
4419 | } |
4420 | } | |
4421 | ||
4422 | /// A common error is to forget to add a semicolon at the end of a block: | |
4423 | /// | |
4424 | /// ``` | |
4425 | /// fn foo() { | |
4426 | /// bar_that_returns_u32() | |
4427 | /// } | |
4428 | /// ``` | |
4429 | /// | |
4430 | /// This routine checks if the return expression in a block would make sense on its own as a | |
3b2f2976 | 4431 | /// statement and the return type has been left as default or has been specified as `()`. If so, |
041b39d2 XL |
4432 | /// it suggests adding a semicolon. |
4433 | fn suggest_missing_semicolon(&self, | |
4434 | err: &mut DiagnosticBuilder<'tcx>, | |
4435 | expression: &'gcx hir::Expr, | |
4436 | expected: Ty<'tcx>, | |
4437 | cause_span: Span) { | |
4438 | if expected.is_nil() { | |
4439 | // `BlockTailExpression` only relevant if the tail expr would be | |
4440 | // useful on its own. | |
4441 | match expression.node { | |
4442 | hir::ExprCall(..) | | |
4443 | hir::ExprMethodCall(..) | | |
4444 | hir::ExprIf(..) | | |
4445 | hir::ExprWhile(..) | | |
4446 | hir::ExprLoop(..) | | |
4447 | hir::ExprMatch(..) | | |
4448 | hir::ExprBlock(..) => { | |
4449 | let sp = cause_span.next_point(); | |
4450 | err.span_suggestion(sp, | |
3b2f2976 | 4451 | "try adding a semicolon", |
041b39d2 XL |
4452 | ";".to_string()); |
4453 | } | |
4454 | _ => (), | |
4455 | } | |
4456 | } | |
4457 | } | |
4458 | ||
4459 | ||
4460 | /// A possible error is to forget to add a return type that is needed: | |
4461 | /// | |
4462 | /// ``` | |
4463 | /// fn foo() { | |
4464 | /// bar_that_returns_u32() | |
4465 | /// } | |
4466 | /// ``` | |
4467 | /// | |
4468 | /// This routine checks if the return type is left as default, the method is not part of an | |
4469 | /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return | |
4470 | /// type. | |
4471 | fn suggest_missing_return_type(&self, | |
4472 | err: &mut DiagnosticBuilder<'tcx>, | |
4473 | fn_decl: &hir::FnDecl, | |
3b2f2976 XL |
4474 | expected: Ty<'tcx>, |
4475 | found: Ty<'tcx>, | |
4476 | can_suggest: bool) { | |
4477 | // Only suggest changing the return type for methods that | |
041b39d2 | 4478 | // haven't set a return type at all (and aren't `fn main()` or an impl). |
3b2f2976 XL |
4479 | match (&fn_decl.output, found.is_suggestable(), can_suggest) { |
4480 | (&hir::FunctionRetTy::DefaultReturn(span), true, true) => { | |
041b39d2 | 4481 | err.span_suggestion(span, |
3b2f2976 XL |
4482 | "try adding a return type", |
4483 | format!("-> {} ", found)); | |
4484 | } | |
4485 | (&hir::FunctionRetTy::DefaultReturn(span), false, true) => { | |
041b39d2 XL |
4486 | err.span_label(span, "possibly return type missing here?"); |
4487 | } | |
3b2f2976 XL |
4488 | (&hir::FunctionRetTy::DefaultReturn(span), _, _) => { |
4489 | // `fn main()` must return `()`, do not suggest changing return type | |
4490 | err.span_label(span, "expected `()` because of default return type"); | |
4491 | } | |
4492 | (&hir::FunctionRetTy::Return(ref ty), _, _) => { | |
4493 | // Only point to return type if the expected type is the return type, as if they | |
4494 | // are not, the expectation must have been caused by something else. | |
4495 | debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node); | |
4496 | let sp = ty.span; | |
4497 | let ty = AstConv::ast_ty_to_ty(self, ty); | |
4498 | debug!("suggest_missing_return_type: return type sty {:?}", ty.sty); | |
4499 | debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty); | |
4500 | if ty.sty == expected.sty { | |
4501 | err.span_label(sp, format!("expected `{}` because of return type", | |
4502 | expected)); | |
4503 | } | |
4504 | } | |
041b39d2 XL |
4505 | } |
4506 | } | |
4507 | ||
4508 | ||
cc61c64b XL |
4509 | /// A common error is to add an extra semicolon: |
4510 | /// | |
4511 | /// ``` | |
4512 | /// fn foo() -> usize { | |
4513 | /// 22; | |
4514 | /// } | |
4515 | /// ``` | |
4516 | /// | |
4517 | /// This routine checks if the final statement in a block is an | |
4518 | /// expression with an explicit semicolon whose type is compatible | |
4519 | /// with `expected_ty`. If so, it suggests removing the semicolon. | |
4520 | fn consider_hint_about_removing_semicolon(&self, | |
4521 | blk: &'gcx hir::Block, | |
4522 | expected_ty: Ty<'tcx>, | |
4523 | err: &mut DiagnosticBuilder) { | |
4524 | // Be helpful when the user wrote `{... expr;}` and | |
4525 | // taking the `;` off is enough to fix the error. | |
4526 | let last_stmt = match blk.stmts.last() { | |
4527 | Some(s) => s, | |
4528 | None => return, | |
4529 | }; | |
4530 | let last_expr = match last_stmt.node { | |
4531 | hir::StmtSemi(ref e, _) => e, | |
4532 | _ => return, | |
4533 | }; | |
3b2f2976 | 4534 | let last_expr_ty = self.node_ty(last_expr.hir_id); |
7cac9316 | 4535 | if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() { |
cc61c64b XL |
4536 | return; |
4537 | } | |
4538 | let original_span = original_sp(last_stmt.span, blk.span); | |
ea8adc8c | 4539 | let span_semi = original_span.with_lo(original_span.hi() - BytePos(1)); |
041b39d2 | 4540 | err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); |
cc61c64b XL |
4541 | } |
4542 | ||
a7813a04 XL |
4543 | // Instantiates the given path, which must refer to an item with the given |
4544 | // number of type parameters and type. | |
5bcae85e SL |
4545 | pub fn instantiate_value_path(&self, |
4546 | segments: &[hir::PathSegment], | |
5bcae85e SL |
4547 | opt_self_ty: Option<Ty<'tcx>>, |
4548 | def: Def, | |
4549 | span: Span, | |
4550 | node_id: ast::NodeId) | |
4551 | -> Ty<'tcx> { | |
9e0c209e | 4552 | debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})", |
a7813a04 XL |
4553 | segments, |
4554 | def, | |
9e0c209e | 4555 | node_id); |
a7813a04 XL |
4556 | |
4557 | // We need to extract the type parameters supplied by the user in | |
4558 | // the path `path`. Due to the current setup, this is a bit of a | |
4559 | // tricky-process; the problem is that resolve only tells us the | |
4560 | // end-point of the path resolution, and not the intermediate steps. | |
4561 | // Luckily, we can (at least for now) deduce the intermediate steps | |
4562 | // just from the end-point. | |
4563 | // | |
4564 | // There are basically four cases to consider: | |
4565 | // | |
c30ab7b3 | 4566 | // 1. Reference to a constructor of enum variant or struct: |
a7813a04 | 4567 | // |
c30ab7b3 SL |
4568 | // struct Foo<T>(...) |
4569 | // enum E<T> { Foo(...) } | |
a7813a04 XL |
4570 | // |
4571 | // In these cases, the parameters are declared in the type | |
4572 | // space. | |
4573 | // | |
c30ab7b3 | 4574 | // 2. Reference to a fn item or a free constant: |
a7813a04 XL |
4575 | // |
4576 | // fn foo<T>() { } | |
4577 | // | |
4578 | // In this case, the path will again always have the form | |
4579 | // `a::b::foo::<T>` where only the final segment should have | |
4580 | // type parameters. However, in this case, those parameters are | |
4581 | // declared on a value, and hence are in the `FnSpace`. | |
4582 | // | |
c30ab7b3 | 4583 | // 3. Reference to a method or an associated constant: |
a7813a04 XL |
4584 | // |
4585 | // impl<A> SomeStruct<A> { | |
4586 | // fn foo<B>(...) | |
4587 | // } | |
4588 | // | |
4589 | // Here we can have a path like | |
4590 | // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters | |
4591 | // may appear in two places. The penultimate segment, | |
4592 | // `SomeStruct::<A>`, contains parameters in TypeSpace, and the | |
4593 | // final segment, `foo::<B>` contains parameters in fn space. | |
4594 | // | |
c30ab7b3 | 4595 | // 4. Reference to a local variable |
a7813a04 | 4596 | // |
c30ab7b3 | 4597 | // Local variables can't have any type parameters. |
a7813a04 XL |
4598 | // |
4599 | // The first step then is to categorize the segments appropriately. | |
4600 | ||
4601 | assert!(!segments.is_empty()); | |
4602 | ||
4603 | let mut ufcs_associated = None; | |
9e0c209e SL |
4604 | let mut type_segment = None; |
4605 | let mut fn_segment = None; | |
a7813a04 | 4606 | match def { |
c30ab7b3 SL |
4607 | // Case 1. Reference to a struct/variant constructor. |
4608 | Def::StructCtor(def_id, ..) | | |
4609 | Def::VariantCtor(def_id, ..) => { | |
a7813a04 XL |
4610 | // Everything but the final segment should have no |
4611 | // parameters at all. | |
7cac9316 | 4612 | let mut generics = self.tcx.generics_of(def_id); |
9e0c209e SL |
4613 | if let Some(def_id) = generics.parent { |
4614 | // Variant and struct constructors use the | |
4615 | // generics of their parent type definition. | |
7cac9316 | 4616 | generics = self.tcx.generics_of(def_id); |
9e0c209e SL |
4617 | } |
4618 | type_segment = Some((segments.last().unwrap(), generics)); | |
c34b1796 | 4619 | } |
1a4d82fc | 4620 | |
a7813a04 | 4621 | // Case 2. Reference to a top-level value. |
9e0c209e SL |
4622 | Def::Fn(def_id) | |
4623 | Def::Const(def_id) | | |
4624 | Def::Static(def_id, _) => { | |
4625 | fn_segment = Some((segments.last().unwrap(), | |
7cac9316 | 4626 | self.tcx.generics_of(def_id))); |
1a4d82fc | 4627 | } |
1a4d82fc | 4628 | |
9e0c209e SL |
4629 | // Case 3. Reference to a method or associated const. |
4630 | Def::Method(def_id) | | |
a7813a04 | 4631 | Def::AssociatedConst(def_id) => { |
476ff2be | 4632 | let container = self.tcx.associated_item(def_id).container; |
a7813a04 XL |
4633 | match container { |
4634 | ty::TraitContainer(trait_did) => { | |
8bb4bdeb | 4635 | callee::check_legal_trait_for_method_call(self.tcx, span, trait_did) |
a7813a04 XL |
4636 | } |
4637 | ty::ImplContainer(_) => {} | |
4638 | } | |
1a4d82fc | 4639 | |
7cac9316 | 4640 | let generics = self.tcx.generics_of(def_id); |
a7813a04 | 4641 | if segments.len() >= 2 { |
7cac9316 | 4642 | let parent_generics = self.tcx.generics_of(generics.parent.unwrap()); |
9e0c209e | 4643 | type_segment = Some((&segments[segments.len() - 2], parent_generics)); |
a7813a04 | 4644 | } else { |
9e0c209e SL |
4645 | // `<T>::assoc` will end up here, and so can `T::assoc`. |
4646 | let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); | |
a7813a04 | 4647 | ufcs_associated = Some((container, self_ty)); |
1a4d82fc | 4648 | } |
9e0c209e | 4649 | fn_segment = Some((segments.last().unwrap(), generics)); |
1a4d82fc JJ |
4650 | } |
4651 | ||
c30ab7b3 SL |
4652 | // Case 4. Local variable, no generics. |
4653 | Def::Local(..) | Def::Upvar(..) => {} | |
4654 | ||
4655 | _ => bug!("unexpected definition: {:?}", def), | |
a7813a04 | 4656 | } |
a7813a04 | 4657 | |
9e0c209e | 4658 | debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment); |
a7813a04 XL |
4659 | |
4660 | // Now that we have categorized what space the parameters for each | |
4661 | // segment belong to, let's sort out the parameters that the user | |
4662 | // provided (if any) into their appropriate spaces. We'll also report | |
4663 | // errors if type parameters are provided in an inappropriate place. | |
9e0c209e SL |
4664 | let poly_segments = type_segment.is_some() as usize + |
4665 | fn_segment.is_some() as usize; | |
8bb4bdeb | 4666 | AstConv::prohibit_type_params(self, &segments[..segments.len() - poly_segments]); |
9e0c209e SL |
4667 | |
4668 | match def { | |
ea8adc8c | 4669 | Def::Local(nid) | Def::Upvar(nid, ..) => { |
9e0c209e SL |
4670 | let ty = self.local_ty(span, nid); |
4671 | let ty = self.normalize_associated_types_in(span, &ty); | |
3b2f2976 | 4672 | self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty); |
9e0c209e | 4673 | return ty; |
a7813a04 | 4674 | } |
9e0c209e | 4675 | _ => {} |
1a4d82fc | 4676 | } |
c34b1796 | 4677 | |
a7813a04 XL |
4678 | // Now we have to compare the types that the user *actually* |
4679 | // provided against the types that were *expected*. If the user | |
4680 | // did not provide any types, then we want to substitute inference | |
4681 | // variables. If the user provided some types, we may still need | |
4682 | // to add defaults. If the user provided *too many* types, that's | |
4683 | // a problem. | |
3b2f2976 XL |
4684 | self.check_path_parameter_count(span, &mut type_segment, false); |
4685 | self.check_path_parameter_count(span, &mut fn_segment, false); | |
ea8adc8c | 4686 | self.check_impl_trait(span, &mut fn_segment); |
1a4d82fc | 4687 | |
9e0c209e SL |
4688 | let (fn_start, has_self) = match (type_segment, fn_segment) { |
4689 | (_, Some((_, generics))) => { | |
4690 | (generics.parent_count(), generics.has_self) | |
4691 | } | |
4692 | (Some((_, generics)), None) => { | |
4693 | (generics.own_count(), generics.has_self) | |
4694 | } | |
4695 | (None, None) => (0, false) | |
4696 | }; | |
4697 | let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { | |
4698 | let mut i = def.index as usize; | |
4699 | ||
4700 | let segment = if i < fn_start { | |
4701 | i -= has_self as usize; | |
4702 | type_segment | |
4703 | } else { | |
4704 | i -= fn_start; | |
4705 | fn_segment | |
4706 | }; | |
ea8adc8c XL |
4707 | let lifetimes = segment.map_or(&[][..], |(s, _)| { |
4708 | s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) | |
4709 | }); | |
9e0c209e | 4710 | |
32a655c1 SL |
4711 | if let Some(lifetime) = lifetimes.get(i) { |
4712 | AstConv::ast_region_to_region(self, lifetime, Some(def)) | |
9e0c209e | 4713 | } else { |
32a655c1 | 4714 | self.re_infer(span, Some(def)).unwrap() |
9e0c209e SL |
4715 | } |
4716 | }, |def, substs| { | |
4717 | let mut i = def.index as usize; | |
4718 | ||
9e0c209e SL |
4719 | let segment = if i < fn_start { |
4720 | // Handle Self first, so we can adjust the index to match the AST. | |
4721 | if has_self && i == 0 { | |
4722 | return opt_self_ty.unwrap_or_else(|| { | |
4723 | self.type_var_for_def(span, def, substs) | |
4724 | }); | |
4725 | } | |
4726 | i -= has_self as usize; | |
4727 | type_segment | |
4728 | } else { | |
4729 | i -= fn_start; | |
4730 | fn_segment | |
4731 | }; | |
3b2f2976 | 4732 | let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { |
ea8adc8c | 4733 | (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) |
3b2f2976 | 4734 | }); |
9e0c209e SL |
4735 | |
4736 | // Skip over the lifetimes in the same segment. | |
4737 | if let Some((_, generics)) = segment { | |
4738 | i -= generics.regions.len(); | |
4739 | } | |
4740 | ||
9e0c209e SL |
4741 | if let Some(ast_ty) = types.get(i) { |
4742 | // A provided type parameter. | |
4743 | self.to_ty(ast_ty) | |
8bb4bdeb | 4744 | } else if !infer_types && def.has_default { |
9e0c209e | 4745 | // No type parameter provided, but a default exists. |
7cac9316 | 4746 | let default = self.tcx.type_of(def.def_id); |
8bb4bdeb XL |
4747 | self.normalize_ty( |
4748 | span, | |
4749 | default.subst_spanned(self.tcx, substs, Some(span)) | |
4750 | ) | |
9e0c209e SL |
4751 | } else { |
4752 | // No type parameters were provided, we can infer all. | |
4753 | // This can also be reached in some error cases: | |
4754 | // We prefer to use inference variables instead of | |
4755 | // TyError to let type inference recover somewhat. | |
4756 | self.type_var_for_def(span, def, substs) | |
4757 | } | |
4758 | }); | |
1a4d82fc | 4759 | |
a7813a04 XL |
4760 | // The things we are substituting into the type should not contain |
4761 | // escaping late-bound regions, and nor should the base type scheme. | |
7cac9316 | 4762 | let ty = self.tcx.type_of(def.def_id()); |
9e0c209e | 4763 | assert!(!substs.has_escaping_regions()); |
476ff2be | 4764 | assert!(!ty.has_escaping_regions()); |
1a4d82fc | 4765 | |
a7813a04 XL |
4766 | // Add all the obligations that are required, substituting and |
4767 | // normalized appropriately. | |
476ff2be | 4768 | let bounds = self.instantiate_bounds(span, def.def_id(), &substs); |
a7813a04 XL |
4769 | self.add_obligations_for_parameters( |
4770 | traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())), | |
4771 | &bounds); | |
1a4d82fc | 4772 | |
a7813a04 XL |
4773 | // Substitute the values for the type parameters into the type of |
4774 | // the referenced item. | |
476ff2be | 4775 | let ty_substituted = self.instantiate_type_scheme(span, &substs, &ty); |
a7813a04 | 4776 | |
a7813a04 XL |
4777 | if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated { |
4778 | // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method` | |
4779 | // is inherent, there is no `Self` parameter, instead, the impl needs | |
4780 | // type parameters, which we can infer by unifying the provided `Self` | |
4781 | // with the substituted impl type. | |
7cac9316 | 4782 | let ty = self.tcx.type_of(impl_def_id); |
a7813a04 | 4783 | |
476ff2be | 4784 | let impl_ty = self.instantiate_type_scheme(span, &substs, &ty); |
7cac9316 | 4785 | match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) { |
476ff2be | 4786 | Ok(ok) => self.register_infer_ok_obligations(ok), |
a7813a04 XL |
4787 | Err(_) => { |
4788 | span_bug!(span, | |
5bcae85e | 4789 | "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?", |
a7813a04 XL |
4790 | self_ty, |
4791 | impl_ty); | |
4792 | } | |
1a4d82fc JJ |
4793 | } |
4794 | } | |
1a4d82fc | 4795 | |
5bcae85e | 4796 | debug!("instantiate_value_path: type of {:?} is {:?}", |
a7813a04 XL |
4797 | node_id, |
4798 | ty_substituted); | |
3b2f2976 | 4799 | self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs); |
5bcae85e | 4800 | ty_substituted |
1a4d82fc JJ |
4801 | } |
4802 | ||
9e0c209e SL |
4803 | /// Report errors if the provided parameters are too few or too many. |
4804 | fn check_path_parameter_count(&self, | |
4805 | span: Span, | |
3b2f2976 XL |
4806 | segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, |
4807 | is_method_call: bool) { | |
4808 | let (lifetimes, types, infer_types, bindings) = segment.map_or( | |
4809 | (&[][..], &[][..], true, &[][..]), | |
ea8adc8c XL |
4810 | |(s, _)| s.parameters.as_ref().map_or( |
4811 | (&[][..], &[][..], s.infer_types, &[][..]), | |
4812 | |p| (&p.lifetimes[..], &p.types[..], | |
4813 | s.infer_types, &p.bindings[..]))); | |
3b2f2976 | 4814 | let infer_lifetimes = lifetimes.len() == 0; |
1a4d82fc | 4815 | |
8bb4bdeb XL |
4816 | let count_lifetime_params = |n| { |
4817 | format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" }) | |
4818 | }; | |
4819 | let count_type_params = |n| { | |
4820 | format!("{} type parameter{}", n, if n == 1 { "" } else { "s" }) | |
9e0c209e | 4821 | }; |
1a4d82fc | 4822 | |
9e0c209e SL |
4823 | // Check provided type parameters. |
4824 | let type_defs = segment.map_or(&[][..], |(_, generics)| { | |
4825 | if generics.parent.is_none() { | |
4826 | &generics.types[generics.has_self as usize..] | |
4827 | } else { | |
4828 | &generics.types | |
1a4d82fc | 4829 | } |
9e0c209e | 4830 | }); |
8bb4bdeb | 4831 | let required_len = type_defs.iter().take_while(|d| !d.has_default).count(); |
9e0c209e SL |
4832 | if types.len() > type_defs.len() { |
4833 | let span = types[type_defs.len()].span; | |
8bb4bdeb XL |
4834 | let expected_text = count_type_params(type_defs.len()); |
4835 | let actual_text = count_type_params(types.len()); | |
9e0c209e SL |
4836 | struct_span_err!(self.tcx.sess, span, E0087, |
4837 | "too many type parameters provided: \ | |
4838 | expected at most {}, found {}", | |
8bb4bdeb | 4839 | expected_text, actual_text) |
7cac9316 | 4840 | .span_label(span, format!("expected {}", expected_text)) |
8bb4bdeb | 4841 | .emit(); |
9e0c209e SL |
4842 | |
4843 | // To prevent derived errors to accumulate due to extra | |
4844 | // type parameters, we force instantiate_value_path to | |
4845 | // use inference variables instead of the provided types. | |
4846 | *segment = None; | |
3b2f2976 | 4847 | } else if types.len() < required_len && !infer_types { |
8bb4bdeb XL |
4848 | let expected_text = count_type_params(required_len); |
4849 | let actual_text = count_type_params(types.len()); | |
9e0c209e SL |
4850 | struct_span_err!(self.tcx.sess, span, E0089, |
4851 | "too few type parameters provided: \ | |
8bb4bdeb XL |
4852 | expected {}, found {}", |
4853 | expected_text, actual_text) | |
7cac9316 | 4854 | .span_label(span, format!("expected {}", expected_text)) |
9e0c209e | 4855 | .emit(); |
1a4d82fc JJ |
4856 | } |
4857 | ||
9e0c209e | 4858 | if !bindings.is_empty() { |
3b2f2976 XL |
4859 | AstConv::prohibit_projection(self, bindings[0].span); |
4860 | } | |
4861 | ||
4862 | // Check provided lifetime parameters. | |
4863 | let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); | |
4864 | let required_len = lifetime_defs.len(); | |
4865 | ||
4866 | // Prohibit explicit lifetime arguments if late bound lifetime parameters are present. | |
4867 | let has_late_bound_lifetime_defs = | |
4868 | segment.map_or(None, |(_, generics)| generics.has_late_bound_regions); | |
4869 | if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) { | |
4870 | // Report this as a lint only if no error was reported previously. | |
4871 | let primary_msg = "cannot specify lifetime arguments explicitly \ | |
4872 | if late bound lifetime parameters are present"; | |
4873 | let note_msg = "the late bound lifetime parameter is introduced here"; | |
4874 | if !is_method_call && (lifetimes.len() > lifetime_defs.len() || | |
4875 | lifetimes.len() < required_len && !infer_lifetimes) { | |
4876 | let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg); | |
4877 | err.span_note(span_late, note_msg); | |
4878 | err.emit(); | |
4879 | *segment = None; | |
4880 | } else { | |
4881 | let mut multispan = MultiSpan::from_span(lifetimes[0].span); | |
4882 | multispan.push_span_label(span_late, note_msg.to_string()); | |
4883 | self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, | |
4884 | lifetimes[0].id, multispan, primary_msg); | |
4885 | } | |
4886 | return; | |
4887 | } | |
4888 | ||
4889 | if lifetimes.len() > lifetime_defs.len() { | |
4890 | let span = lifetimes[lifetime_defs.len()].span; | |
4891 | let expected_text = count_lifetime_params(lifetime_defs.len()); | |
4892 | let actual_text = count_lifetime_params(lifetimes.len()); | |
4893 | struct_span_err!(self.tcx.sess, span, E0088, | |
4894 | "too many lifetime parameters provided: \ | |
4895 | expected at most {}, found {}", | |
4896 | expected_text, actual_text) | |
4897 | .span_label(span, format!("expected {}", expected_text)) | |
4898 | .emit(); | |
4899 | } else if lifetimes.len() < required_len && !infer_lifetimes { | |
4900 | let expected_text = count_lifetime_params(lifetime_defs.len()); | |
4901 | let actual_text = count_lifetime_params(lifetimes.len()); | |
4902 | struct_span_err!(self.tcx.sess, span, E0090, | |
4903 | "too few lifetime parameters provided: \ | |
4904 | expected {}, found {}", | |
4905 | expected_text, actual_text) | |
4906 | .span_label(span, format!("expected {}", expected_text)) | |
4907 | .emit(); | |
1a4d82fc | 4908 | } |
1a4d82fc | 4909 | } |
1a4d82fc | 4910 | |
ea8adc8c XL |
4911 | /// Report error if there is an explicit type parameter when using `impl Trait`. |
4912 | fn check_impl_trait(&self, | |
4913 | span: Span, | |
4914 | segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { | |
4915 | use hir::SyntheticTyParamKind::*; | |
4916 | ||
4917 | segment.map(|(path_segment, generics)| { | |
4918 | let explicit = !path_segment.infer_types; | |
4919 | let impl_trait = generics.types.iter() | |
4920 | .any(|ty_param| { | |
4921 | match ty_param.synthetic { | |
4922 | Some(ImplTrait) => true, | |
4923 | _ => false, | |
4924 | } | |
4925 | }); | |
4926 | ||
4927 | if explicit && impl_trait { | |
4928 | let mut err = struct_span_err! { | |
4929 | self.tcx.sess, | |
4930 | span, | |
4931 | E0632, | |
4932 | "cannot provide explicit type parameters when `impl Trait` is \ | |
4933 | used in argument position." | |
4934 | }; | |
4935 | ||
4936 | err.emit(); | |
4937 | } | |
4938 | }); | |
4939 | } | |
4940 | ||
a7813a04 XL |
4941 | fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F) |
4942 | -> Ty<'tcx> | |
4943 | where F: Fn() -> Ty<'tcx> | |
4944 | { | |
4945 | let mut ty = self.resolve_type_vars_with_obligations(ty); | |
4946 | ||
4947 | if ty.is_ty_var() { | |
4948 | let alternative = f(); | |
4949 | ||
4950 | // If not, error. | |
4951 | if alternative.is_ty_var() || alternative.references_error() { | |
4952 | if !self.is_tainted_by_errors() { | |
041b39d2 XL |
4953 | type_error_struct!(self.tcx.sess, sp, ty, E0619, |
4954 | "the type of this value must be known in this context") | |
4955 | .emit(); | |
a7813a04 XL |
4956 | } |
4957 | self.demand_suptype(sp, self.tcx.types.err, ty); | |
4958 | ty = self.tcx.types.err; | |
4959 | } else { | |
4960 | self.demand_suptype(sp, alternative, ty); | |
4961 | ty = alternative; | |
4962 | } | |
85aaf69f | 4963 | } |
1a4d82fc | 4964 | |
a7813a04 XL |
4965 | ty |
4966 | } | |
1a4d82fc | 4967 | |
a7813a04 XL |
4968 | // Resolves `typ` by a single level if `typ` is a type variable. If no |
4969 | // resolution is possible, then an error is reported. | |
4970 | pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { | |
4971 | self.structurally_resolve_type_or_else(sp, ty, || { | |
4972 | self.tcx.types.err | |
4973 | }) | |
4974 | } | |
85aaf69f | 4975 | |
cc61c64b XL |
4976 | fn with_breakable_ctxt<F: FnOnce() -> R, R>(&self, id: ast::NodeId, |
4977 | ctxt: BreakableCtxt<'gcx, 'tcx>, f: F) | |
4978 | -> (BreakableCtxt<'gcx, 'tcx>, R) { | |
476ff2be SL |
4979 | let index; |
4980 | { | |
cc61c64b XL |
4981 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); |
4982 | index = enclosing_breakables.stack.len(); | |
4983 | enclosing_breakables.by_id.insert(id, index); | |
4984 | enclosing_breakables.stack.push(ctxt); | |
c34b1796 | 4985 | } |
cc61c64b XL |
4986 | let result = f(); |
4987 | let ctxt = { | |
4988 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
4989 | debug_assert!(enclosing_breakables.stack.len() == index + 1); | |
4990 | enclosing_breakables.by_id.remove(&id).expect("missing breakable context"); | |
4991 | enclosing_breakables.stack.pop().expect("missing breakable context") | |
4992 | }; | |
4993 | (ctxt, result) | |
476ff2be | 4994 | } |
1a4d82fc JJ |
4995 | } |
4996 | ||
8bb4bdeb | 4997 | pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
9e0c209e | 4998 | generics: &hir::Generics, |
1a4d82fc | 4999 | ty: Ty<'tcx>) { |
62682a34 | 5000 | debug!("check_bounds_are_used(n_tps={}, ty={:?})", |
9e0c209e | 5001 | generics.ty_params.len(), ty); |
1a4d82fc JJ |
5002 | |
5003 | // make a vector of booleans initially false, set to true when used | |
9e0c209e SL |
5004 | if generics.ty_params.is_empty() { return; } |
5005 | let mut tps_used = vec![false; generics.ty_params.len()]; | |
1a4d82fc | 5006 | |
c1a9b12d SL |
5007 | for leaf_ty in ty.walk() { |
5008 | if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty { | |
5009 | debug!("Found use of ty param num {}", idx); | |
9e0c209e | 5010 | tps_used[idx as usize - generics.lifetimes.len()] = true; |
abe05a73 XL |
5011 | } else if let ty::TyError = leaf_ty.sty { |
5012 | // If there already another error, do not emit an error for not using a type Parameter | |
5013 | assert!(tcx.sess.err_count() > 0); | |
5014 | return; | |
c1a9b12d SL |
5015 | } |
5016 | } | |
1a4d82fc | 5017 | |
9e0c209e SL |
5018 | for (&used, param) in tps_used.iter().zip(&generics.ty_params) { |
5019 | if !used { | |
8bb4bdeb | 5020 | struct_span_err!(tcx.sess, param.span, E0091, |
1a4d82fc | 5021 | "type parameter `{}` is unused", |
9e0c209e | 5022 | param.name) |
7cac9316 | 5023 | .span_label(param.span, "unused type parameter") |
5bcae85e | 5024 | .emit(); |
1a4d82fc JJ |
5025 | } |
5026 | } | |
5027 | } | |
3b2f2976 XL |
5028 | |
5029 | fn fatally_break_rust(sess: &Session) { | |
5030 | let handler = sess.diagnostic(); | |
5031 | handler.span_bug_no_panic( | |
5032 | MultiSpan::new(), | |
5033 | "It looks like you're trying to break rust; would you like some ICE?", | |
5034 | ); | |
5035 | handler.note_without_error("the compiler expectedly panicked. this is a feature."); | |
5036 | handler.note_without_error( | |
5037 | "we would appreciate a joke overview: \ | |
5038 | https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675" | |
5039 | ); | |
5040 | handler.note_without_error(&format!("rustc {} running on {}", | |
5041 | option_env!("CFG_VERSION").unwrap_or("unknown_version"), | |
5042 | ::session::config::host_triple(), | |
5043 | )); | |
5044 | } |