]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/lib.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / lib.rs
CommitLineData
1a4d82fc
JJ
1/*!
2
9fa01778 3# typeck
1a4d82fc
JJ
4
5The type checker is responsible for:
6
0731742a
XL
71. Determining the type of each expression.
82. Resolving methods and traits.
93. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
1a4d82fc
JJ
10 Well, dear reader, read on)
11
0731742a 12The main entry point is `check_crate()`. Type checking operates in
1a4d82fc
JJ
13several major phases:
14
151. The collect phase first passes over all items and determines their
16 type, without examining their "innards".
17
0731742a 182. Variance inference then runs to compute the variance of each parameter.
1a4d82fc 19
0731742a 203. Coherence checks for overlapping or orphaned impls.
1a4d82fc
JJ
21
224. Finally, the check phase then checks function bodies and so forth.
23 Within the check phase, we check each function body one at a time
24 (bodies of function expressions are checked as part of the
25 containing function). Inference is used to supply types wherever
26 they are unknown. The actual checking of a function itself has
27 several phases (check, regionck, writeback), as discussed in the
28 documentation for the `check` module.
29
30The type checker is defined into various submodules which are documented
31independently:
32
33- astconv: converts the AST representation of types
0731742a 34 into the `ty` representation.
1a4d82fc
JJ
35
36- collect: computes the types of each top-level item and enters them into
0731742a 37 the `tcx.types` table for later use.
1a4d82fc 38
0731742a 39- coherence: enforces coherence rules, builds some tables.
1a4d82fc
JJ
40
41- variance: variance inference
42
abe05a73
XL
43- outlives: outlives inference
44
1a4d82fc
JJ
45- check: walks over function bodies and type checks them, inferring types for
46 local variables, type parameters, etc as necessary.
47
48- infer: finds the types to use for each type variable such that
49 all subtyping and assignment constraints are met. In essence, the check
50 module specifies the constraints, and the infer module solves them.
51
0731742a 52## Note
1a4d82fc
JJ
53
54This API is completely unstable and subject to change.
55
56*/
9cc50fc6 57
1b1a35ee 58#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
29967ef6 59#![feature(array_value_iter)]
60c5eb7d 60#![feature(bool_to_option)]
1a4d82fc 61#![feature(box_syntax)]
2c00a5a8 62#![feature(crate_visibility_modifier)]
dc9dc135 63#![feature(in_band_lifetimes)]
fc512014 64#![feature(is_sorted)]
0bf4aa26 65#![feature(nll)]
ba9703b0 66#![feature(or_patterns)]
dfeec247 67#![feature(try_blocks)]
0531ce1d 68#![feature(never_type)]
ba9703b0 69#![feature(slice_partition_dedup)]
29967ef6 70#![feature(control_flow_enum)]
dfeec247 71#![recursion_limit = "256"]
7cac9316 72
dfeec247 73#[macro_use]
3dfed10e 74extern crate tracing;
94b46f34 75
dfeec247 76#[macro_use]
ba9703b0 77extern crate rustc_middle;
1a4d82fc 78
3dfed10e
XL
79// These are used by Clippy.
80pub mod check;
60c5eb7d 81pub mod expr_use_visitor;
85aaf69f 82
2c00a5a8 83mod astconv;
3dfed10e 84mod bounds;
7cac9316 85mod check_unused;
2c00a5a8 86mod coherence;
7cac9316 87mod collect;
532ac7d7 88mod constrained_generic_params;
1b1a35ee 89mod errors;
476ff2be 90mod impl_wf_check;
60c5eb7d 91mod mem_categorization;
abe05a73 92mod outlives;
dfeec247 93mod structured_errors;
7cac9316 94mod variance;
1a4d82fc 95
ba9703b0 96use rustc_errors::{struct_span_err, ErrorReported};
dfeec247 97use rustc_hir as hir;
f9f354fc 98use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
dfeec247 99use rustc_hir::Node;
74b04a01 100use rustc_infer::infer::{InferOk, TyCtxtInferExt};
ba9703b0
XL
101use rustc_infer::traits::TraitEngineExt as _;
102use rustc_middle::middle;
103use rustc_middle::ty::query::Providers;
104use rustc_middle::ty::{self, Ty, TyCtxt};
105use rustc_middle::util;
106use rustc_session::config::EntryFnType;
f9652781 107use rustc_span::{symbol::sym, Span, DUMMY_SP};
dfeec247 108use rustc_target::spec::abi::Abi;
ba9703b0
XL
109use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
110use rustc_trait_selection::traits::{
111 ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
112};
60c5eb7d 113
0731742a
XL
114use std::iter;
115
3dfed10e
XL
116use astconv::AstConv;
117use bounds::Bounds;
1a4d82fc 118
dfeec247 119fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
532ac7d7 120 if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
dfeec247
XL
121 let mut err = struct_span_err!(
122 tcx.sess,
123 span,
124 E0045,
125 "C-variadic function must have C or cdecl calling convention"
126 );
532ac7d7 127 err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
c1a9b12d
SL
128 }
129}
130
dc9dc135
XL
131fn require_same_types<'tcx>(
132 tcx: TyCtxt<'tcx>,
133 cause: &ObligationCause<'tcx>,
134 expected: Ty<'tcx>,
135 actual: Ty<'tcx>,
136) -> bool {
041b39d2 137 tcx.infer_ctxt().enter(|ref infcx| {
0531ce1d
XL
138 let param_env = ty::ParamEnv::empty();
139 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
7cac9316 140 match infcx.at(&cause, param_env).eq(expected, actual) {
c30ab7b3 141 Ok(InferOk { obligations, .. }) => {
cc61c64b 142 fulfill_cx.register_predicate_obligations(infcx, obligations);
c30ab7b3
SL
143 }
144 Err(err) => {
32a655c1 145 infcx.report_mismatched_types(cause, expected, actual, err).emit();
cc61c64b
XL
146 return false;
147 }
148 }
149
150 match fulfill_cx.select_all_or_error(infcx) {
151 Ok(()) => true,
152 Err(errors) => {
0531ce1d 153 infcx.report_fulfillment_errors(&errors, None, false);
c30ab7b3
SL
154 false
155 }
1a4d82fc 156 }
a7813a04 157 })
1a4d82fc
JJ
158}
159
f9f354fc 160fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
3dfed10e 161 let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
9fa01778 162 let main_span = tcx.def_span(main_def_id);
7cac9316 163 let main_t = tcx.type_of(main_def_id);
1b1a35ee 164 match main_t.kind() {
b7449926 165 ty::FnDef(..) => {
dc9dc135 166 if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
ba9703b0 167 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
0bf4aa26
XL
168 let mut error = false;
169 if !generics.params.is_empty() {
170 let msg = "`main` function is not allowed to have generic \
dfeec247
XL
171 parameters"
172 .to_owned();
0bf4aa26
XL
173 let label = "`main` cannot have generic parameters".to_string();
174 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
175 .span_label(generics.span, label)
176 .emit();
177 error = true;
178 }
179 if let Some(sp) = generics.where_clause.span() {
dfeec247
XL
180 struct_span_err!(
181 tcx.sess,
182 sp,
183 E0646,
184 "`main` function is not allowed to have a `where` clause"
185 )
186 .span_label(sp, "`main` cannot have a `where` clause")
187 .emit();
0bf4aa26
XL
188 error = true;
189 }
ba9703b0
XL
190 if let hir::IsAsync::Async = sig.header.asyncness {
191 let span = tcx.sess.source_map().guess_head_span(it.span);
192 struct_span_err!(
193 tcx.sess,
194 span,
195 E0752,
196 "`main` function is not allowed to be `async`"
197 )
198 .span_label(span, "`main` function is not allowed to be `async`")
199 .emit();
200 error = true;
201 }
f9652781
XL
202
203 for attr in it.attrs {
3dfed10e 204 if tcx.sess.check_name(attr, sym::track_caller) {
f9652781
XL
205 tcx.sess
206 .struct_span_err(
207 attr.span,
208 "`main` function is not allowed to be `#[track_caller]`",
209 )
210 .span_label(
211 main_span,
212 "`main` function is not allowed to be `#[track_caller]`",
213 )
214 .emit();
215 error = true;
216 }
217 }
218
0bf4aa26
XL
219 if error {
220 return;
1a4d82fc
JJ
221 }
222 }
1a4d82fc 223 }
ff7c6d11
XL
224
225 let actual = tcx.fn_sig(main_def_id);
0531ce1d 226 let expected_return_type = if tcx.lang_items().termination().is_some() {
ff7c6d11
XL
227 // we take the return type of the given main function, the real check is done
228 // in `check_fn`
fc512014 229 actual.output()
ff7c6d11
XL
230 } else {
231 // standard () main return type
fc512014 232 ty::Binder::dummy(tcx.mk_unit())
ff7c6d11
XL
233 };
234
fc512014
XL
235 let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
236 tcx.mk_fn_sig(
237 iter::empty(),
238 expected_return_type,
239 false,
240 hir::Unsafety::Normal,
241 Abi::Rust,
242 )
243 }));
1a4d82fc 244
5bcae85e 245 require_same_types(
8bb4bdeb 246 tcx,
476ff2be 247 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
c30ab7b3 248 se_ty,
dfeec247
XL
249 tcx.mk_fn_ptr(actual),
250 );
1a4d82fc
JJ
251 }
252 _ => {
dfeec247 253 span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
1a4d82fc
JJ
254 }
255 }
256}
257
f9f354fc 258fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
3dfed10e 259 let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
9fa01778 260 let start_span = tcx.def_span(start_def_id);
7cac9316 261 let start_t = tcx.type_of(start_def_id);
1b1a35ee 262 match start_t.kind() {
b7449926 263 ty::FnDef(..) => {
dc9dc135 264 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
ba9703b0 265 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
0bf4aa26
XL
266 let mut error = false;
267 if !generics.params.is_empty() {
dfeec247
XL
268 struct_span_err!(
269 tcx.sess,
270 generics.span,
271 E0132,
272 "start function is not allowed to have type parameters"
273 )
274 .span_label(generics.span, "start function cannot have type parameters")
275 .emit();
0bf4aa26
XL
276 error = true;
277 }
278 if let Some(sp) = generics.where_clause.span() {
dfeec247
XL
279 struct_span_err!(
280 tcx.sess,
281 sp,
282 E0647,
283 "start function is not allowed to have a `where` clause"
284 )
285 .span_label(sp, "start function cannot have a `where` clause")
286 .emit();
0bf4aa26
XL
287 error = true;
288 }
ba9703b0
XL
289 if let hir::IsAsync::Async = sig.header.asyncness {
290 let span = tcx.sess.source_map().guess_head_span(it.span);
291 struct_span_err!(
292 tcx.sess,
293 span,
294 E0752,
f9652781 295 "`start` is not allowed to be `async`"
ba9703b0 296 )
f9652781 297 .span_label(span, "`start` is not allowed to be `async`")
ba9703b0
XL
298 .emit();
299 error = true;
300 }
f9652781
XL
301
302 for attr in it.attrs {
3dfed10e 303 if tcx.sess.check_name(attr, sym::track_caller) {
f9652781
XL
304 tcx.sess
305 .struct_span_err(
306 attr.span,
307 "`start` is not allowed to be `#[track_caller]`",
308 )
309 .span_label(
310 start_span,
311 "`start` is not allowed to be `#[track_caller]`",
312 )
313 .emit();
314 error = true;
315 }
316 }
317
0bf4aa26
XL
318 if error {
319 return;
1a4d82fc
JJ
320 }
321 }
1a4d82fc
JJ
322 }
323
29967ef6 324 let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
dfeec247
XL
325 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
326 tcx.types.isize,
327 false,
328 hir::Unsafety::Normal,
329 Abi::Rust,
330 )));
1a4d82fc 331
5bcae85e 332 require_same_types(
8bb4bdeb 333 tcx,
476ff2be 334 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
c30ab7b3 335 se_ty,
dfeec247
XL
336 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
337 );
1a4d82fc
JJ
338 }
339 _ => {
dfeec247 340 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
1a4d82fc
JJ
341 }
342 }
343}
344
416331ca 345fn check_for_entry_fn(tcx: TyCtxt<'_>) {
9fa01778
XL
346 match tcx.entry_fn(LOCAL_CRATE) {
347 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
348 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
349 _ => {}
1a4d82fc
JJ
350 }
351}
352
f035d41b 353pub fn provide(providers: &mut Providers) {
8bb4bdeb
XL
354 collect::provide(providers);
355 coherence::provide(providers);
356 check::provide(providers);
7cac9316 357 variance::provide(providers);
abe05a73 358 outlives::provide(providers);
9fa01778 359 impl_wf_check::provide(providers);
8bb4bdeb
XL
360}
361
416331ca 362pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
dfeec247 363 let _prof_timer = tcx.sess.timer("type_check_crate");
b7449926 364
1a4d82fc
JJ
365 // this ensures that later parts of type checking can assume that items
366 // have valid types and not error
1b1a35ee 367 // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
54a0048b 368 tcx.sess.track_errors(|| {
dfeec247 369 tcx.sess.time("type_collecting", || {
532ac7d7 370 for &module in tcx.hir().krate().modules.keys() {
e74abb32 371 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
532ac7d7
XL
372 }
373 });
54a0048b 374 })?;
1a4d82fc 375
9fa01778
XL
376 if tcx.features().rustc_attrs {
377 tcx.sess.track_errors(|| {
dfeec247 378 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
9fa01778
XL
379 })?;
380 }
abe05a73 381
476ff2be 382 tcx.sess.track_errors(|| {
dfeec247 383 tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
476ff2be
SL
384 })?;
385
54a0048b 386 tcx.sess.track_errors(|| {
dfeec247 387 tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
54a0048b 388 })?;
1a4d82fc 389
9fa01778
XL
390 if tcx.features().rustc_attrs {
391 tcx.sess.track_errors(|| {
dfeec247 392 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
9fa01778
XL
393 })?;
394 }
7cac9316 395
dc9dc135 396 tcx.sess.track_errors(|| {
dfeec247 397 tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
dc9dc135 398 })?;
1a4d82fc 399
3dfed10e 400 // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
dfeec247 401 tcx.sess.time("item_types_checking", || {
48663c56 402 for &module in tcx.hir().krate().modules.keys() {
e74abb32 403 tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
48663c56
XL
404 }
405 });
e9174d1e 406
dfeec247 407 tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
e9174d1e 408
a7813a04 409 check_unused::check_crate(tcx);
8bb4bdeb 410 check_for_entry_fn(tcx);
7453a54e 411
dfeec247 412 if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
1a4d82fc 413}
d9579d0f 414
532ac7d7 415/// A quasi-deprecated helper used in rustdoc and clippy to get
7cac9316 416/// the type from a HIR node.
dfeec247 417pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
dc9dc135
XL
418 // In case there are any projections, etc., find the "environment"
419 // def-ID that will be used to determine the traits/predicates in
7cac9316 420 // scope. This is derived from the enclosing item-like thing.
532ac7d7 421 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
416331ca 422 let env_def_id = tcx.hir().local_def_id(env_node_id);
f9f354fc 423 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
0bf4aa26 424
ff7c6d11
XL
425 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
426}
427
dc9dc135
XL
428pub fn hir_trait_to_predicates<'tcx>(
429 tcx: TyCtxt<'tcx>,
dfeec247 430 hir_trait: &hir::TraitRef<'_>,
ba9703b0 431 self_ty: Ty<'tcx>,
416331ca 432) -> Bounds<'tcx> {
dc9dc135
XL
433 // In case there are any projections, etc., find the "environment"
434 // def-ID that will be used to determine the traits/predicates in
ff7c6d11 435 // scope. This is derived from the enclosing item-like thing.
532ac7d7 436 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
416331ca 437 let env_def_id = tcx.hir().local_def_id(env_hir_id);
f9f354fc 438 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
dc9dc135 439 let mut bounds = Bounds::default();
416331ca 440 let _ = AstConv::instantiate_poly_trait_ref_inner(
dfeec247
XL
441 &item_cx,
442 hir_trait,
443 DUMMY_SP,
74b04a01 444 hir::Constness::NotConst,
ba9703b0 445 self_ty,
dfeec247
XL
446 &mut bounds,
447 true,
ff7c6d11 448 );
0bf4aa26 449
416331ca 450 bounds
7cac9316 451}