1 #![feature(if_let_guard)]
2 #![feature(let_chains)]
3 #![feature(try_blocks)]
4 #![feature(never_type)]
5 #![feature(min_specialization)]
6 #![feature(spec_option_partial_eq)]
7 #![feature(control_flow_enum)]
8 #![feature(drain_filter)]
9 #![allow(rustc::potential_query_instability)]
10 #![recursion_limit = "256"]
16 extern crate rustc_middle;
32 pub mod expr_use_visitor;
36 mod generator_interior;
39 mod mem_categorization;
48 pub use diverges::Diverges;
49 pub use expectation::Expectation;
51 pub use inherited::{Inherited, InheritedBuilder};
53 use crate::check::check_fn;
54 use crate::coercion::DynamicCoerceMany;
55 use crate::gather_locals::GatherLocalsVisitor;
56 use rustc_data_structures::unord::UnordSet;
57 use rustc_errors::{struct_span_err, MultiSpan};
59 use rustc_hir::def::Res;
60 use rustc_hir::intravisit::Visitor;
61 use rustc_hir::{HirIdMap, Node};
62 use rustc_hir_analysis::astconv::AstConv;
63 use rustc_hir_analysis::check::check_abi;
64 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
65 use rustc_middle::traits;
66 use rustc_middle::ty::query::Providers;
67 use rustc_middle::ty::{self, Ty, TyCtxt};
68 use rustc_session::config;
69 use rustc_session::Session;
70 use rustc_span::def_id::{DefId, LocalDefId};
74 macro_rules! type_error_struct {
75 ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
76 let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
78 if $typ.references_error() {
79 err.downgrade_to_delayed_bug();
86 /// The type of a local binding, including the revealed type for anon types.
87 #[derive(Copy, Clone, Debug)]
88 pub struct LocalTy<'tcx> {
90 revealed_ty: Ty<'tcx>,
93 #[derive(Copy, Clone)]
94 pub struct UnsafetyState {
96 pub unsafety: hir::Unsafety,
101 pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
102 UnsafetyState { def, unsafety, from_fn: true }
105 pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
106 use hir::BlockCheckMode;
107 match self.unsafety {
108 // If this unsafe, then if the outer function was already marked as
109 // unsafe we shouldn't attribute the unsafe'ness to the block. This
110 // way the block can be warned about instead of ignoring this
111 // extraneous block (functions are never warned about).
112 hir::Unsafety::Unsafe if self.from_fn => self,
115 let (unsafety, def) = match blk.rules {
116 BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
117 BlockCheckMode::DefaultBlock => (unsafety, self.def),
119 UnsafetyState { def, unsafety, from_fn: false }
125 /// If this `DefId` is a "primary tables entry", returns
126 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
128 /// If this function returns `Some`, then `typeck_results(def_id)` will
129 /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
130 /// may not succeed. In some cases where this function returns `None`
131 /// (notably closures), `typeck_results(def_id)` would wind up
132 /// redirecting to the owning function.
136 ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
137 match tcx.hir().get(id) {
138 Node::Item(item) => match item.kind {
139 hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
140 Some((body, Some(ty), None))
142 hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
145 Node::TraitItem(item) => match item.kind {
146 hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
147 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
148 Some((body, None, Some(sig)))
152 Node::ImplItem(item) => match item.kind {
153 hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
154 hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
157 Node::AnonConst(constant) => Some((constant.body, None, None)),
162 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
163 // Closures' typeck results come from their outermost function,
164 // as they are part of the same "inference environment".
165 let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
166 if typeck_root_def_id != def_id {
167 return tcx.has_typeck_results(typeck_root_def_id);
170 if let Some(def_id) = def_id.as_local() {
171 let id = tcx.hir().local_def_id_to_hir_id(def_id);
172 primary_body_of(tcx, id).is_some()
178 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
179 &*tcx.typeck(def_id).used_trait_imports
182 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
183 tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
186 fn typeck_const_arg<'tcx>(
188 (did, param_did): (LocalDefId, DefId),
189 ) -> &ty::TypeckResults<'tcx> {
190 let fallback = move || tcx.type_of(param_did);
191 typeck_with_fallback(tcx, did, fallback)
194 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
195 if let Some(param_did) = tcx.opt_const_param_of(def_id) {
196 tcx.typeck_const_arg((def_id, param_did))
198 let fallback = move || tcx.type_of(def_id.to_def_id());
199 typeck_with_fallback(tcx, def_id, fallback)
203 /// Used only to get `TypeckResults` for type inference during error recovery.
204 /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
205 fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
206 let fallback = move || {
207 let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
208 tcx.ty_error_with_message(span, "diagnostic only typeck table used")
210 typeck_with_fallback(tcx, def_id, fallback)
213 fn typeck_with_fallback<'tcx>(
216 fallback: impl Fn() -> Ty<'tcx> + 'tcx,
217 ) -> &'tcx ty::TypeckResults<'tcx> {
218 // Closures' typeck results come from their outermost function,
219 // as they are part of the same "inference environment".
220 let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
221 if typeck_root_def_id != def_id {
222 return tcx.typeck(typeck_root_def_id);
225 let id = tcx.hir().local_def_id_to_hir_id(def_id);
226 let span = tcx.hir().span(id);
228 // Figure out what primary body this item has.
229 let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
230 span_bug!(span, "can't type-check body of {:?}", def_id);
232 let body = tcx.hir().body(body_id);
234 let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
235 let param_env = tcx.param_env(def_id);
236 let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
237 let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
238 let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
239 <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
244 check_abi(tcx, id, span, fn_sig.abi());
246 // Compute the function signature from point of view of inside the fn.
247 let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
248 let fn_sig = inh.normalize_associated_types_in(
254 check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
256 let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
257 let expected_type = body_ty
258 .and_then(|ty| match ty.kind {
259 hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
262 .unwrap_or_else(|| match tcx.hir().get(id) {
263 Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
264 Node::Expr(&hir::Expr {
265 kind: hir::ExprKind::ConstBlock(ref anon_const),
267 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
268 kind: TypeVariableOriginKind::TypeInference,
272 kind: hir::TyKind::Typeof(ref anon_const), ..
273 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
274 kind: TypeVariableOriginKind::TypeInference,
277 Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
278 | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
282 .filter_map(|(op, _op_sp)| match op {
283 hir::InlineAsmOperand::Const { anon_const }
284 if anon_const.hir_id == id =>
286 // Inline assembly constants must be integers.
287 Some(fcx.next_int_var())
289 hir::InlineAsmOperand::SymFn { anon_const }
290 if anon_const.hir_id == id =>
292 Some(fcx.next_ty_var(TypeVariableOrigin {
293 kind: TypeVariableOriginKind::MiscVariable,
300 operand_ty.unwrap_or_else(fallback)
307 let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
308 fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
310 // Gather locals in statics (because of block expressions).
311 GatherLocalsVisitor::new(&fcx).visit_body(body);
313 fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
315 fcx.write_ty(id, expected_type);
320 let fallback_has_occurred = fcx.type_inference_fallback();
322 // Even though coercion casts provide type hints, we check casts after fallback for
323 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
325 fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
327 // Closure and generator analysis may run after fallback
328 // because they don't constrain other type variables.
329 // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
330 let prev_constness = fcx.param_env.constness();
331 fcx.param_env = fcx.param_env.without_const();
332 fcx.closure_analyze(body);
333 fcx.param_env = fcx.param_env.with_constness(prev_constness);
334 assert!(fcx.deferred_call_resolutions.borrow().is_empty());
335 // Before the generator analysis, temporary scopes shall be marked to provide more
336 // precise information on types to be captured.
337 fcx.resolve_rvalue_scopes(def_id.to_def_id());
338 fcx.resolve_generator_interiors(def_id.to_def_id());
340 for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
341 let ty = fcx.normalize_ty(span, ty);
342 fcx.require_type_is_sized(ty, span, code);
345 fcx.select_all_obligations_or_error();
347 if !fcx.infcx.is_tainted_by_errors() {
348 fcx.check_transmutes();
353 fcx.infcx.skip_region_resolution();
355 fcx.resolve_type_vars_in_body(body)
358 // Consistency check our TypeckResults instance can hold all ItemLocalIds
359 // it will need to hold.
360 assert_eq!(typeck_results.hir_owner, id.owner);
365 /// When `check_fn` is invoked on a generator (i.e., a body that
366 /// includes yield), it returns back some information about the yield
368 struct GeneratorTypes<'tcx> {
369 /// Type of generator argument / values returned by `yield`.
372 /// Type of value that is yielded.
375 /// Types that are captured (see `GeneratorInterior` for more).
378 /// Indicates if the generator is movable or static (immovable).
379 movability: hir::Movability,
382 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
389 fn maybe_mut_place(m: hir::Mutability) -> Self {
391 hir::Mutability::Mut => Needs::MutPlace,
392 hir::Mutability::Not => Needs::None,
397 #[derive(Debug, Copy, Clone)]
403 pub struct BreakableCtxt<'tcx> {
406 // this is `null` for loops where break with a value is illegal,
407 // such as `while`, `for`, and `while let`
408 coerce: Option<DynamicCoerceMany<'tcx>>,
411 pub struct EnclosingBreakables<'tcx> {
412 stack: Vec<BreakableCtxt<'tcx>>,
413 by_id: HirIdMap<usize>,
416 impl<'tcx> EnclosingBreakables<'tcx> {
417 fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
418 self.opt_find_breakable(target_id).unwrap_or_else(|| {
419 bug!("could not find enclosing breakable with id {}", target_id);
423 fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
424 match self.by_id.get(&target_id) {
425 Some(ix) => Some(&mut self.stack[*ix]),
431 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
436 "expected unit struct, unit variant or constant, found {} `{}`",
438 rustc_hir_pretty::qpath_to_string(qpath),
443 /// Controls whether the arguments are tupled. This is used for the call
446 /// Tupling means that all call-side arguments are packed into a tuple and
447 /// passed as a single parameter. For example, if tupling is enabled, this
450 /// fn f(x: (isize, isize)) {}
452 /// Can be called as:
453 /// ```ignore UNSOLVED (can this be done in user code?)
454 /// # fn f(x: (isize, isize)) {}
459 /// # fn f(x: (isize, isize)) {}
462 #[derive(Clone, Eq, PartialEq)]
463 enum TupleArgumentsFlag {
468 fn fatally_break_rust(sess: &Session) {
469 let handler = sess.diagnostic();
470 handler.span_bug_no_panic(
472 "It looks like you're trying to break rust; would you like some ICE?",
474 handler.note_without_error("the compiler expectedly panicked. this is a feature.");
475 handler.note_without_error(
476 "we would appreciate a joke overview: \
477 https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
479 handler.note_without_error(&format!(
480 "rustc {} running on {}",
481 option_env!("CFG_VERSION").unwrap_or("unknown_version"),
482 config::host_triple(),
486 fn has_expected_num_generic_args<'tcx>(
488 trait_did: Option<DefId>,
491 trait_did.map_or(true, |trait_did| {
492 let generics = tcx.generics_of(trait_did);
493 generics.count() == expected + if generics.has_self { 1 } else { 0 }
497 pub fn provide(providers: &mut Providers) {
498 method::provide(providers);
499 *providers = Providers {
503 diagnostic_only_typeck,