]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_typeck/src/lib.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / lib.rs
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
deleted file mode 100644 (file)
index b1ce972..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/*!
-
-# typeck
-
-The type checker is responsible for:
-
-1. Determining the type of each expression.
-2. Resolving methods and traits.
-3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
-   Well, dear reader, read on.)
-
-The main entry point is [`check_crate()`]. Type checking operates in
-several major phases:
-
-1. The collect phase first passes over all items and determines their
-   type, without examining their "innards".
-
-2. Variance inference then runs to compute the variance of each parameter.
-
-3. Coherence checks for overlapping or orphaned impls.
-
-4. Finally, the check phase then checks function bodies and so forth.
-   Within the check phase, we check each function body one at a time
-   (bodies of function expressions are checked as part of the
-   containing function).  Inference is used to supply types wherever
-   they are unknown. The actual checking of a function itself has
-   several phases (check, regionck, writeback), as discussed in the
-   documentation for the [`check`] module.
-
-The type checker is defined into various submodules which are documented
-independently:
-
-- astconv: converts the AST representation of types
-  into the `ty` representation.
-
-- collect: computes the types of each top-level item and enters them into
-  the `tcx.types` table for later use.
-
-- coherence: enforces coherence rules, builds some tables.
-
-- variance: variance inference
-
-- outlives: outlives inference
-
-- check: walks over function bodies and type checks them, inferring types for
-  local variables, type parameters, etc as necessary.
-
-- infer: finds the types to use for each type variable such that
-  all subtyping and assignment constraints are met.  In essence, the check
-  module specifies the constraints, and the infer module solves them.
-
-## Note
-
-This API is completely unstable and subject to change.
-
-*/
-
-#![allow(rustc::potential_query_instability)]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(box_patterns)]
-#![feature(control_flow_enum)]
-#![feature(drain_filter)]
-#![feature(hash_drain_filter)]
-#![feature(if_let_guard)]
-#![feature(is_sorted)]
-#![feature(iter_intersperse)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
-#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
-#![feature(min_specialization)]
-#![feature(never_type)]
-#![feature(once_cell)]
-#![feature(slice_partition_dedup)]
-#![feature(try_blocks)]
-#![feature(is_some_with)]
-#![feature(type_alias_impl_trait)]
-#![recursion_limit = "256"]
-
-#[macro_use]
-extern crate tracing;
-
-#[macro_use]
-extern crate rustc_middle;
-
-// These are used by Clippy.
-pub mod check;
-pub mod expr_use_visitor;
-
-mod astconv;
-mod bounds;
-mod check_unused;
-mod coherence;
-mod collect;
-mod constrained_generic_params;
-mod errors;
-pub mod hir_wf_check;
-mod impl_wf_check;
-mod mem_categorization;
-mod outlives;
-mod structured_errors;
-mod variance;
-
-use rustc_errors::{struct_span_err, ErrorGuaranteed};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_hir::{Node, CRATE_HIR_ID};
-use rustc_infer::infer::{InferOk, TyCtxtInferExt};
-use rustc_middle::middle;
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::util;
-use rustc_session::config::EntryFnType;
-use rustc_span::{symbol::sym, Span, DUMMY_SP};
-use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
-
-use std::iter;
-
-use astconv::AstConv;
-use bounds::Bounds;
-
-fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
-    match (decl.c_variadic, abi) {
-        // The function has the correct calling convention, or isn't a "C-variadic" function.
-        (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
-        // The function is a "C-variadic" function with an incorrect calling convention.
-        (true, _) => {
-            let mut err = struct_span_err!(
-                tcx.sess,
-                span,
-                E0045,
-                "C-variadic function must have C or cdecl calling convention"
-            );
-            err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
-        }
-    }
-}
-
-fn require_same_types<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cause: &ObligationCause<'tcx>,
-    expected: Ty<'tcx>,
-    actual: Ty<'tcx>,
-) -> bool {
-    tcx.infer_ctxt().enter(|ref infcx| {
-        let param_env = ty::ParamEnv::empty();
-        let errors = match infcx.at(cause, param_env).eq(expected, actual) {
-            Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
-            Err(err) => {
-                infcx.report_mismatched_types(cause, expected, actual, err).emit();
-                return false;
-            }
-        };
-
-        match &errors[..] {
-            [] => true,
-            errors => {
-                infcx.report_fulfillment_errors(errors, None, false);
-                false
-            }
-        }
-    })
-}
-
-fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
-    let main_fnsig = tcx.fn_sig(main_def_id);
-    let main_span = tcx.def_span(main_def_id);
-
-    fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId {
-        if let Some(local_def_id) = def_id.as_local() {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
-            let hir_type = tcx.type_of(local_def_id);
-            if !matches!(hir_type.kind(), ty::FnDef(..)) {
-                span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
-            }
-            hir_id
-        } else {
-            CRATE_HIR_ID
-        }
-    }
-
-    fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-        if !def_id.is_local() {
-            return None;
-        }
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        match tcx.hir().find(hir_id) {
-            Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
-                if !generics.params.is_empty() {
-                    Some(generics.span)
-                } else {
-                    None
-                }
-            }
-            _ => {
-                span_bug!(tcx.def_span(def_id), "main has a non-function type");
-            }
-        }
-    }
-
-    fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-        if !def_id.is_local() {
-            return None;
-        }
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        match tcx.hir().find(hir_id) {
-            Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
-                Some(generics.where_clause_span)
-            }
-            _ => {
-                span_bug!(tcx.def_span(def_id), "main has a non-function type");
-            }
-        }
-    }
-
-    fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-        if !def_id.is_local() {
-            return None;
-        }
-        Some(tcx.def_span(def_id))
-    }
-
-    fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-        if !def_id.is_local() {
-            return None;
-        }
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        match tcx.hir().find(hir_id) {
-            Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => {
-                Some(fn_sig.decl.output.span())
-            }
-            _ => {
-                span_bug!(tcx.def_span(def_id), "main has a non-function type");
-            }
-        }
-    }
-
-    let mut error = false;
-    let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span);
-    let main_fn_generics = tcx.generics_of(main_def_id);
-    let main_fn_predicates = tcx.predicates_of(main_def_id);
-    if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
-        let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
-        let msg = "`main` function is not allowed to have generic \
-            parameters";
-        let mut diag =
-            struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg);
-        if let Some(generics_param_span) = generics_param_span {
-            let label = "`main` cannot have generic parameters";
-            diag.span_label(generics_param_span, label);
-        }
-        diag.emit();
-        error = true;
-    } else if !main_fn_predicates.predicates.is_empty() {
-        // generics may bring in implicit predicates, so we skip this check if generics is present.
-        let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
-        let mut diag = struct_span_err!(
-            tcx.sess,
-            generics_where_clauses_span.unwrap_or(main_span),
-            E0646,
-            "`main` function is not allowed to have a `where` clause"
-        );
-        if let Some(generics_where_clauses_span) = generics_where_clauses_span {
-            diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause");
-        }
-        diag.emit();
-        error = true;
-    }
-
-    let main_asyncness = tcx.asyncness(main_def_id);
-    if let hir::IsAsync::Async = main_asyncness {
-        let mut diag = struct_span_err!(
-            tcx.sess,
-            main_span,
-            E0752,
-            "`main` function is not allowed to be `async`"
-        );
-        let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
-        if let Some(asyncness_span) = asyncness_span {
-            diag.span_label(asyncness_span, "`main` function is not allowed to be `async`");
-        }
-        diag.emit();
-        error = true;
-    }
-
-    for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
-        tcx.sess
-            .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`")
-            .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`")
-            .emit();
-        error = true;
-    }
-
-    if error {
-        return;
-    }
-
-    let expected_return_type;
-    if let Some(term_did) = tcx.lang_items().termination() {
-        let return_ty = main_fnsig.output();
-        let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
-        if !return_ty.bound_vars().is_empty() {
-            let msg = "`main` function return type is not allowed to have generic \
-                    parameters";
-            struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit();
-            error = true;
-        }
-        let return_ty = return_ty.skip_binder();
-        tcx.infer_ctxt().enter(|infcx| {
-            // Main should have no WC, so empty param env is OK here.
-            let param_env = ty::ParamEnv::empty();
-            let cause = traits::ObligationCause::new(
-                return_ty_span,
-                main_diagnostics_hir_id,
-                ObligationCauseCode::MainFunctionType,
-            );
-            let ocx = traits::ObligationCtxt::new(&infcx);
-            let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
-            ocx.register_bound(cause, param_env, norm_return_ty, term_did);
-            let errors = ocx.select_all_or_error();
-            if !errors.is_empty() {
-                infcx.report_fulfillment_errors(&errors, None, false);
-                error = true;
-            }
-        });
-        // now we can take the return type of the given main function
-        expected_return_type = main_fnsig.output();
-    } else {
-        // standard () main return type
-        expected_return_type = ty::Binder::dummy(tcx.mk_unit());
-    }
-
-    if error {
-        return;
-    }
-
-    let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
-        tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
-    }));
-
-    require_same_types(
-        tcx,
-        &ObligationCause::new(
-            main_span,
-            main_diagnostics_hir_id,
-            ObligationCauseCode::MainFunctionType,
-        ),
-        se_ty,
-        tcx.mk_fn_ptr(main_fnsig),
-    );
-}
-fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
-    let start_def_id = start_def_id.expect_local();
-    let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
-    let start_span = tcx.def_span(start_def_id);
-    let start_t = tcx.type_of(start_def_id);
-    match start_t.kind() {
-        ty::FnDef(..) => {
-            if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
-                if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
-                    let mut error = false;
-                    if !generics.params.is_empty() {
-                        struct_span_err!(
-                            tcx.sess,
-                            generics.span,
-                            E0132,
-                            "start function is not allowed to have type parameters"
-                        )
-                        .span_label(generics.span, "start function cannot have type parameters")
-                        .emit();
-                        error = true;
-                    }
-                    if generics.has_where_clause_predicates {
-                        struct_span_err!(
-                            tcx.sess,
-                            generics.where_clause_span,
-                            E0647,
-                            "start function is not allowed to have a `where` clause"
-                        )
-                        .span_label(
-                            generics.where_clause_span,
-                            "start function cannot have a `where` clause",
-                        )
-                        .emit();
-                        error = true;
-                    }
-                    if let hir::IsAsync::Async = sig.header.asyncness {
-                        let span = tcx.def_span(it.def_id);
-                        struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0752,
-                            "`start` is not allowed to be `async`"
-                        )
-                        .span_label(span, "`start` is not allowed to be `async`")
-                        .emit();
-                        error = true;
-                    }
-
-                    let attrs = tcx.hir().attrs(start_id);
-                    for attr in attrs {
-                        if attr.has_name(sym::track_caller) {
-                            tcx.sess
-                                .struct_span_err(
-                                    attr.span,
-                                    "`start` is not allowed to be `#[track_caller]`",
-                                )
-                                .span_label(
-                                    start_span,
-                                    "`start` is not allowed to be `#[track_caller]`",
-                                )
-                                .emit();
-                            error = true;
-                        }
-                    }
-
-                    if error {
-                        return;
-                    }
-                }
-            }
-
-            let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
-                [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
-                tcx.types.isize,
-                false,
-                hir::Unsafety::Normal,
-                Abi::Rust,
-            )));
-
-            require_same_types(
-                tcx,
-                &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
-                se_ty,
-                tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
-            );
-        }
-        _ => {
-            span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
-        }
-    }
-}
-
-fn check_for_entry_fn(tcx: TyCtxt<'_>) {
-    match tcx.entry_fn(()) {
-        Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
-        Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
-        _ => {}
-    }
-}
-
-pub fn provide(providers: &mut Providers) {
-    collect::provide(providers);
-    coherence::provide(providers);
-    check::provide(providers);
-    variance::provide(providers);
-    outlives::provide(providers);
-    impl_wf_check::provide(providers);
-    hir_wf_check::provide(providers);
-}
-
-pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
-    let _prof_timer = tcx.sess.timer("type_check_crate");
-
-    // this ensures that later parts of type checking can assume that items
-    // have valid types and not error
-    // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("type_collecting", || {
-            tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
-        });
-    })?;
-
-    if tcx.features().rustc_attrs {
-        tcx.sess.track_errors(|| {
-            tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
-        })?;
-    }
-
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("impl_wf_inference", || {
-            tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
-        });
-    })?;
-
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("coherence_checking", || {
-            for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
-                tcx.ensure().coherent_trait(trait_def_id);
-            }
-
-            // these queries are executed for side-effects (error reporting):
-            tcx.ensure().crate_inherent_impls(());
-            tcx.ensure().crate_inherent_impls_overlap_check(());
-        });
-    })?;
-
-    if tcx.features().rustc_attrs {
-        tcx.sess.track_errors(|| {
-            tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
-        })?;
-    }
-
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("wf_checking", || {
-            tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
-        });
-    })?;
-
-    // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
-    tcx.sess.time("item_types_checking", || {
-        tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
-    });
-
-    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
-
-    check_unused::check_crate(tcx);
-    check_for_entry_fn(tcx);
-
-    if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
-}
-
-/// A quasi-deprecated helper used in rustdoc and clippy to get
-/// the type from a HIR node.
-pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
-    // In case there are any projections, etc., find the "environment"
-    // def-ID that will be used to determine the traits/predicates in
-    // scope.  This is derived from the enclosing item-like thing.
-    let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
-    let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
-    <dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty)
-}
-
-pub fn hir_trait_to_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    hir_trait: &hir::TraitRef<'_>,
-    self_ty: Ty<'tcx>,
-) -> Bounds<'tcx> {
-    // In case there are any projections, etc., find the "environment"
-    // def-ID that will be used to determine the traits/predicates in
-    // scope.  This is derived from the enclosing item-like thing.
-    let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
-    let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
-    let mut bounds = Bounds::default();
-    let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
-        &item_cx,
-        hir_trait,
-        DUMMY_SP,
-        ty::BoundConstness::NotConst,
-        self_ty,
-        &mut bounds,
-        true,
-    );
-
-    bounds
-}