]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_typeck/src/lib.rs
rustc_hir_typeck: fix paths and partially mv files
[rust.git] / compiler / rustc_hir_typeck / src / lib.rs
1 #![feature(if_let_guard)]
2 #![feature(let_chains)]
3 #![feature(try_blocks)]
4 #![feature(never_type)]
5 #![feature(min_specialization)]
6 #![feature(control_flow_enum)]
7 #![feature(drain_filter)]
8 #![allow(rustc::potential_query_instability)]
9
10 #[macro_use]
11 extern crate tracing;
12
13 #[macro_use]
14 extern crate rustc_middle;
15
16 mod _match;
17 mod autoderef;
18 mod callee;
19 // Used by clippy;
20 pub mod cast;
21 mod check;
22 mod closure;
23 mod coercion;
24 mod demand;
25 mod diverges;
26 mod errors;
27 mod expectation;
28 mod expr;
29 // Used by clippy;
30 pub mod expr_use_visitor;
31 mod fallback;
32 mod fn_ctxt;
33 mod gather_locals;
34 mod generator_interior;
35 mod inherited;
36 mod intrinsicck;
37 mod mem_categorization;
38 mod method;
39 mod op;
40 mod pat;
41 mod place_op;
42 mod rvalue_scopes;
43 mod upvar;
44 mod writeback;
45
46 pub use diverges::Diverges;
47 pub use expectation::Expectation;
48 pub use fn_ctxt::*;
49 pub use inherited::{Inherited, InheritedBuilder};
50
51 use crate::check::check_fn;
52 use crate::coercion::DynamicCoerceMany;
53 use crate::gather_locals::GatherLocalsVisitor;
54 use rustc_data_structures::fx::FxHashSet;
55 use rustc_errors::{struct_span_err, MultiSpan};
56 use rustc_hir as hir;
57 use rustc_hir::def::Res;
58 use rustc_hir::intravisit::Visitor;
59 use rustc_hir::{HirIdMap, Node};
60 use rustc_hir_analysis::astconv::AstConv;
61 use rustc_hir_analysis::check::check_abi;
62 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
63 use rustc_middle::traits;
64 use rustc_middle::ty::query::Providers;
65 use rustc_middle::ty::{self, Ty, TyCtxt};
66 use rustc_session::config;
67 use rustc_session::Session;
68 use rustc_span::def_id::{DefId, LocalDefId};
69 use rustc_span::Span;
70
71 #[macro_export]
72 macro_rules! type_error_struct {
73     ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
74         let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
75
76         if $typ.references_error() {
77             err.downgrade_to_delayed_bug();
78         }
79
80         err
81     })
82 }
83
84 /// The type of a local binding, including the revealed type for anon types.
85 #[derive(Copy, Clone, Debug)]
86 pub struct LocalTy<'tcx> {
87     decl_ty: Ty<'tcx>,
88     revealed_ty: Ty<'tcx>,
89 }
90
91 #[derive(Copy, Clone)]
92 pub struct UnsafetyState {
93     pub def: hir::HirId,
94     pub unsafety: hir::Unsafety,
95     from_fn: bool,
96 }
97
98 impl UnsafetyState {
99     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
100         UnsafetyState { def, unsafety, from_fn: true }
101     }
102
103     pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
104         use hir::BlockCheckMode;
105         match self.unsafety {
106             // If this unsafe, then if the outer function was already marked as
107             // unsafe we shouldn't attribute the unsafe'ness to the block. This
108             // way the block can be warned about instead of ignoring this
109             // extraneous block (functions are never warned about).
110             hir::Unsafety::Unsafe if self.from_fn => self,
111
112             unsafety => {
113                 let (unsafety, def) = match blk.rules {
114                     BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
115                     BlockCheckMode::DefaultBlock => (unsafety, self.def),
116                 };
117                 UnsafetyState { def, unsafety, from_fn: false }
118             }
119         }
120     }
121 }
122
123 /// If this `DefId` is a "primary tables entry", returns
124 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
125 ///
126 /// If this function returns `Some`, then `typeck_results(def_id)` will
127 /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
128 /// may not succeed. In some cases where this function returns `None`
129 /// (notably closures), `typeck_results(def_id)` would wind up
130 /// redirecting to the owning function.
131 fn primary_body_of(
132     tcx: TyCtxt<'_>,
133     id: hir::HirId,
134 ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
135     match tcx.hir().get(id) {
136         Node::Item(item) => match item.kind {
137             hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
138                 Some((body, Some(ty), None))
139             }
140             hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
141             _ => None,
142         },
143         Node::TraitItem(item) => match item.kind {
144             hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
145             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
146                 Some((body, None, Some(sig)))
147             }
148             _ => None,
149         },
150         Node::ImplItem(item) => match item.kind {
151             hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
152             hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
153             _ => None,
154         },
155         Node::AnonConst(constant) => Some((constant.body, None, None)),
156         _ => None,
157     }
158 }
159
160 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
161     // Closures' typeck results come from their outermost function,
162     // as they are part of the same "inference environment".
163     let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
164     if typeck_root_def_id != def_id {
165         return tcx.has_typeck_results(typeck_root_def_id);
166     }
167
168     if let Some(def_id) = def_id.as_local() {
169         let id = tcx.hir().local_def_id_to_hir_id(def_id);
170         primary_body_of(tcx, id).is_some()
171     } else {
172         false
173     }
174 }
175
176 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
177     &*tcx.typeck(def_id).used_trait_imports
178 }
179
180 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
181     tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
182 }
183
184 fn typeck_const_arg<'tcx>(
185     tcx: TyCtxt<'tcx>,
186     (did, param_did): (LocalDefId, DefId),
187 ) -> &ty::TypeckResults<'tcx> {
188     let fallback = move || tcx.type_of(param_did);
189     typeck_with_fallback(tcx, did, fallback)
190 }
191
192 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
193     if let Some(param_did) = tcx.opt_const_param_of(def_id) {
194         tcx.typeck_const_arg((def_id, param_did))
195     } else {
196         let fallback = move || tcx.type_of(def_id.to_def_id());
197         typeck_with_fallback(tcx, def_id, fallback)
198     }
199 }
200
201 /// Used only to get `TypeckResults` for type inference during error recovery.
202 /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
203 fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
204     let fallback = move || {
205         let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
206         tcx.ty_error_with_message(span, "diagnostic only typeck table used")
207     };
208     typeck_with_fallback(tcx, def_id, fallback)
209 }
210
211 fn typeck_with_fallback<'tcx>(
212     tcx: TyCtxt<'tcx>,
213     def_id: LocalDefId,
214     fallback: impl Fn() -> Ty<'tcx> + 'tcx,
215 ) -> &'tcx ty::TypeckResults<'tcx> {
216     // Closures' typeck results come from their outermost function,
217     // as they are part of the same "inference environment".
218     let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
219     if typeck_root_def_id != def_id {
220         return tcx.typeck(typeck_root_def_id);
221     }
222
223     let id = tcx.hir().local_def_id_to_hir_id(def_id);
224     let span = tcx.hir().span(id);
225
226     // Figure out what primary body this item has.
227     let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
228         span_bug!(span, "can't type-check body of {:?}", def_id);
229     });
230     let body = tcx.hir().body(body_id);
231
232     let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
233         let param_env = tcx.param_env(def_id);
234         let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
235             let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
236                 let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
237                 <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
238             } else {
239                 tcx.fn_sig(def_id)
240             };
241
242             check_abi(tcx, id, span, fn_sig.abi());
243
244             // Compute the function signature from point of view of inside the fn.
245             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
246             let fn_sig = inh.normalize_associated_types_in(
247                 body.value.span,
248                 body_id.hir_id,
249                 param_env,
250                 fn_sig,
251             );
252             check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
253         } else {
254             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
255             let expected_type = body_ty
256                 .and_then(|ty| match ty.kind {
257                     hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
258                     _ => None,
259                 })
260                 .unwrap_or_else(|| match tcx.hir().get(id) {
261                     Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
262                         Node::Expr(&hir::Expr {
263                             kind: hir::ExprKind::ConstBlock(ref anon_const),
264                             ..
265                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
266                             kind: TypeVariableOriginKind::TypeInference,
267                             span,
268                         }),
269                         Node::Ty(&hir::Ty {
270                             kind: hir::TyKind::Typeof(ref anon_const), ..
271                         }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
272                             kind: TypeVariableOriginKind::TypeInference,
273                             span,
274                         }),
275                         Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
276                         | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
277                             let operand_ty = asm
278                                 .operands
279                                 .iter()
280                                 .filter_map(|(op, _op_sp)| match op {
281                                     hir::InlineAsmOperand::Const { anon_const }
282                                         if anon_const.hir_id == id =>
283                                     {
284                                         // Inline assembly constants must be integers.
285                                         Some(fcx.next_int_var())
286                                     }
287                                     hir::InlineAsmOperand::SymFn { anon_const }
288                                         if anon_const.hir_id == id =>
289                                     {
290                                         Some(fcx.next_ty_var(TypeVariableOrigin {
291                                             kind: TypeVariableOriginKind::MiscVariable,
292                                             span,
293                                         }))
294                                     }
295                                     _ => None,
296                                 })
297                                 .next();
298                             operand_ty.unwrap_or_else(fallback)
299                         }
300                         _ => fallback(),
301                     },
302                     _ => fallback(),
303                 });
304
305             let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
306             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
307
308             // Gather locals in statics (because of block expressions).
309             GatherLocalsVisitor::new(&fcx).visit_body(body);
310
311             fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
312
313             fcx.write_ty(id, expected_type);
314
315             fcx
316         };
317
318         let fallback_has_occurred = fcx.type_inference_fallback();
319
320         // Even though coercion casts provide type hints, we check casts after fallback for
321         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
322         fcx.check_casts();
323         fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
324
325         // Closure and generator analysis may run after fallback
326         // because they don't constrain other type variables.
327         // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
328         let prev_constness = fcx.param_env.constness();
329         fcx.param_env = fcx.param_env.without_const();
330         fcx.closure_analyze(body);
331         fcx.param_env = fcx.param_env.with_constness(prev_constness);
332         assert!(fcx.deferred_call_resolutions.borrow().is_empty());
333         // Before the generator analysis, temporary scopes shall be marked to provide more
334         // precise information on types to be captured.
335         fcx.resolve_rvalue_scopes(def_id.to_def_id());
336         fcx.resolve_generator_interiors(def_id.to_def_id());
337
338         for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
339             let ty = fcx.normalize_ty(span, ty);
340             fcx.require_type_is_sized(ty, span, code);
341         }
342
343         fcx.select_all_obligations_or_error();
344
345         if !fcx.infcx.is_tainted_by_errors() {
346             fcx.check_transmutes();
347         }
348
349         fcx.check_asms();
350
351         fcx.infcx.skip_region_resolution();
352
353         fcx.resolve_type_vars_in_body(body)
354     });
355
356     // Consistency check our TypeckResults instance can hold all ItemLocalIds
357     // it will need to hold.
358     assert_eq!(typeck_results.hir_owner, id.owner);
359
360     typeck_results
361 }
362
363 /// When `check_fn` is invoked on a generator (i.e., a body that
364 /// includes yield), it returns back some information about the yield
365 /// points.
366 struct GeneratorTypes<'tcx> {
367     /// Type of generator argument / values returned by `yield`.
368     resume_ty: Ty<'tcx>,
369
370     /// Type of value that is yielded.
371     yield_ty: Ty<'tcx>,
372
373     /// Types that are captured (see `GeneratorInterior` for more).
374     interior: Ty<'tcx>,
375
376     /// Indicates if the generator is movable or static (immovable).
377     movability: hir::Movability,
378 }
379
380 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
381 pub enum Needs {
382     MutPlace,
383     None,
384 }
385
386 impl Needs {
387     fn maybe_mut_place(m: hir::Mutability) -> Self {
388         match m {
389             hir::Mutability::Mut => Needs::MutPlace,
390             hir::Mutability::Not => Needs::None,
391         }
392     }
393 }
394
395 #[derive(Debug, Copy, Clone)]
396 pub enum PlaceOp {
397     Deref,
398     Index,
399 }
400
401 pub struct BreakableCtxt<'tcx> {
402     may_break: bool,
403
404     // this is `null` for loops where break with a value is illegal,
405     // such as `while`, `for`, and `while let`
406     coerce: Option<DynamicCoerceMany<'tcx>>,
407 }
408
409 pub struct EnclosingBreakables<'tcx> {
410     stack: Vec<BreakableCtxt<'tcx>>,
411     by_id: HirIdMap<usize>,
412 }
413
414 impl<'tcx> EnclosingBreakables<'tcx> {
415     fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
416         self.opt_find_breakable(target_id).unwrap_or_else(|| {
417             bug!("could not find enclosing breakable with id {}", target_id);
418         })
419     }
420
421     fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
422         match self.by_id.get(&target_id) {
423             Some(ix) => Some(&mut self.stack[*ix]),
424             None => None,
425         }
426     }
427 }
428
429 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
430     struct_span_err!(
431         tcx.sess,
432         span,
433         E0533,
434         "expected unit struct, unit variant or constant, found {} `{}`",
435         res.descr(),
436         rustc_hir_pretty::qpath_to_string(qpath),
437     )
438     .emit();
439 }
440
441 /// Controls whether the arguments are tupled. This is used for the call
442 /// operator.
443 ///
444 /// Tupling means that all call-side arguments are packed into a tuple and
445 /// passed as a single parameter. For example, if tupling is enabled, this
446 /// function:
447 /// ```
448 /// fn f(x: (isize, isize)) {}
449 /// ```
450 /// Can be called as:
451 /// ```ignore UNSOLVED (can this be done in user code?)
452 /// # fn f(x: (isize, isize)) {}
453 /// f(1, 2);
454 /// ```
455 /// Instead of:
456 /// ```
457 /// # fn f(x: (isize, isize)) {}
458 /// f((1, 2));
459 /// ```
460 #[derive(Clone, Eq, PartialEq)]
461 enum TupleArgumentsFlag {
462     DontTupleArguments,
463     TupleArguments,
464 }
465
466 fn fatally_break_rust(sess: &Session) {
467     let handler = sess.diagnostic();
468     handler.span_bug_no_panic(
469         MultiSpan::new(),
470         "It looks like you're trying to break rust; would you like some ICE?",
471     );
472     handler.note_without_error("the compiler expectedly panicked. this is a feature.");
473     handler.note_without_error(
474         "we would appreciate a joke overview: \
475          https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
476     );
477     handler.note_without_error(&format!(
478         "rustc {} running on {}",
479         option_env!("CFG_VERSION").unwrap_or("unknown_version"),
480         config::host_triple(),
481     ));
482 }
483
484 fn has_expected_num_generic_args<'tcx>(
485     tcx: TyCtxt<'tcx>,
486     trait_did: Option<DefId>,
487     expected: usize,
488 ) -> bool {
489     trait_did.map_or(true, |trait_did| {
490         let generics = tcx.generics_of(trait_did);
491         generics.count() == expected + if generics.has_self { 1 } else { 0 }
492     })
493 }
494
495 pub fn provide(providers: &mut Providers) {
496     method::provide(providers);
497     *providers = Providers {
498         typeck_item_bodies,
499         typeck_const_arg,
500         typeck,
501         diagnostic_only_typeck,
502         has_typeck_results,
503         used_trait_imports,
504         ..*providers
505     };
506 }