From f468a90bade063eecb086599a58fa306d2079094 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Oct 2022 15:52:05 +0200 Subject: [PATCH 1/5] rustc_hir_typeck: move whole files --- .../src/check => rustc_hir_typeck/src}/_match.rs | 0 .../src/check => rustc_hir_typeck/src}/autoderef.rs | 0 .../src/check => rustc_hir_typeck/src}/callee.rs | 0 .../src/check => rustc_hir_typeck/src}/cast.rs | 0 .../src/check => rustc_hir_typeck/src}/closure.rs | 0 .../src/check => rustc_hir_typeck/src}/coercion.rs | 0 .../src/check => rustc_hir_typeck/src}/demand.rs | 0 .../src/check => rustc_hir_typeck/src}/diverges.rs | 0 .../src/check => rustc_hir_typeck/src}/expectation.rs | 0 .../src/check => rustc_hir_typeck/src}/expr.rs | 0 .../src/expr_use_visitor.rs | 0 .../src/check => rustc_hir_typeck/src}/fallback.rs | 0 .../src/check => rustc_hir_typeck/src}/fn_ctxt/_impl.rs | 0 .../src/check => rustc_hir_typeck/src}/fn_ctxt/arg_matrix.rs | 0 .../src/check => rustc_hir_typeck/src}/fn_ctxt/checks.rs | 0 .../src/check => rustc_hir_typeck/src}/fn_ctxt/mod.rs | 0 .../src/check => rustc_hir_typeck/src}/fn_ctxt/suggestions.rs | 0 .../src/check => rustc_hir_typeck/src}/gather_locals.rs | 0 .../src}/generator_interior/drop_ranges/cfg_build.rs | 0 .../src}/generator_interior/drop_ranges/cfg_propagate.rs | 0 .../src}/generator_interior/drop_ranges/cfg_visualize.rs | 0 .../src/generator_interior/drop_ranges/mod.rs} | 0 .../src}/generator_interior/drop_ranges/record_consumed_borrow.rs | 0 .../src/generator_interior/mod.rs} | 0 .../src/check => rustc_hir_typeck/src}/inherited.rs | 0 .../src/mem_categorization.rs | 0 .../src/check => rustc_hir_typeck/src}/method/confirm.rs | 0 .../src/check => rustc_hir_typeck/src}/method/mod.rs | 0 .../src/check => rustc_hir_typeck/src}/method/prelude2021.rs | 0 .../src/check => rustc_hir_typeck/src}/method/probe.rs | 0 .../src/check => rustc_hir_typeck/src}/method/suggest.rs | 0 .../{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/op.rs | 0 .../{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/pat.rs | 0 .../src/check => rustc_hir_typeck/src}/place_op.rs | 0 .../src/check => rustc_hir_typeck/src}/rvalue_scopes.rs | 0 .../src/check => rustc_hir_typeck/src}/upvar.rs | 0 .../src/check => rustc_hir_typeck/src}/writeback.rs | 0 37 files changed, 0 insertions(+), 0 deletions(-) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/_match.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/autoderef.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/callee.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/cast.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/closure.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/coercion.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/demand.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/diverges.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/expectation.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/expr.rs (100%) rename compiler/{rustc_hir_analysis => rustc_hir_typeck}/src/expr_use_visitor.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fallback.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fn_ctxt/_impl.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fn_ctxt/arg_matrix.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fn_ctxt/checks.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fn_ctxt/mod.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/fn_ctxt/suggestions.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/gather_locals.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/generator_interior/drop_ranges/cfg_build.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/generator_interior/drop_ranges/cfg_propagate.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/generator_interior/drop_ranges/cfg_visualize.rs (100%) rename compiler/{rustc_hir_analysis/src/check/generator_interior/drop_ranges.rs => rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs} (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/generator_interior/drop_ranges/record_consumed_borrow.rs (100%) rename compiler/{rustc_hir_analysis/src/check/generator_interior.rs => rustc_hir_typeck/src/generator_interior/mod.rs} (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/inherited.rs (100%) rename compiler/{rustc_hir_analysis => rustc_hir_typeck}/src/mem_categorization.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/method/confirm.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/method/mod.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/method/prelude2021.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/method/probe.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/method/suggest.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/op.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/pat.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/place_op.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/rvalue_scopes.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/upvar.rs (100%) rename compiler/{rustc_hir_analysis/src/check => rustc_hir_typeck/src}/writeback.rs (100%) diff --git a/compiler/rustc_hir_analysis/src/check/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/_match.rs rename to compiler/rustc_hir_typeck/src/_match.rs diff --git a/compiler/rustc_hir_analysis/src/check/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/autoderef.rs rename to compiler/rustc_hir_typeck/src/autoderef.rs diff --git a/compiler/rustc_hir_analysis/src/check/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/callee.rs rename to compiler/rustc_hir_typeck/src/callee.rs diff --git a/compiler/rustc_hir_analysis/src/check/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/cast.rs rename to compiler/rustc_hir_typeck/src/cast.rs diff --git a/compiler/rustc_hir_analysis/src/check/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/closure.rs rename to compiler/rustc_hir_typeck/src/closure.rs diff --git a/compiler/rustc_hir_analysis/src/check/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/coercion.rs rename to compiler/rustc_hir_typeck/src/coercion.rs diff --git a/compiler/rustc_hir_analysis/src/check/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/demand.rs rename to compiler/rustc_hir_typeck/src/demand.rs diff --git a/compiler/rustc_hir_analysis/src/check/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/diverges.rs rename to compiler/rustc_hir_typeck/src/diverges.rs diff --git a/compiler/rustc_hir_analysis/src/check/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/expectation.rs rename to compiler/rustc_hir_typeck/src/expectation.rs diff --git a/compiler/rustc_hir_analysis/src/check/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/expr.rs rename to compiler/rustc_hir_typeck/src/expr.rs diff --git a/compiler/rustc_hir_analysis/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/expr_use_visitor.rs rename to compiler/rustc_hir_typeck/src/expr_use_visitor.rs diff --git a/compiler/rustc_hir_analysis/src/check/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fallback.rs rename to compiler/rustc_hir_typeck/src/fallback.rs diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs rename to compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fn_ctxt/arg_matrix.rs rename to compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs rename to compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fn_ctxt/mod.rs rename to compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs rename to compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs diff --git a/compiler/rustc_hir_analysis/src/check/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/gather_locals.rs rename to compiler/rustc_hir_typeck/src/gather_locals.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs rename to compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_propagate.rs rename to compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_visualize.rs rename to compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges.rs rename to compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs rename to compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/generator_interior.rs rename to compiler/rustc_hir_typeck/src/generator_interior/mod.rs diff --git a/compiler/rustc_hir_analysis/src/check/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/inherited.rs rename to compiler/rustc_hir_typeck/src/inherited.rs diff --git a/compiler/rustc_hir_analysis/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/mem_categorization.rs rename to compiler/rustc_hir_typeck/src/mem_categorization.rs diff --git a/compiler/rustc_hir_analysis/src/check/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/method/confirm.rs rename to compiler/rustc_hir_typeck/src/method/confirm.rs diff --git a/compiler/rustc_hir_analysis/src/check/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/method/mod.rs rename to compiler/rustc_hir_typeck/src/method/mod.rs diff --git a/compiler/rustc_hir_analysis/src/check/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/method/prelude2021.rs rename to compiler/rustc_hir_typeck/src/method/prelude2021.rs diff --git a/compiler/rustc_hir_analysis/src/check/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/method/probe.rs rename to compiler/rustc_hir_typeck/src/method/probe.rs diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/method/suggest.rs rename to compiler/rustc_hir_typeck/src/method/suggest.rs diff --git a/compiler/rustc_hir_analysis/src/check/op.rs b/compiler/rustc_hir_typeck/src/op.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/op.rs rename to compiler/rustc_hir_typeck/src/op.rs diff --git a/compiler/rustc_hir_analysis/src/check/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/pat.rs rename to compiler/rustc_hir_typeck/src/pat.rs diff --git a/compiler/rustc_hir_analysis/src/check/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/place_op.rs rename to compiler/rustc_hir_typeck/src/place_op.rs diff --git a/compiler/rustc_hir_analysis/src/check/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/rvalue_scopes.rs rename to compiler/rustc_hir_typeck/src/rvalue_scopes.rs diff --git a/compiler/rustc_hir_analysis/src/check/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/upvar.rs rename to compiler/rustc_hir_typeck/src/upvar.rs diff --git a/compiler/rustc_hir_analysis/src/check/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs similarity index 100% rename from compiler/rustc_hir_analysis/src/check/writeback.rs rename to compiler/rustc_hir_typeck/src/writeback.rs From fb3ab13a1c997d46ecf4b962a5eabf255e91404a Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Oct 2022 17:51:37 +0200 Subject: [PATCH 2/5] rustc_hir_typeck: fix paths and partially mv files --- Cargo.lock | 27 + .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 312 +---------- .../src/check/intrinsicck.rs | 106 ---- compiler/rustc_hir_analysis/src/check/mod.rs | 502 +---------------- compiler/rustc_hir_analysis/src/errors.rs | 127 +---- compiler/rustc_hir_analysis/src/lib.rs | 9 +- compiler/rustc_hir_typeck/Cargo.toml | 28 + compiler/rustc_hir_typeck/src/_match.rs | 4 +- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 7 +- compiler/rustc_hir_typeck/src/check.rs | 324 +++++++++++ compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/demand.rs | 11 +- compiler/rustc_hir_typeck/src/errors.rs | 127 +++++ compiler/rustc_hir_typeck/src/expr.rs | 38 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 9 - compiler/rustc_hir_typeck/src/fallback.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 21 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 30 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 7 +- .../src/fn_ctxt/suggestions.rs | 4 +- .../rustc_hir_typeck/src/gather_locals.rs | 3 +- .../src/generator_interior/drop_ranges/mod.rs | 2 +- .../drop_ranges/record_consumed_borrow.rs | 2 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 108 ++++ compiler/rustc_hir_typeck/src/lib.rs | 506 ++++++++++++++++++ .../rustc_hir_typeck/src/method/confirm.rs | 4 +- compiler/rustc_hir_typeck/src/method/mod.rs | 4 +- .../src/method/prelude2021.rs | 9 +- compiler/rustc_hir_typeck/src/method/probe.rs | 7 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/op.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_hir_typeck/src/place_op.rs | 4 +- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- compiler/rustc_interface/Cargo.toml | 1 + compiler/rustc_interface/src/passes.rs | 1 + 39 files changed, 1232 insertions(+), 1133 deletions(-) create mode 100644 compiler/rustc_hir_typeck/Cargo.toml create mode 100644 compiler/rustc_hir_typeck/src/check.rs create mode 100644 compiler/rustc_hir_typeck/src/errors.rs create mode 100644 compiler/rustc_hir_typeck/src/intrinsicck.rs create mode 100644 compiler/rustc_hir_typeck/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d5acab8139c98..34d7f60664570 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3568,6 +3568,32 @@ dependencies = [ "rustc_target", ] +[[package]] +name = "rustc_hir_typeck" +version = "0.1.0" +dependencies = [ + "rustc_ast", + "rustc_data_structures", + "rustc_errors", + "rustc_graphviz", + "rustc_hir", + "rustc_hir_analysis", + "rustc_hir_pretty", + "rustc_index", + "rustc_infer", + "rustc_lint", + "rustc_macros", + "rustc_middle", + "rustc_serialize", + "rustc_session", + "rustc_span", + "rustc_target", + "rustc_trait_selection", + "rustc_type_ir", + "smallvec", + "tracing", +] + [[package]] name = "rustc_incremental" version = "0.0.0" @@ -3637,6 +3663,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_hir_analysis", + "rustc_hir_typeck", "rustc_incremental", "rustc_lint", "rustc_macros", diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6e373e41b4c02..9b9ef2b1fbd02 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -582,7 +582,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_bindings } - pub(crate) fn create_substs_for_associated_item( + pub fn create_substs_for_associated_item( &self, span: Span, item_def_id: DefId, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c3583eeb430be..a1faf80251957 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,6 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use super::coercion::CoerceMany; use super::compare_method::check_type_bounds; use super::compare_method::{compare_impl_method, compare_ty_impl}; use super::*; @@ -10,10 +9,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node, PathSegment}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; @@ -34,7 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use std::ops::ControlFlow; -pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { +pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { match tcx.sess.target.is_abi_supported(abi) { Some(true) => (), Some(false) => { @@ -69,313 +66,6 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab } } -/// Helper used for fns and closures. Does the grungy work of checking a function -/// body and returns the function context used for that purpose, since in the case of a fn item -/// there is still a bit more to do. -/// -/// * ... -/// * inherited: other fields inherited from the enclosing fn (if any) -#[instrument(skip(inherited, body), level = "debug")] -pub(super) fn check_fn<'a, 'tcx>( - inherited: &'a Inherited<'tcx>, - param_env: ty::ParamEnv<'tcx>, - fn_sig: ty::FnSig<'tcx>, - decl: &'tcx hir::FnDecl<'tcx>, - fn_id: hir::HirId, - body: &'tcx hir::Body<'tcx>, - can_be_generator: Option, - return_type_pre_known: bool, -) -> (FnCtxt<'a, 'tcx>, Option>) { - // Create the function context. This is either derived from scratch or, - // in the case of closures, based on the outer context. - let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); - fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); - fcx.return_type_pre_known = return_type_pre_known; - - let tcx = fcx.tcx; - let hir = tcx.hir(); - - let declared_ret_ty = fn_sig.output(); - - let ret_ty = - fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars( - declared_ret_ty, - body.value.hir_id, - decl.output.span(), - param_env, - )); - // If we replaced declared_ret_ty with infer vars, then we must be inferring - // an opaque type, so set a flag so we can improve diagnostics. - fcx.return_type_has_opaque = ret_ty != declared_ret_ty; - - fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); - - let span = body.value.span; - - fn_maybe_err(tcx, span, fn_sig.abi); - - if fn_sig.abi == Abi::RustCall { - let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 }; - - let err = || { - let item = match tcx.hir().get(fn_id) { - Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header), - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(header, ..), .. - }) => Some(header), - Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(header, ..), - .. - }) => Some(header), - // Closures are RustCall, but they tuple their arguments, so shouldn't be checked - Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None, - node => bug!("Item being checked wasn't a function/closure: {:?}", node), - }; - - if let Some(header) = item { - tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); - } - }; - - if fn_sig.inputs().len() != expected_args { - err() - } else { - // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on - // This will probably require wide-scale changes to support a TupleKind obligation - // We can't resolve this without knowing the type of the param - if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) { - err() - } - } - } - - if body.generator_kind.is_some() && can_be_generator.is_some() { - let yield_ty = fcx - .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); - fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); - - // Resume type defaults to `()` if the generator has no argument. - let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit()); - - fcx.resume_yield_tys = Some((resume_ty, yield_ty)); - } - - GatherLocalsVisitor::new(&fcx).visit_body(body); - - // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` - // (as it's created inside the body itself, not passed in from outside). - let maybe_va_list = if fn_sig.c_variadic { - let span = body.params.last().unwrap().span; - let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span)); - let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span)); - - Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()])) - } else { - None - }; - - // Add formal parameters. - let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); - let inputs_fn = fn_sig.inputs().iter().copied(); - for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { - // Check the pattern. - let ty_span = try { inputs_hir?.get(idx)?.span }; - fcx.check_pat_top(¶m.pat, param_ty, ty_span, false); - - // Check that argument is Sized. - // The check for a non-trivial pattern is a hack to avoid duplicate warnings - // for simple cases like `fn foo(x: Trait)`, - // where we would error once on the parameter as a whole, and once on the binding `x`. - if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params { - fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span)); - } - - fcx.write_ty(param.hir_id, param_ty); - } - - inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - - fcx.in_tail_expr = true; - if let ty::Dynamic(..) = declared_ret_ty.kind() { - // FIXME: We need to verify that the return type is `Sized` after the return expression has - // been evaluated so that we have types available for all the nodes being returned, but that - // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this - // causes unsized errors caused by the `declared_ret_ty` to point at the return expression, - // while keeping the current ordering we will ignore the tail expression's type because we - // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr` - // because we will trigger "unreachable expression" lints unconditionally. - // Because of all of this, we perform a crude check to know whether the simplest `!Sized` - // case that a newcomer might make, returning a bare trait, and in that case we populate - // the tail expression's type so that the suggestion will be correct, but ignore all other - // possible cases. - fcx.check_expr(&body.value); - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - } else { - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - fcx.check_return_expr(&body.value, false); - } - fcx.in_tail_expr = false; - - // We insert the deferred_generator_interiors entry after visiting the body. - // This ensures that all nested generators appear before the entry of this generator. - // resolve_generator_interiors relies on this property. - let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) { - let interior = fcx - .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span }); - fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind)); - - let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap(); - Some(GeneratorTypes { - resume_ty, - yield_ty, - interior, - movability: can_be_generator.unwrap(), - }) - } else { - None - }; - - // Finalize the return check by taking the LUB of the return types - // we saw and assigning it to the expected return type. This isn't - // really expected to fail, since the coercions would have failed - // earlier when trying to find a LUB. - let coercion = fcx.ret_coercion.take().unwrap().into_inner(); - let mut actual_return_ty = coercion.complete(&fcx); - debug!("actual_return_ty = {:?}", actual_return_ty); - if let ty::Dynamic(..) = declared_ret_ty.kind() { - // We have special-cased the case where the function is declared - // `-> dyn Foo` and we don't actually relate it to the - // `fcx.ret_coercion`, so just substitute a type variable. - actual_return_ty = - fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }); - debug!("actual_return_ty replaced with {:?}", actual_return_ty); - } - - // HACK(oli-obk, compiler-errors): We should be comparing this against - // `declared_ret_ty`, but then anything uninferred would be inferred to - // the opaque type itself. That again would cause writeback to assume - // we have a recursive call site and do the sadly stabilized fallback to `()`. - fcx.demand_suptype(span, ret_ty, actual_return_ty); - - // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` - if let Some(panic_impl_did) = tcx.lang_items().panic_impl() - && panic_impl_did == hir.local_def_id(fn_id).to_def_id() - { - check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); - } - - // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` - if let Some(alloc_error_handler_did) = tcx.lang_items().oom() - && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() - { - check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty); - } - - (fcx, gen_ty) -} - -fn check_panic_info_fn( - tcx: TyCtxt<'_>, - fn_id: LocalDefId, - fn_sig: ty::FnSig<'_>, - decl: &hir::FnDecl<'_>, - declared_ret_ty: Ty<'_>, -) { - let Some(panic_info_did) = tcx.lang_items().panic_info() else { - tcx.sess.err("language item required, but not found: `panic_info`"); - return; - }; - - if *declared_ret_ty.kind() != ty::Never { - tcx.sess.span_err(decl.output.span(), "return type should be `!`"); - } - - let inputs = fn_sig.inputs(); - if inputs.len() != 1 { - tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); - return; - } - - let arg_is_panic_info = match *inputs[0].kind() { - ty::Ref(region, ty, mutbl) => match *ty.kind() { - ty::Adt(ref adt, _) => { - adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static() - } - _ => false, - }, - _ => false, - }; - - if !arg_is_panic_info { - tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); - } - - let DefKind::Fn = tcx.def_kind(fn_id) else { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "should be a function"); - return; - }; - - let generic_counts = tcx.generics_of(fn_id).own_counts(); - if generic_counts.types != 0 { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "should have no type parameters"); - } - if generic_counts.consts != 0 { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "should have no const parameters"); - } -} - -fn check_alloc_error_fn( - tcx: TyCtxt<'_>, - fn_id: LocalDefId, - fn_sig: ty::FnSig<'_>, - decl: &hir::FnDecl<'_>, - declared_ret_ty: Ty<'_>, -) { - let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else { - tcx.sess.err("language item required, but not found: `alloc_layout`"); - return; - }; - - if *declared_ret_ty.kind() != ty::Never { - tcx.sess.span_err(decl.output.span(), "return type should be `!`"); - } - - let inputs = fn_sig.inputs(); - if inputs.len() != 1 { - tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); - return; - } - - let arg_is_alloc_layout = match inputs[0].kind() { - ty::Adt(ref adt, _) => adt.did() == alloc_layout_did, - _ => false, - }; - - if !arg_is_alloc_layout { - tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); - } - - let DefKind::Fn = tcx.def_kind(fn_id) else { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function"); - return; - }; - - let generic_counts = tcx.generics_of(fn_id).own_counts(); - if generic_counts.types != 0 { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters"); - } - if generic_counts.consts != 0 { - let span = tcx.def_span(fn_id); - tcx.sess - .span_err(span, "`#[alloc_error_handler]` function should have no const parameters"); - } -} - fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 25228f424cd07..a026f8033c8cb 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -1,117 +1,11 @@ -use hir::HirId; use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_index::vec::Idx; -use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy}; use rustc_session::lint; use rustc_span::{Symbol, DUMMY_SP}; -use rustc_target::abi::{Pointer, VariantIdx}; use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType}; -use super::FnCtxt; - -/// If the type is `Option`, it will return `T`, otherwise -/// the type itself. Works on most `Option`-like types. -fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty::Adt(def, substs) = *ty.kind() else { return ty }; - - if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() { - let data_idx; - - let one = VariantIdx::new(1); - let zero = VariantIdx::new(0); - - if def.variant(zero).fields.is_empty() { - data_idx = one; - } else if def.variant(one).fields.is_empty() { - data_idx = zero; - } else { - return ty; - } - - if def.variant(data_idx).fields.len() == 1 { - return def.variant(data_idx).fields[0].ty(tcx, substs); - } - } - - ty -} - -impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { - let tcx = self.tcx; - let span = tcx.hir().span(hir_id); - let normalize = |ty| { - let ty = self.resolve_vars_if_possible(ty); - self.tcx.normalize_erasing_regions(self.param_env, ty) - }; - let from = normalize(from); - let to = normalize(to); - trace!(?from, ?to); - - // Transmutes that are only changing lifetimes are always ok. - if from == to { - return; - } - - let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env); - let sk_from = skel(from); - let sk_to = skel(to); - trace!(?sk_from, ?sk_to); - - // Check for same size using the skeletons. - if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) { - if sk_from.same_size(sk_to) { - return; - } - - // Special-case transmuting from `typeof(function)` and - // `Option` to present a clearer error. - let from = unpack_option_like(tcx, from); - if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) { - struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type") - .note(&format!("source type: {from}")) - .note(&format!("target type: {to}")) - .help("cast with `as` to a pointer instead") - .emit(); - return; - } - } - - // Try to display a sensible error with as much information as possible. - let skeleton_string = |ty: Ty<'tcx>, sk| match sk { - Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), - Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), - Err(LayoutError::Unknown(bad)) => { - if bad == ty { - "this type does not have a fixed size".to_owned() - } else { - format!("size can vary because of {bad}") - } - } - Err(err) => err.to_string(), - }; - - let mut err = struct_span_err!( - tcx.sess, - span, - E0512, - "cannot transmute between types of different sizes, \ - or dependently-sized types" - ); - if from == to { - err.note(&format!("`{from}` does not have a fixed size")); - } else { - err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) - .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); - } - err.emit(); - } -} - pub struct InlineAsmCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 331bd7e26c858..2e7b102576407 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -62,191 +62,45 @@ a type parameter). */ -pub mod _match; -mod autoderef; -mod callee; -pub mod cast; mod check; -mod closure; -pub mod coercion; mod compare_method; -pub mod demand; -mod diverges; pub mod dropck; -mod expectation; -mod expr; -mod fallback; -mod fn_ctxt; -mod gather_locals; -mod generator_interior; -mod inherited; pub mod intrinsic; -mod intrinsicck; -pub mod method; -mod op; -mod pat; -mod place_op; +pub mod intrinsicck; mod region; -pub mod rvalue_scopes; -mod upvar; pub mod wfcheck; -pub mod writeback; -use check::{check_abi, check_fn, check_mod_item_types}; -pub use diverges::Diverges; -pub use expectation::Expectation; -pub use fn_ctxt::*; -pub use inherited::{Inherited, InheritedBuilder}; +pub use check::check_abi; -use crate::astconv::AstConv; -use crate::check::gather_locals::GatherLocalsVisitor; +use check::check_mod_item_types; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{ - pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, -}; +use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{HirIdMap, ImplicitSelfKind, Node}; use rustc_index::bit_set::BitSet; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt, UserType}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; -use rustc_session::config; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, Ident}; use rustc_span::{self, BytePos, Span, Symbol}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; -use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; -use std::cell::RefCell; use std::num::NonZeroU32; use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; -use self::coercion::DynamicCoerceMany; use self::compare_method::collect_trait_impl_trait_tys; use self::region::region_scope_tree; -pub use self::Expectation::*; - -#[macro_export] -macro_rules! type_error_struct { - ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ - let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*); - - if $typ.references_error() { - err.downgrade_to_delayed_bug(); - } - - err - }) -} - -/// The type of a local binding, including the revealed type for anon types. -#[derive(Copy, Clone, Debug)] -pub struct LocalTy<'tcx> { - decl_ty: Ty<'tcx>, - revealed_ty: Ty<'tcx>, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Needs { - MutPlace, - None, -} - -impl Needs { - fn maybe_mut_place(m: hir::Mutability) -> Self { - match m { - hir::Mutability::Mut => Needs::MutPlace, - hir::Mutability::Not => Needs::None, - } - } -} - -#[derive(Copy, Clone)] -pub struct UnsafetyState { - pub def: hir::HirId, - pub unsafety: hir::Unsafety, - from_fn: bool, -} - -impl UnsafetyState { - pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState { - UnsafetyState { def, unsafety, from_fn: true } - } - - pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState { - use hir::BlockCheckMode; - match self.unsafety { - // If this unsafe, then if the outer function was already marked as - // unsafe we shouldn't attribute the unsafe'ness to the block. This - // way the block can be warned about instead of ignoring this - // extraneous block (functions are never warned about). - hir::Unsafety::Unsafe if self.from_fn => self, - - unsafety => { - let (unsafety, def) = match blk.rules { - BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id), - BlockCheckMode::DefaultBlock => (unsafety, self.def), - }; - UnsafetyState { def, unsafety, from_fn: false } - } - } - } -} - -#[derive(Debug, Copy, Clone)] -pub enum PlaceOp { - Deref, - Index, -} - -pub struct BreakableCtxt<'tcx> { - may_break: bool, - - // this is `null` for loops where break with a value is illegal, - // such as `while`, `for`, and `while let` - coerce: Option>, -} - -pub struct EnclosingBreakables<'tcx> { - stack: Vec>, - by_id: HirIdMap, -} - -impl<'tcx> EnclosingBreakables<'tcx> { - fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> { - self.opt_find_breakable(target_id).unwrap_or_else(|| { - bug!("could not find enclosing breakable with id {}", target_id); - }) - } - - fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> { - match self.by_id.get(&target_id) { - Some(ix) => Some(&mut self.stack[*ix]), - None => None, - } - } -} pub fn provide(providers: &mut Providers) { - method::provide(providers); wfcheck::provide(providers); *providers = Providers { - typeck_item_bodies, - typeck_const_arg, - typeck, - diagnostic_only_typeck, - has_typeck_results, adt_destructor, - used_trait_imports, check_mod_item_types, region_scope_tree, collect_trait_impl_trait_tys, @@ -259,259 +113,6 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option { tcx.calculate_dtor(def_id, dropck::check_drop_impl) } -/// If this `DefId` is a "primary tables entry", returns -/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`. -/// -/// If this function returns `Some`, then `typeck_results(def_id)` will -/// succeed; if it returns `None`, then `typeck_results(def_id)` may or -/// may not succeed. In some cases where this function returns `None` -/// (notably closures), `typeck_results(def_id)` would wind up -/// redirecting to the owning function. -fn primary_body_of( - tcx: TyCtxt<'_>, - id: hir::HirId, -) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> { - match tcx.hir().get(id) { - Node::Item(item) => match item.kind { - hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => { - Some((body, Some(ty), None)) - } - hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))), - _ => None, - }, - Node::TraitItem(item) => match item.kind { - hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)), - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - Some((body, None, Some(sig))) - } - _ => None, - }, - Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)), - hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))), - _ => None, - }, - Node::AnonConst(constant) => Some((constant.body, None, None)), - _ => None, - } -} - -fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // Closures' typeck results come from their outermost function, - // as they are part of the same "inference environment". - let typeck_root_def_id = tcx.typeck_root_def_id(def_id); - if typeck_root_def_id != def_id { - return tcx.has_typeck_results(typeck_root_def_id); - } - - if let Some(def_id) = def_id.as_local() { - let id = tcx.hir().local_def_id_to_hir_id(def_id); - primary_body_of(tcx, id).is_some() - } else { - false - } -} - -fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet { - &*tcx.typeck(def_id).used_trait_imports -} - -fn typeck_const_arg<'tcx>( - tcx: TyCtxt<'tcx>, - (did, param_did): (LocalDefId, DefId), -) -> &ty::TypeckResults<'tcx> { - let fallback = move || tcx.type_of(param_did); - typeck_with_fallback(tcx, did, fallback) -} - -fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { - if let Some(param_did) = tcx.opt_const_param_of(def_id) { - tcx.typeck_const_arg((def_id, param_did)) - } else { - let fallback = move || tcx.type_of(def_id.to_def_id()); - typeck_with_fallback(tcx, def_id, fallback) - } -} - -/// Used only to get `TypeckResults` for type inference during error recovery. -/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. -fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { - let fallback = move || { - let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id)); - tcx.ty_error_with_message(span, "diagnostic only typeck table used") - }; - typeck_with_fallback(tcx, def_id, fallback) -} - -fn typeck_with_fallback<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - fallback: impl Fn() -> Ty<'tcx> + 'tcx, -) -> &'tcx ty::TypeckResults<'tcx> { - // Closures' typeck results come from their outermost function, - // as they are part of the same "inference environment". - let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(); - if typeck_root_def_id != def_id { - return tcx.typeck(typeck_root_def_id); - } - - let id = tcx.hir().local_def_id_to_hir_id(def_id); - let span = tcx.hir().span(id); - - // Figure out what primary body this item has. - let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| { - span_bug!(span, "can't type-check body of {:?}", def_id); - }); - let body = tcx.hir().body(body_id); - - let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { - let param_env = tcx.param_env(def_id); - let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { - let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { - let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - >::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) - } else { - tcx.fn_sig(def_id) - }; - - check_abi(tcx, id, span, fn_sig.abi()); - - // Compute the function signature from point of view of inside the fn. - let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); - let fn_sig = inh.normalize_associated_types_in( - body.value.span, - body_id.hir_id, - param_env, - fn_sig, - ); - check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0 - } else { - let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - let expected_type = body_ty - .and_then(|ty| match ty.kind { - hir::TyKind::Infer => Some(>::ast_ty_to_ty(&fcx, ty)), - _ => None, - }) - .unwrap_or_else(|| match tcx.hir().get(id) { - Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) { - Node::Expr(&hir::Expr { - kind: hir::ExprKind::ConstBlock(ref anon_const), - .. - }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - }), - Node::Ty(&hir::Ty { - kind: hir::TyKind::Typeof(ref anon_const), .. - }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - }), - Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => { - let operand_ty = asm - .operands - .iter() - .filter_map(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - if anon_const.hir_id == id => - { - // Inline assembly constants must be integers. - Some(fcx.next_int_var()) - } - hir::InlineAsmOperand::SymFn { anon_const } - if anon_const.hir_id == id => - { - Some(fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, - })) - } - _ => None, - }) - .next(); - operand_ty.unwrap_or_else(fallback) - } - _ => fallback(), - }, - _ => fallback(), - }); - - let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type); - fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); - - // Gather locals in statics (because of block expressions). - GatherLocalsVisitor::new(&fcx).visit_body(body); - - fcx.check_expr_coercable_to_type(&body.value, expected_type, None); - - fcx.write_ty(id, expected_type); - - fcx - }; - - let fallback_has_occurred = fcx.type_inference_fallback(); - - // Even though coercion casts provide type hints, we check casts after fallback for - // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. - fcx.check_casts(); - fcx.select_obligations_where_possible(fallback_has_occurred, |_| {}); - - // Closure and generator analysis may run after fallback - // because they don't constrain other type variables. - // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now) - let prev_constness = fcx.param_env.constness(); - fcx.param_env = fcx.param_env.without_const(); - fcx.closure_analyze(body); - fcx.param_env = fcx.param_env.with_constness(prev_constness); - assert!(fcx.deferred_call_resolutions.borrow().is_empty()); - // Before the generator analysis, temporary scopes shall be marked to provide more - // precise information on types to be captured. - fcx.resolve_rvalue_scopes(def_id.to_def_id()); - fcx.resolve_generator_interiors(def_id.to_def_id()); - - for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { - let ty = fcx.normalize_ty(span, ty); - fcx.require_type_is_sized(ty, span, code); - } - - fcx.select_all_obligations_or_error(); - - if !fcx.infcx.is_tainted_by_errors() { - fcx.check_transmutes(); - } - - fcx.check_asms(); - - fcx.infcx.skip_region_resolution(); - - fcx.resolve_type_vars_in_body(body) - }); - - // Consistency check our TypeckResults instance can hold all ItemLocalIds - // it will need to hold. - assert_eq!(typeck_results.hir_owner, id.owner); - - typeck_results -} - -/// When `check_fn` is invoked on a generator (i.e., a body that -/// includes yield), it returns back some information about the yield -/// points. -struct GeneratorTypes<'tcx> { - /// Type of generator argument / values returned by `yield`. - resume_ty: Ty<'tcx>, - - /// Type of value that is yielded. - yield_ty: Ty<'tcx>, - - /// Types that are captured (see `GeneratorInterior` for more). - interior: Ty<'tcx>, - - /// Indicates if the generator is movable or static (immovable). - movability: hir::Movability, -} - /// Given a `DefId` for an opaque type in return position, find its parent item's return /// expressions. fn get_owner_return_paths<'tcx>( @@ -528,9 +129,10 @@ fn get_owner_return_paths<'tcx>( }) } -// Forbid defining intrinsics in Rust code, -// as they must always be defined by the compiler. -fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { +/// Forbid defining intrinsics in Rust code, +/// as they must always be defined by the compiler. +// FIXME: Move this to a more appropriate place. +pub fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi { tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); } @@ -824,6 +426,17 @@ fn fn_sig_suggestion<'tcx>( format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}") } +pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> { + Some(match ty.kind() { + ty::Bool => "true", + ty::Char => "'a'", + ty::Int(_) | ty::Uint(_) => "42", + ty::Float(_) => "3.14159", + ty::Error(_) | ty::Never => return None, + _ => "value", + }) +} + /// Return placeholder code for the given associated item. /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a /// structured suggestion. @@ -845,7 +458,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String { ty::AssocKind::Type => format!("type {} = Type;", assoc.name), ty::AssocKind::Const => { let ty = tcx.type_of(assoc.def_id); - let val = expr::ty_kind_suggestion(ty).unwrap_or("value"); + let val = ty_kind_suggestion(ty).unwrap_or("value"); format!("const {}: {} = {};", assoc.name, ty, val) } } @@ -896,76 +509,7 @@ fn bad_non_zero_sized_fields<'tcx>( err.emit(); } -fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) { - struct_span_err!( - tcx.sess, - span, - E0533, - "expected unit struct, unit variant or constant, found {} `{}`", - res.descr(), - rustc_hir_pretty::qpath_to_string(qpath), - ) - .emit(); -} - -/// Controls whether the arguments are tupled. This is used for the call -/// operator. -/// -/// Tupling means that all call-side arguments are packed into a tuple and -/// passed as a single parameter. For example, if tupling is enabled, this -/// function: -/// ``` -/// fn f(x: (isize, isize)) {} -/// ``` -/// Can be called as: -/// ```ignore UNSOLVED (can this be done in user code?) -/// # fn f(x: (isize, isize)) {} -/// f(1, 2); -/// ``` -/// Instead of: -/// ``` -/// # fn f(x: (isize, isize)) {} -/// f((1, 2)); -/// ``` -#[derive(Clone, Eq, PartialEq)] -enum TupleArgumentsFlag { - DontTupleArguments, - TupleArguments, -} - -fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) { - tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id)); -} - -fn fatally_break_rust(sess: &Session) { - let handler = sess.diagnostic(); - handler.span_bug_no_panic( - MultiSpan::new(), - "It looks like you're trying to break rust; would you like some ICE?", - ); - handler.note_without_error("the compiler expectedly panicked. this is a feature."); - handler.note_without_error( - "we would appreciate a joke overview: \ - https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", - ); - handler.note_without_error(&format!( - "rustc {} running on {}", - option_env!("CFG_VERSION").unwrap_or("unknown_version"), - config::host_triple(), - )); -} - -fn potentially_plural_count(count: usize, word: &str) -> String { +// FIXME: Consider moving this method to a more fitting place. +pub fn potentially_plural_count(count: usize, word: &str) -> String { format!("{} {}{}", count, word, pluralize!(count)) } - -fn has_expected_num_generic_args<'tcx>( - tcx: TyCtxt<'tcx>, - trait_did: Option, - expected: usize, -) -> bool { - trait_did.map_or(true, |trait_did| { - let generics = tcx.generics_of(trait_did); - generics.count() == expected + if generics.has_self { 1 } else { 0 } - }) -} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 41f73323d9a9a..aaebbe6398a13 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1,22 +1,11 @@ -//! Errors emitted by `hir_analysis`. +//! Errors emitted by `rustc_hir_analysis`. use rustc_errors::IntoDiagnostic; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler}; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; -#[derive(Diagnostic)] -#[diag(hir_analysis::field_multiply_specified_in_initializer, code = "E0062")] -pub struct FieldMultiplySpecifiedInInitializer { - #[primary_span] - #[label] - pub span: Span, - #[label(hir_analysis::previous_use_label)] - pub prev_span: Span, - pub ident: Ident, -} - #[derive(Diagnostic)] #[diag(hir_analysis::unrecognized_atomic_operation, code = "E0092")] pub struct UnrecognizedAtomicOperation<'a> { @@ -124,13 +113,6 @@ pub struct AssocTypeBindingNotAllowed { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_analysis::functional_record_update_on_non_struct, code = "E0436")] -pub struct FunctionalRecordUpdateOnNonStruct { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis::typeof_reserved_keyword_used, code = "E0516")] pub struct TypeofReservedKeywordUsed<'tcx> { @@ -142,39 +124,6 @@ pub struct TypeofReservedKeywordUsed<'tcx> { pub opt_sugg: Option<(Span, Applicability)>, } -#[derive(Diagnostic)] -#[diag(hir_analysis::return_stmt_outside_of_fn_body, code = "E0572")] -pub struct ReturnStmtOutsideOfFnBody { - #[primary_span] - pub span: Span, - #[label(hir_analysis::encl_body_label)] - pub encl_body_span: Option, - #[label(hir_analysis::encl_fn_label)] - pub encl_fn_span: Option, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis::yield_expr_outside_of_generator, code = "E0627")] -pub struct YieldExprOutsideOfGenerator { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis::struct_expr_non_exhaustive, code = "E0639")] -pub struct StructExprNonExhaustive { - #[primary_span] - pub span: Span, - pub what: &'static str, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis::method_call_on_unknown_type, code = "E0699")] -pub struct MethodCallOnUnknownType { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis::value_of_associated_struct_already_specified, code = "E0719")] pub struct ValueOfAssociatedStructAlreadySpecified { @@ -187,52 +136,6 @@ pub struct ValueOfAssociatedStructAlreadySpecified { pub def_path: String, } -#[derive(Diagnostic)] -#[diag(hir_analysis::address_of_temporary_taken, code = "E0745")] -pub struct AddressOfTemporaryTaken { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Subdiagnostic)] -pub enum AddReturnTypeSuggestion { - #[suggestion( - hir_analysis::add_return_type_add, - code = "-> {found} ", - applicability = "machine-applicable" - )] - Add { - #[primary_span] - span: Span, - found: String, - }, - #[suggestion( - hir_analysis::add_return_type_missing_here, - code = "-> _ ", - applicability = "has-placeholders" - )] - MissingHere { - #[primary_span] - span: Span, - }, -} - -#[derive(Subdiagnostic)] -pub enum ExpectedReturnTypeLabel<'tcx> { - #[label(hir_analysis::expected_default_return_type)] - Unit { - #[primary_span] - span: Span, - }, - #[label(hir_analysis::expected_return_type)] - Other { - #[primary_span] - span: Span, - expected: Ty<'tcx>, - }, -} - #[derive(Diagnostic)] #[diag(hir_analysis::unconstrained_opaque_type)] #[note] @@ -346,29 +249,3 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } - -#[derive(Diagnostic)] -#[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")] -pub struct MissingParentheseInRange { - #[primary_span] - #[label(hir_analysis::missing_parentheses_in_range)] - pub span: Span, - pub ty_str: String, - pub method_name: String, - - #[subdiagnostic] - pub add_missing_parentheses: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion_verbose( - hir_analysis::add_missing_parentheses_in_range, - applicability = "maybe-incorrect" -)] -pub struct AddMissingParenthesesInRange { - pub func_name: String, - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index b7d9fc8a2fe27..dba505149de87 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -82,20 +82,19 @@ extern crate rustc_middle; // These are used by Clippy. pub mod check; -pub mod expr_use_visitor; -mod astconv; +pub mod astconv; mod bounds; mod check_unused; mod coherence; -mod collect; +// FIXME: This module shouldn't be public. +pub 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; +pub mod structured_errors; mod variance; use rustc_errors::{struct_span_err, ErrorGuaranteed}; diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml new file mode 100644 index 0000000000000..093f9bb84486e --- /dev/null +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "rustc_hir_typeck" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_graphviz = { path = "../rustc_graphviz" } +rustc_index = { path = "../rustc_index" } +rustc_infer = { path = "../rustc_infer" } +rustc_hir = { path = "../rustc_hir" } +rustc_hir_analysis = { path = "../rustc_hir_analysis" } +rustc_hir_pretty = { path = "../rustc_hir_pretty" } +rustc_lint = { path = "../rustc_lint" } +rustc_middle = { path = "../rustc_middle" } +rustc_macros = { path = "../rustc_macros" } +rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } +rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 143508b785f1e..c22d828625bc8 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,5 +1,5 @@ -use crate::check::coercion::{AsCoercionSite, CoerceMany}; -use crate::check::{Diverges, Expectation, FnCtxt, Needs}; +use crate::coercion::{AsCoercionSite, CoerceMany}; +use crate::{Diverges, Expectation, FnCtxt, Needs}; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 088de1979babe..1b33f2f02b8ad 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -1,8 +1,8 @@ use super::method::probe::{IsSuggestion, Mode, ProbeScope}; use super::method::MethodCallee; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; -use crate::type_error_struct; +use crate::type_error_struct; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey}; use rustc_hir as hir; diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 51abdd2e059d7..0e7576ecf8b0c 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -30,9 +30,7 @@ use super::FnCtxt; -use crate::hir::def_id::DefId; use crate::type_error_struct; -use hir::def_id::LOCAL_CRATE; use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_middle::mir::Mutability; @@ -43,6 +41,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef}; use rustc_session::lint; use rustc_session::Session; +use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; @@ -527,7 +526,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::SizedUnsizedCast => { - use crate::structured_errors::{SizedUnsizedCast, StructuredDiagnostic}; + use rustc_hir_analysis::structured_errors::{ + SizedUnsizedCast, StructuredDiagnostic, + }; SizedUnsizedCast { sess: &fcx.tcx.sess, diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs new file mode 100644 index 0000000000000..7f76364e15a75 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -0,0 +1,324 @@ +use crate::coercion::CoerceMany; +use crate::gather_locals::GatherLocalsVisitor; +use crate::{FnCtxt, Inherited}; +use crate::{GeneratorTypes, UnsafetyState}; +use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::intravisit::Visitor; +use rustc_hir::lang_items::LangItem; +use rustc_hir::{ImplicitSelfKind, ItemKind, Node}; +use rustc_hir_analysis::check::fn_maybe_err; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::RegionVariableOrigin; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::def_id::LocalDefId; +use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; +use std::cell::RefCell; + +/// Helper used for fns and closures. Does the grungy work of checking a function +/// body and returns the function context used for that purpose, since in the case of a fn item +/// there is still a bit more to do. +/// +/// * ... +/// * inherited: other fields inherited from the enclosing fn (if any) +#[instrument(skip(inherited, body), level = "debug")] +pub(super) fn check_fn<'a, 'tcx>( + inherited: &'a Inherited<'tcx>, + param_env: ty::ParamEnv<'tcx>, + fn_sig: ty::FnSig<'tcx>, + decl: &'tcx hir::FnDecl<'tcx>, + fn_id: hir::HirId, + body: &'tcx hir::Body<'tcx>, + can_be_generator: Option, + return_type_pre_known: bool, +) -> (FnCtxt<'a, 'tcx>, Option>) { + // Create the function context. This is either derived from scratch or, + // in the case of closures, based on the outer context. + let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); + fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); + fcx.return_type_pre_known = return_type_pre_known; + + let tcx = fcx.tcx; + let hir = tcx.hir(); + + let declared_ret_ty = fn_sig.output(); + + let ret_ty = + fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars( + declared_ret_ty, + body.value.hir_id, + decl.output.span(), + param_env, + )); + // If we replaced declared_ret_ty with infer vars, then we must be inferring + // an opaque type, so set a flag so we can improve diagnostics. + fcx.return_type_has_opaque = ret_ty != declared_ret_ty; + + fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); + + let span = body.value.span; + + fn_maybe_err(tcx, span, fn_sig.abi); + + if fn_sig.abi == Abi::RustCall { + let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 }; + + let err = || { + let item = match tcx.hir().get(fn_id) { + Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header), + Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(header, ..), .. + }) => Some(header), + Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(header, ..), + .. + }) => Some(header), + // Closures are RustCall, but they tuple their arguments, so shouldn't be checked + Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None, + node => bug!("Item being checked wasn't a function/closure: {:?}", node), + }; + + if let Some(header) = item { + tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); + } + }; + + if fn_sig.inputs().len() != expected_args { + err() + } else { + // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on + // This will probably require wide-scale changes to support a TupleKind obligation + // We can't resolve this without knowing the type of the param + if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) { + err() + } + } + } + + if body.generator_kind.is_some() && can_be_generator.is_some() { + let yield_ty = fcx + .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); + fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); + + // Resume type defaults to `()` if the generator has no argument. + let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit()); + + fcx.resume_yield_tys = Some((resume_ty, yield_ty)); + } + + GatherLocalsVisitor::new(&fcx).visit_body(body); + + // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` + // (as it's created inside the body itself, not passed in from outside). + let maybe_va_list = if fn_sig.c_variadic { + let span = body.params.last().unwrap().span; + let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span)); + let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span)); + + Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()])) + } else { + None + }; + + // Add formal parameters. + let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); + let inputs_fn = fn_sig.inputs().iter().copied(); + for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { + // Check the pattern. + let ty_span = try { inputs_hir?.get(idx)?.span }; + fcx.check_pat_top(¶m.pat, param_ty, ty_span, false); + + // Check that argument is Sized. + // The check for a non-trivial pattern is a hack to avoid duplicate warnings + // for simple cases like `fn foo(x: Trait)`, + // where we would error once on the parameter as a whole, and once on the binding `x`. + if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params { + fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span)); + } + + fcx.write_ty(param.hir_id, param_ty); + } + + inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); + + fcx.in_tail_expr = true; + if let ty::Dynamic(..) = declared_ret_ty.kind() { + // FIXME: We need to verify that the return type is `Sized` after the return expression has + // been evaluated so that we have types available for all the nodes being returned, but that + // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this + // causes unsized errors caused by the `declared_ret_ty` to point at the return expression, + // while keeping the current ordering we will ignore the tail expression's type because we + // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr` + // because we will trigger "unreachable expression" lints unconditionally. + // Because of all of this, we perform a crude check to know whether the simplest `!Sized` + // case that a newcomer might make, returning a bare trait, and in that case we populate + // the tail expression's type so that the suggestion will be correct, but ignore all other + // possible cases. + fcx.check_expr(&body.value); + fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + } else { + fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + fcx.check_return_expr(&body.value, false); + } + fcx.in_tail_expr = false; + + // We insert the deferred_generator_interiors entry after visiting the body. + // This ensures that all nested generators appear before the entry of this generator. + // resolve_generator_interiors relies on this property. + let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) { + let interior = fcx + .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span }); + fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind)); + + let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap(); + Some(GeneratorTypes { + resume_ty, + yield_ty, + interior, + movability: can_be_generator.unwrap(), + }) + } else { + None + }; + + // Finalize the return check by taking the LUB of the return types + // we saw and assigning it to the expected return type. This isn't + // really expected to fail, since the coercions would have failed + // earlier when trying to find a LUB. + let coercion = fcx.ret_coercion.take().unwrap().into_inner(); + let mut actual_return_ty = coercion.complete(&fcx); + debug!("actual_return_ty = {:?}", actual_return_ty); + if let ty::Dynamic(..) = declared_ret_ty.kind() { + // We have special-cased the case where the function is declared + // `-> dyn Foo` and we don't actually relate it to the + // `fcx.ret_coercion`, so just substitute a type variable. + actual_return_ty = + fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }); + debug!("actual_return_ty replaced with {:?}", actual_return_ty); + } + + // HACK(oli-obk, compiler-errors): We should be comparing this against + // `declared_ret_ty`, but then anything uninferred would be inferred to + // the opaque type itself. That again would cause writeback to assume + // we have a recursive call site and do the sadly stabilized fallback to `()`. + fcx.demand_suptype(span, ret_ty, actual_return_ty); + + // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` + if let Some(panic_impl_did) = tcx.lang_items().panic_impl() + && panic_impl_did == hir.local_def_id(fn_id).to_def_id() + { + check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); + } + + // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` + if let Some(alloc_error_handler_did) = tcx.lang_items().oom() + && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() + { + check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty); + } + + (fcx, gen_ty) +} + +fn check_panic_info_fn( + tcx: TyCtxt<'_>, + fn_id: LocalDefId, + fn_sig: ty::FnSig<'_>, + decl: &hir::FnDecl<'_>, + declared_ret_ty: Ty<'_>, +) { + let Some(panic_info_did) = tcx.lang_items().panic_info() else { + tcx.sess.err("language item required, but not found: `panic_info`"); + return; + }; + + if *declared_ret_ty.kind() != ty::Never { + tcx.sess.span_err(decl.output.span(), "return type should be `!`"); + } + + let inputs = fn_sig.inputs(); + if inputs.len() != 1 { + tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); + return; + } + + let arg_is_panic_info = match *inputs[0].kind() { + ty::Ref(region, ty, mutbl) => match *ty.kind() { + ty::Adt(ref adt, _) => { + adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static() + } + _ => false, + }, + _ => false, + }; + + if !arg_is_panic_info { + tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); + } + + let DefKind::Fn = tcx.def_kind(fn_id) else { + let span = tcx.def_span(fn_id); + tcx.sess.span_err(span, "should be a function"); + return; + }; + + let generic_counts = tcx.generics_of(fn_id).own_counts(); + if generic_counts.types != 0 { + let span = tcx.def_span(fn_id); + tcx.sess.span_err(span, "should have no type parameters"); + } + if generic_counts.consts != 0 { + let span = tcx.def_span(fn_id); + tcx.sess.span_err(span, "should have no const parameters"); + } +} + +fn check_alloc_error_fn( + tcx: TyCtxt<'_>, + fn_id: LocalDefId, + fn_sig: ty::FnSig<'_>, + decl: &hir::FnDecl<'_>, + declared_ret_ty: Ty<'_>, +) { + let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else { + tcx.sess.err("language item required, but not found: `alloc_layout`"); + return; + }; + + if *declared_ret_ty.kind() != ty::Never { + tcx.sess.span_err(decl.output.span(), "return type should be `!`"); + } + + let inputs = fn_sig.inputs(); + if inputs.len() != 1 { + tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); + return; + } + + let arg_is_alloc_layout = match inputs[0].kind() { + ty::Adt(ref adt, _) => adt.did() == alloc_layout_did, + _ => false, + }; + + if !arg_is_alloc_layout { + tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); + } + + let DefKind::Fn = tcx.def_kind(fn_id) else { + let span = tcx.def_span(fn_id); + tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function"); + return; + }; + + let generic_counts = tcx.generics_of(fn_id).own_counts(); + if generic_counts.types != 0 { + let span = tcx.def_span(fn_id); + tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters"); + } + if generic_counts.consts != 0 { + let span = tcx.def_span(fn_id); + tcx.sess + .span_err(span, "`#[alloc_error_handler]` function should have no const parameters"); + } +} diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 84ea06a460bb2..de5b4a5021892 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -2,11 +2,11 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; -use crate::astconv::AstConv; use hir::def::DefKind; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; +use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index faa6c6d9356f4..86597a703e833 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -35,8 +35,7 @@ //! // and are then unable to coerce `&7i32` to `&mut i32`. //! ``` -use crate::astconv::AstConv; -use crate::check::FnCtxt; +use crate::FnCtxt; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; @@ -44,6 +43,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; +use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt}; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index a5222c92331a9..2974ac97f2368 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,21 +1,20 @@ -use crate::check::FnCtxt; -use rustc_infer::infer::InferOk; -use rustc_middle::middle::stability::EvalResult; -use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::traits::ObligationCause; - +use crate::FnCtxt; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; +use rustc_infer::infer::InferOk; use rustc_middle::lint::in_external_macro; +use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::ObligationCause; use super::method::probe; diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs new file mode 100644 index 0000000000000..2f8898d5ea9a8 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -0,0 +1,127 @@ +//! Errors emitted by `rustc_hir_analysis`. +use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_middle::ty::Ty; +use rustc_span::{symbol::Ident, Span}; + +#[derive(Diagnostic)] +#[diag(hir_analysis::field_multiply_specified_in_initializer, code = "E0062")] +pub struct FieldMultiplySpecifiedInInitializer { + #[primary_span] + #[label] + pub span: Span, + #[label(hir_analysis::previous_use_label)] + pub prev_span: Span, + pub ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::return_stmt_outside_of_fn_body, code = "E0572")] +pub struct ReturnStmtOutsideOfFnBody { + #[primary_span] + pub span: Span, + #[label(hir_analysis::encl_body_label)] + pub encl_body_span: Option, + #[label(hir_analysis::encl_fn_label)] + pub encl_fn_span: Option, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::yield_expr_outside_of_generator, code = "E0627")] +pub struct YieldExprOutsideOfGenerator { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::struct_expr_non_exhaustive, code = "E0639")] +pub struct StructExprNonExhaustive { + #[primary_span] + pub span: Span, + pub what: &'static str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::method_call_on_unknown_type, code = "E0699")] +pub struct MethodCallOnUnknownType { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::functional_record_update_on_non_struct, code = "E0436")] +pub struct FunctionalRecordUpdateOnNonStruct { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::address_of_temporary_taken, code = "E0745")] +pub struct AddressOfTemporaryTaken { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Subdiagnostic)] +pub enum AddReturnTypeSuggestion { + #[suggestion( + hir_analysis::add_return_type_add, + code = "-> {found} ", + applicability = "machine-applicable" + )] + Add { + #[primary_span] + span: Span, + found: String, + }, + #[suggestion( + hir_analysis::add_return_type_missing_here, + code = "-> _ ", + applicability = "has-placeholders" + )] + MissingHere { + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub enum ExpectedReturnTypeLabel<'tcx> { + #[label(hir_analysis::expected_default_return_type)] + Unit { + #[primary_span] + span: Span, + }, + #[label(hir_analysis::expected_return_type)] + Other { + #[primary_span] + span: Span, + expected: Ty<'tcx>, + }, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")] +pub struct MissingParentheseInRange { + #[primary_span] + #[label(hir_analysis::missing_parentheses_in_range)] + pub span: Span, + pub ty_str: String, + pub method_name: String, + + #[subdiagnostic] + pub add_missing_parentheses: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion_verbose( + hir_analysis::add_missing_parentheses_in_range, + applicability = "maybe-incorrect" +)] +pub struct AddMissingParenthesesInRange { + pub func_name: String, + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ccdfd3a056b83..41b00fda03ebf 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2,23 +2,22 @@ //! //! See `mod.rs` for more context on type checking in general. -use crate::astconv::AstConv as _; -use crate::check::cast; -use crate::check::coercion::CoerceMany; -use crate::check::fatally_break_rust; -use crate::check::method::SelfSource; -use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; -use crate::check::{ - report_unexpected_variant_res, BreakableCtxt, Diverges, DynamicCoerceMany, FnCtxt, Needs, - TupleArgumentsFlag::DontTupleArguments, -}; +use crate::cast; +use crate::coercion::CoerceMany; +use crate::coercion::DynamicCoerceMany; +use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; use crate::errors::{ FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, YieldExprOutsideOfGenerator, }; +use crate::fatally_break_rust; +use crate::method::SelfSource; use crate::type_error_struct; - -use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; +use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; +use crate::{ + report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs, + TupleArgumentsFlag::DontTupleArguments, +}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -32,6 +31,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{Closure, ExprKind, HirId, QPath}; +use rustc_hir_analysis::astconv::AstConv as _; +use rustc_hir_analysis::check::ty_kind_suggestion; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; @@ -1362,7 +1363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a new function context. let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id); - crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body); + crate::GatherLocalsVisitor::new(&fcx).visit_body(body); let ty = fcx.check_expr_with_expectation(&body.value, expected); fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized); @@ -2885,14 +2886,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - -pub(super) fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> { - Some(match ty.kind() { - ty::Bool => "true", - ty::Char => "'a'", - ty::Int(_) | ty::Uint(_) => "42", - ty::Float(_) => "3.14159", - ty::Error(_) | ty::Never => return None, - _ => "value", - }) -} diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 039c653e5bc64..fce2a5888ba24 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -89,15 +89,6 @@ enum ConsumeMode { Move, } -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum MutateMode { - Init, - /// Example: `x = y` - JustWrite, - /// Example: `x += y` - WriteAndRead, -} - /// The ExprUseVisitor type /// /// This is the code that actually walks the tree. diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 474d5651bbe2f..747ecb036b2a1 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -1,4 +1,4 @@ -use crate::check::FnCtxt; +use crate::FnCtxt; use rustc_data_structures::{ fx::{FxHashMap, FxHashSet}, graph::WithSuccessors, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index d140c3a098990..6a1cffe3e6025 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1,12 +1,7 @@ -use crate::astconv::{ - AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, - GenericArgCountResult, IsMethodCall, PathSeg, -}; -use crate::check::callee::{self, DeferredCallResolution}; -use crate::check::method::{self, MethodCallee, SelfSource}; -use crate::check::rvalue_scopes; -use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; - +use crate::callee::{self, DeferredCallResolution}; +use crate::method::{self, MethodCallee, SelfSource}; +use crate::rvalue_scopes; +use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; @@ -15,6 +10,10 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, GenericArg, Node, QPath}; +use rustc_hir_analysis::astconv::{ + AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, + GenericArgCountResult, IsMethodCall, PathSeg, +}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; @@ -603,9 +602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut generators = self.deferred_generator_interiors.borrow_mut(); for (body_id, interior, kind) in generators.drain(..) { self.select_obligations_where_possible(false, |_| {}); - crate::check::generator_interior::resolve_interior( - self, def_id, body_id, interior, kind, - ); + crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 285db90a9df55..08a3cbccfb05e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1,19 +1,13 @@ -use crate::astconv::AstConv; -use crate::check::coercion::CoerceMany; -use crate::check::fn_ctxt::arg_matrix::{ - ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx, +use crate::coercion::CoerceMany; +use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; +use crate::gather_locals::Declaration; +use crate::method::MethodCallee; +use crate::Expectation::*; +use crate::TupleArgumentsFlag::*; +use crate::{ + struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, + TupleArgumentsFlag, }; -use crate::check::gather_locals::Declaration; -use crate::check::intrinsicck::InlineAsmCtxt; -use crate::check::method::MethodCallee; -use crate::check::Expectation::*; -use crate::check::TupleArgumentsFlag::*; -use crate::check::{ - potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, - LocalTy, Needs, TupleArgumentsFlag, -}; -use crate::structured_errors::StructuredDiagnostic; - use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan}; @@ -21,6 +15,10 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, Node, QPath}; +use rustc_hir_analysis::astconv::AstConv; +use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; +use rustc_hir_analysis::check::potentially_plural_count; +use rustc_hir_analysis::structured_errors::StructuredDiagnostic; use rustc_index::vec::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -391,7 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, cast_ty: &str, ) { - use crate::structured_errors::MissingCastForVariadicArg; + use rustc_hir_analysis::structured_errors::MissingCastForVariadicArg; MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 51f4cb7e0ebfa..a8004d90a4522 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -6,12 +6,11 @@ mod suggestions; pub use _impl::*; pub use suggestions::*; -use crate::astconv::AstConv; -use crate::check::coercion::DynamicCoerceMany; -use crate::check::{Diverges, EnclosingBreakables, Inherited, UnsafetyState}; - +use crate::coercion::DynamicCoerceMany; +use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 08b21b82faf5a..cd2e41aff0f12 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1,7 +1,6 @@ use super::FnCtxt; -use crate::astconv::AstConv; -use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; +use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -10,6 +9,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{ Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, }; +use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 8f34a970f6ff7..9a096f24fac0d 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -1,9 +1,10 @@ -use crate::check::{FnCtxt, LocalTy, UserType}; +use crate::{FnCtxt, LocalTy}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::Ty; +use rustc_middle::ty::UserType; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs index 518cd7342366c..4f3bdfbe758d9 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs @@ -14,7 +14,7 @@ use self::cfg_build::build_control_flow_graph; use self::record_consumed_borrow::find_consumed_and_borrowed; -use crate::check::FnCtxt; +use crate::FnCtxt; use hir::def_id::DefId; use hir::{Body, HirId, HirIdMap, Node}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs index 2f68b57a0193f..7954ddc4166ca 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -1,7 +1,7 @@ use super::TrackedValue; use crate::{ - check::FnCtxt, expr_use_visitor::{self, ExprUseVisitor}, + FnCtxt, }; use hir::{def_id::DefId, Body, HirId, HirIdMap}; use rustc_data_structures::fx::FxHashSet; diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs new file mode 100644 index 0000000000000..9812d96fcc3c7 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -0,0 +1,108 @@ +use hir::HirId; +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_index::vec::Idx; +use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::{Pointer, VariantIdx}; + +use super::FnCtxt; + +/// If the type is `Option`, it will return `T`, otherwise +/// the type itself. Works on most `Option`-like types. +fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let ty::Adt(def, substs) = *ty.kind() else { return ty }; + + if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() { + let data_idx; + + let one = VariantIdx::new(1); + let zero = VariantIdx::new(0); + + if def.variant(zero).fields.is_empty() { + data_idx = one; + } else if def.variant(one).fields.is_empty() { + data_idx = zero; + } else { + return ty; + } + + if def.variant(data_idx).fields.len() == 1 { + return def.variant(data_idx).fields[0].ty(tcx, substs); + } + } + + ty +} + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { + let tcx = self.tcx; + let span = tcx.hir().span(hir_id); + let normalize = |ty| { + let ty = self.resolve_vars_if_possible(ty); + self.tcx.normalize_erasing_regions(self.param_env, ty) + }; + let from = normalize(from); + let to = normalize(to); + trace!(?from, ?to); + + // Transmutes that are only changing lifetimes are always ok. + if from == to { + return; + } + + let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env); + let sk_from = skel(from); + let sk_to = skel(to); + trace!(?sk_from, ?sk_to); + + // Check for same size using the skeletons. + if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) { + if sk_from.same_size(sk_to) { + return; + } + + // Special-case transmuting from `typeof(function)` and + // `Option` to present a clearer error. + let from = unpack_option_like(tcx, from); + if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) { + struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type") + .note(&format!("source type: {from}")) + .note(&format!("target type: {to}")) + .help("cast with `as` to a pointer instead") + .emit(); + return; + } + } + + // Try to display a sensible error with as much information as possible. + let skeleton_string = |ty: Ty<'tcx>, sk| match sk { + Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), + Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), + Err(LayoutError::Unknown(bad)) => { + if bad == ty { + "this type does not have a fixed size".to_owned() + } else { + format!("size can vary because of {bad}") + } + } + Err(err) => err.to_string(), + }; + + let mut err = struct_span_err!( + tcx.sess, + span, + E0512, + "cannot transmute between types of different sizes, \ + or dependently-sized types" + ); + if from == to { + err.note(&format!("`{from}` does not have a fixed size")); + } else { + err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) + .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + } + err.emit(); + } +} diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs new file mode 100644 index 0000000000000..cbff5e8820489 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -0,0 +1,506 @@ +#![feature(if_let_guard)] +#![feature(let_chains)] +#![feature(try_blocks)] +#![feature(never_type)] +#![feature(min_specialization)] +#![feature(control_flow_enum)] +#![feature(drain_filter)] +#![allow(rustc::potential_query_instability)] + +#[macro_use] +extern crate tracing; + +#[macro_use] +extern crate rustc_middle; + +mod _match; +mod autoderef; +mod callee; +// Used by clippy; +pub mod cast; +mod check; +mod closure; +mod coercion; +mod demand; +mod diverges; +mod errors; +mod expectation; +mod expr; +// Used by clippy; +pub mod expr_use_visitor; +mod fallback; +mod fn_ctxt; +mod gather_locals; +mod generator_interior; +mod inherited; +mod intrinsicck; +mod mem_categorization; +mod method; +mod op; +mod pat; +mod place_op; +mod rvalue_scopes; +mod upvar; +mod writeback; + +pub use diverges::Diverges; +pub use expectation::Expectation; +pub use fn_ctxt::*; +pub use inherited::{Inherited, InheritedBuilder}; + +use crate::check::check_fn; +use crate::coercion::DynamicCoerceMany; +use crate::gather_locals::GatherLocalsVisitor; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{struct_span_err, MultiSpan}; +use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::intravisit::Visitor; +use rustc_hir::{HirIdMap, Node}; +use rustc_hir_analysis::astconv::AstConv; +use rustc_hir_analysis::check::check_abi; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_middle::traits; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_session::config; +use rustc_session::Session; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::Span; + +#[macro_export] +macro_rules! type_error_struct { + ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ + let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*); + + if $typ.references_error() { + err.downgrade_to_delayed_bug(); + } + + err + }) +} + +/// The type of a local binding, including the revealed type for anon types. +#[derive(Copy, Clone, Debug)] +pub struct LocalTy<'tcx> { + decl_ty: Ty<'tcx>, + revealed_ty: Ty<'tcx>, +} + +#[derive(Copy, Clone)] +pub struct UnsafetyState { + pub def: hir::HirId, + pub unsafety: hir::Unsafety, + from_fn: bool, +} + +impl UnsafetyState { + pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState { + UnsafetyState { def, unsafety, from_fn: true } + } + + pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState { + use hir::BlockCheckMode; + match self.unsafety { + // If this unsafe, then if the outer function was already marked as + // unsafe we shouldn't attribute the unsafe'ness to the block. This + // way the block can be warned about instead of ignoring this + // extraneous block (functions are never warned about). + hir::Unsafety::Unsafe if self.from_fn => self, + + unsafety => { + let (unsafety, def) = match blk.rules { + BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id), + BlockCheckMode::DefaultBlock => (unsafety, self.def), + }; + UnsafetyState { def, unsafety, from_fn: false } + } + } + } +} + +/// If this `DefId` is a "primary tables entry", returns +/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`. +/// +/// If this function returns `Some`, then `typeck_results(def_id)` will +/// succeed; if it returns `None`, then `typeck_results(def_id)` may or +/// may not succeed. In some cases where this function returns `None` +/// (notably closures), `typeck_results(def_id)` would wind up +/// redirecting to the owning function. +fn primary_body_of( + tcx: TyCtxt<'_>, + id: hir::HirId, +) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> { + match tcx.hir().get(id) { + Node::Item(item) => match item.kind { + hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => { + Some((body, Some(ty), None)) + } + hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))), + _ => None, + }, + Node::TraitItem(item) => match item.kind { + hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)), + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { + Some((body, None, Some(sig))) + } + _ => None, + }, + Node::ImplItem(item) => match item.kind { + hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)), + hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))), + _ => None, + }, + Node::AnonConst(constant) => Some((constant.body, None, None)), + _ => None, + } +} + +fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + // Closures' typeck results come from their outermost function, + // as they are part of the same "inference environment". + let typeck_root_def_id = tcx.typeck_root_def_id(def_id); + if typeck_root_def_id != def_id { + return tcx.has_typeck_results(typeck_root_def_id); + } + + if let Some(def_id) = def_id.as_local() { + let id = tcx.hir().local_def_id_to_hir_id(def_id); + primary_body_of(tcx, id).is_some() + } else { + false + } +} + +fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet { + &*tcx.typeck(def_id).used_trait_imports +} + +fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) { + tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id)); +} + +fn typeck_const_arg<'tcx>( + tcx: TyCtxt<'tcx>, + (did, param_did): (LocalDefId, DefId), +) -> &ty::TypeckResults<'tcx> { + let fallback = move || tcx.type_of(param_did); + typeck_with_fallback(tcx, did, fallback) +} + +fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { + if let Some(param_did) = tcx.opt_const_param_of(def_id) { + tcx.typeck_const_arg((def_id, param_did)) + } else { + let fallback = move || tcx.type_of(def_id.to_def_id()); + typeck_with_fallback(tcx, def_id, fallback) + } +} + +/// Used only to get `TypeckResults` for type inference during error recovery. +/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. +fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { + let fallback = move || { + let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id)); + tcx.ty_error_with_message(span, "diagnostic only typeck table used") + }; + typeck_with_fallback(tcx, def_id, fallback) +} + +fn typeck_with_fallback<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + fallback: impl Fn() -> Ty<'tcx> + 'tcx, +) -> &'tcx ty::TypeckResults<'tcx> { + // Closures' typeck results come from their outermost function, + // as they are part of the same "inference environment". + let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(); + if typeck_root_def_id != def_id { + return tcx.typeck(typeck_root_def_id); + } + + let id = tcx.hir().local_def_id_to_hir_id(def_id); + let span = tcx.hir().span(id); + + // Figure out what primary body this item has. + let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| { + span_bug!(span, "can't type-check body of {:?}", def_id); + }); + let body = tcx.hir().body(body_id); + + let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { + let param_env = tcx.param_env(def_id); + let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() { + let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); + >::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) + } else { + tcx.fn_sig(def_id) + }; + + check_abi(tcx, id, span, fn_sig.abi()); + + // Compute the function signature from point of view of inside the fn. + let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); + let fn_sig = inh.normalize_associated_types_in( + body.value.span, + body_id.hir_id, + param_env, + fn_sig, + ); + check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0 + } else { + let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); + let expected_type = body_ty + .and_then(|ty| match ty.kind { + hir::TyKind::Infer => Some(>::ast_ty_to_ty(&fcx, ty)), + _ => None, + }) + .unwrap_or_else(|| match tcx.hir().get(id) { + Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::ConstBlock(ref anon_const), + .. + }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }), + Node::Ty(&hir::Ty { + kind: hir::TyKind::Typeof(ref anon_const), .. + }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }), + Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. }) + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => { + let operand_ty = asm + .operands + .iter() + .filter_map(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } + if anon_const.hir_id == id => + { + // Inline assembly constants must be integers. + Some(fcx.next_int_var()) + } + hir::InlineAsmOperand::SymFn { anon_const } + if anon_const.hir_id == id => + { + Some(fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + })) + } + _ => None, + }) + .next(); + operand_ty.unwrap_or_else(fallback) + } + _ => fallback(), + }, + _ => fallback(), + }); + + let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type); + fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); + + // Gather locals in statics (because of block expressions). + GatherLocalsVisitor::new(&fcx).visit_body(body); + + fcx.check_expr_coercable_to_type(&body.value, expected_type, None); + + fcx.write_ty(id, expected_type); + + fcx + }; + + let fallback_has_occurred = fcx.type_inference_fallback(); + + // Even though coercion casts provide type hints, we check casts after fallback for + // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. + fcx.check_casts(); + fcx.select_obligations_where_possible(fallback_has_occurred, |_| {}); + + // Closure and generator analysis may run after fallback + // because they don't constrain other type variables. + // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now) + let prev_constness = fcx.param_env.constness(); + fcx.param_env = fcx.param_env.without_const(); + fcx.closure_analyze(body); + fcx.param_env = fcx.param_env.with_constness(prev_constness); + assert!(fcx.deferred_call_resolutions.borrow().is_empty()); + // Before the generator analysis, temporary scopes shall be marked to provide more + // precise information on types to be captured. + fcx.resolve_rvalue_scopes(def_id.to_def_id()); + fcx.resolve_generator_interiors(def_id.to_def_id()); + + for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { + let ty = fcx.normalize_ty(span, ty); + fcx.require_type_is_sized(ty, span, code); + } + + fcx.select_all_obligations_or_error(); + + if !fcx.infcx.is_tainted_by_errors() { + fcx.check_transmutes(); + } + + fcx.check_asms(); + + fcx.infcx.skip_region_resolution(); + + fcx.resolve_type_vars_in_body(body) + }); + + // Consistency check our TypeckResults instance can hold all ItemLocalIds + // it will need to hold. + assert_eq!(typeck_results.hir_owner, id.owner); + + typeck_results +} + +/// When `check_fn` is invoked on a generator (i.e., a body that +/// includes yield), it returns back some information about the yield +/// points. +struct GeneratorTypes<'tcx> { + /// Type of generator argument / values returned by `yield`. + resume_ty: Ty<'tcx>, + + /// Type of value that is yielded. + yield_ty: Ty<'tcx>, + + /// Types that are captured (see `GeneratorInterior` for more). + interior: Ty<'tcx>, + + /// Indicates if the generator is movable or static (immovable). + movability: hir::Movability, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Needs { + MutPlace, + None, +} + +impl Needs { + fn maybe_mut_place(m: hir::Mutability) -> Self { + match m { + hir::Mutability::Mut => Needs::MutPlace, + hir::Mutability::Not => Needs::None, + } + } +} + +#[derive(Debug, Copy, Clone)] +pub enum PlaceOp { + Deref, + Index, +} + +pub struct BreakableCtxt<'tcx> { + may_break: bool, + + // this is `null` for loops where break with a value is illegal, + // such as `while`, `for`, and `while let` + coerce: Option>, +} + +pub struct EnclosingBreakables<'tcx> { + stack: Vec>, + by_id: HirIdMap, +} + +impl<'tcx> EnclosingBreakables<'tcx> { + fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> { + self.opt_find_breakable(target_id).unwrap_or_else(|| { + bug!("could not find enclosing breakable with id {}", target_id); + }) + } + + fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> { + match self.by_id.get(&target_id) { + Some(ix) => Some(&mut self.stack[*ix]), + None => None, + } + } +} + +fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) { + struct_span_err!( + tcx.sess, + span, + E0533, + "expected unit struct, unit variant or constant, found {} `{}`", + res.descr(), + rustc_hir_pretty::qpath_to_string(qpath), + ) + .emit(); +} + +/// Controls whether the arguments are tupled. This is used for the call +/// operator. +/// +/// Tupling means that all call-side arguments are packed into a tuple and +/// passed as a single parameter. For example, if tupling is enabled, this +/// function: +/// ``` +/// fn f(x: (isize, isize)) {} +/// ``` +/// Can be called as: +/// ```ignore UNSOLVED (can this be done in user code?) +/// # fn f(x: (isize, isize)) {} +/// f(1, 2); +/// ``` +/// Instead of: +/// ``` +/// # fn f(x: (isize, isize)) {} +/// f((1, 2)); +/// ``` +#[derive(Clone, Eq, PartialEq)] +enum TupleArgumentsFlag { + DontTupleArguments, + TupleArguments, +} + +fn fatally_break_rust(sess: &Session) { + let handler = sess.diagnostic(); + handler.span_bug_no_panic( + MultiSpan::new(), + "It looks like you're trying to break rust; would you like some ICE?", + ); + handler.note_without_error("the compiler expectedly panicked. this is a feature."); + handler.note_without_error( + "we would appreciate a joke overview: \ + https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", + ); + handler.note_without_error(&format!( + "rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple(), + )); +} + +fn has_expected_num_generic_args<'tcx>( + tcx: TyCtxt<'tcx>, + trait_did: Option, + expected: usize, +) -> bool { + trait_did.map_or(true, |trait_did| { + let generics = tcx.generics_of(trait_did); + generics.count() == expected + if generics.has_self { 1 } else { 0 } + }) +} + +pub fn provide(providers: &mut Providers) { + method::provide(providers); + *providers = Providers { + typeck_item_bodies, + typeck_const_arg, + typeck, + diagnostic_only_typeck, + has_typeck_results, + used_trait_imports, + ..*providers + }; +} diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 30731cbd03d3b..be4ea99862222 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -1,10 +1,10 @@ use super::{probe, MethodCallee}; -use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; -use crate::check::{callee, FnCtxt}; +use crate::{callee, FnCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; +use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; use rustc_infer::infer::{self, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 3fe9bea2299df..a1278edefbb71 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -10,14 +10,14 @@ mod suggest; pub use self::suggest::SelfSource; pub use self::MethodError::*; -use crate::check::{Expectation, FnCtxt}; -use crate::ObligationCause; +use crate::{Expectation, FnCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable}; use rustc_span::symbol::Ident; diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs index ca4cdf5a0d01c..3c98a2aa3aba3 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs @@ -1,3 +1,7 @@ +use crate::{ + method::probe::{self, Pick}, + FnCtxt, +}; use hir::def_id::DefId; use hir::HirId; use hir::ItemKind; @@ -12,11 +16,6 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; -use crate::check::{ - method::probe::{self, Pick}, - FnCtxt, -}; - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(super) fn lint_dot_call_from_2018( &self, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ba078ad0abbd9..74cf2ac32aab2 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -3,14 +3,12 @@ use super::CandidateSource; use super::MethodError; use super::NoMatchData; -use crate::check::FnCtxt; use crate::errors::MethodCallOnUnknownType; -use crate::hir::def::DefKind; -use crate::hir::def_id::DefId; - +use crate::FnCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def::Namespace; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; @@ -23,6 +21,7 @@ use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; use rustc_session::lint; +use rustc_span::def_id::DefId; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{ find_best_match_for_name_with_substrings, lev_distance_with_substrings, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index bfa5b68168fdb..f4351bfa84aed 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1,8 +1,8 @@ //! Give useful errors and suggestions to users when an item can't be //! found or is otherwise invalid. -use crate::check::FnCtxt; use crate::errors; +use crate::FnCtxt; use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 5e498a92ec203..8957399769385 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -2,7 +2,7 @@ use super::method::MethodCallee; use super::{has_expected_num_generic_args, FnCtxt}; -use crate::check::Expectation; +use crate::Expectation; use rustc_ast as ast; use rustc_errors::{self, struct_span_err, Applicability, Diagnostic}; use rustc_hir as hir; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 178326cfdc4fb..ea90da4a6dc35 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1,6 +1,5 @@ -use crate::check::FnCtxt; +use crate::FnCtxt; use rustc_ast as ast; - use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 2e0f37eba232d..ba8cf6926f30b 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -1,5 +1,5 @@ -use crate::check::method::MethodCallee; -use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp}; +use crate::method::MethodCallee; +use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d2d596efb93e7..1e26daa9c2c72 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -2,7 +2,7 @@ // unresolved type variables and replaces "ty_var" types with their // substitutions. -use crate::check::FnCtxt; +use crate::FnCtxt; use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index f0cb861c782f0..6a4c5b4d37376 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -38,6 +38,7 @@ rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_passes = { path = "../rustc_passes" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } +rustc_hir_typeck = { path = "../rustc_hir_typeck" } rustc_lint = { path = "../rustc_lint" } rustc_errors = { path = "../rustc_errors" } rustc_plugin_impl = { path = "../rustc_plugin_impl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8fd4224ca38fe..a47c3e3253ecd 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -736,6 +736,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); rustc_hir_analysis::provide(providers); + rustc_hir_typeck::provide(providers); ty::provide(providers); traits::provide(providers); rustc_passes::provide(providers); From b076f034963a22c591f4b2bb53748b98ec17e5b6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Oct 2022 17:51:48 +0200 Subject: [PATCH 3/5] rustc_hir_typeck: fix clippy --- src/tools/clippy/clippy_lints/src/escape.rs | 4 ++-- src/tools/clippy/clippy_lints/src/lib.rs | 1 + src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs | 4 ++-- .../clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- .../clippy/clippy_lints/src/needless_pass_by_value.rs | 4 ++-- .../clippy/clippy_lints/src/operators/assign_op_pattern.rs | 2 +- src/tools/clippy/clippy_lints/src/transmute/utils.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/sugg.rs | 7 +++---- src/tools/clippy/clippy_utils/src/usage.rs | 7 +++---- 10 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index eb0455ae404c1..c9a8307eba4f2 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_hir; use rustc_hir::intravisit; use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind}; -use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; +use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; @@ -178,7 +178,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn fake_read( &mut self, - _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, + _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId, ) { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 2dcefd78763b7..89ffca8128a9e 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -32,6 +32,7 @@ extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_hir; extern crate rustc_hir_analysis; +extern crate rustc_hir_typeck; extern crate rustc_hir_pretty; extern crate rustc_index; extern crate rustc_infer; diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index db73ab55b37cf..91b321c447479 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -4,7 +4,7 @@ use clippy_utils::{get_enclosing_block, higher, path_to_local}; use if_chain::if_chain; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind}; -use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; +use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::{mir::FakeReadCause, ty}; @@ -115,7 +115,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn fake_read( &mut self, - _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, + _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId, ) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 6017941452c06..5cf88bfc8880d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -8,7 +8,7 @@ use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trai use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; -use rustc_hir_analysis::check::{FnCtxt, Inherited}; +use rustc_hir_typeck::{FnCtxt, Inherited}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 7f881e27dd27c..9c949a28f44d5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -12,7 +12,7 @@ use rustc_hir::{ BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind, }; use rustc_hir::{HirIdMap, HirIdSet}; -use rustc_hir_analysis::expr_use_visitor as euv; +use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; @@ -342,7 +342,7 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { fn fake_read( &mut self, - _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, + _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId, ) { diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index c7e964cf23e2c..ee9fd94064c08 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -8,7 +8,7 @@ use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; +use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::LateContext; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::BorrowKind; diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 102f7541c8ce1..70d166c4854c4 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -1,5 +1,5 @@ use rustc_hir::Expr; -use rustc_hir_analysis::check::{cast, FnCtxt, Inherited}; +use rustc_hir_typeck::{cast, FnCtxt, Inherited}; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_span::DUMMY_SP; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index e7e3625c078ab..7e42fcc6569b6 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -24,7 +24,7 @@ extern crate rustc_attr; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_hir; -extern crate rustc_hir_analysis; +extern crate rustc_hir_typeck; extern crate rustc_infer; extern crate rustc_lexer; extern crate rustc_lint; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 3347342e412b6..5089987ef7200 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -10,7 +10,7 @@ use rustc_ast_pretty::pprust::token_kind_to_string; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind}; -use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; +use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::hir::place::ProjectionKind; @@ -1054,11 +1054,10 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { fn fake_read( &mut self, - _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, + _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId, - ) { - } + ) {} } #[cfg(test)] diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index e32bae6ed1fd4..000fb51c01857 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirIdSet; use rustc_hir::{Expr, ExprKind, HirId, Node}; -use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; +use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -75,11 +75,10 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn fake_read( &mut self, - _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, + _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId, - ) { - } + ) {} } pub struct ParamBindingIdCollector { From 8eb2b75a110ca716ac51018f11df9a00599c670c Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Oct 2022 18:03:28 +0200 Subject: [PATCH 4/5] add increased recursion limit --- compiler/rustc_hir_typeck/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index cbff5e8820489..e862d577573b4 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -6,6 +6,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![allow(rustc::potential_query_instability)] +#![recursion_limit = "256"] #[macro_use] extern crate tracing; From adc700b0899b183fbf45dbe2e9d788e97e4d726a Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Oct 2022 23:47:49 +0200 Subject: [PATCH 5/5] update doc links --- compiler/rustc_hir_analysis/src/collect.rs | 3 +-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 5c76016c66258..66ca7d7aa08f9 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -100,13 +100,12 @@ pub fn provide(providers: &mut Providers) { /// It's also used for the bodies of items like structs where the body (the fields) /// are just signatures. /// -/// This is in contrast to [`FnCtxt`], which is used to type-check bodies of +/// This is in contrast to `FnCtxt`, which is used to type-check bodies of /// functions, closures, and `const`s -- anywhere that expressions and statements show up. /// /// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] -- /// while `FnCtxt` does do inference. /// -/// [`FnCtxt`]: crate::check::FnCtxt /// [`InferCtxt`]: rustc_infer::infer::InferCtxt /// /// # Trait predicates diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index a8004d90a4522..0c600daf4459e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -35,7 +35,7 @@ use std::ops::Deref; /// /// See [`ItemCtxt`]'s docs for more. /// -/// [`ItemCtxt`]: crate::collect::ItemCtxt +/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt /// [`InferCtxt`]: infer::InferCtxt pub struct FnCtxt<'a, 'tcx> { pub(super) body_id: hir::HirId,