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