• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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