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