diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check/check.rs')
-rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e61ca232d..8413a1cc0 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,5 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use crate::errors::{self, LinkageType}; +use crate::errors::LinkageType; use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; @@ -8,9 +8,8 @@ use rustc_attr as attr; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; +use rustc_hir::def_id::LocalModDefId; use rustc_hir::Node; -use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; @@ -21,18 +20,15 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{ - self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, + AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; -use rustc_span::{self, Span}; use rustc_target::abi::FieldIdx; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _}; +use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use rustc_type_ir::fold::TypeFoldable; use std::ops::ControlFlow; @@ -55,7 +51,7 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { hir_id, span, "use of calling convention not supported on this target", - |lint| lint, + |_| {}, ); } } @@ -130,7 +126,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b for field in &def.non_enum_variant().fields { let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args)) else { - tcx.sess.delay_span_bug(span, "could not normalize field type"); + tcx.sess.span_delayed_bug(span, "could not normalize field type"); continue; }; @@ -151,7 +147,8 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. - tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields"); + tcx.sess + .span_delayed_bug(span, "we should never accept maybe-dropping union fields"); } } } else { @@ -181,19 +178,19 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { } // Generic statics are rejected, but we still reach this case. Err(e) => { - tcx.sess.delay_span_bug(span, format!("{e:?}")); + tcx.sess.span_delayed_bug(span, format!("{e:?}")); return; } }; if layout.abi.is_uninhabited() { tcx.struct_span_lint_hir( UNINHABITED_STATIC, - tcx.hir().local_def_id_to_hir_id(def_id), + tcx.local_def_id_to_hir_id(def_id), span, "static of uninhabited type", |lint| { lint - .note("uninhabited statics cannot be initialized, and any access would be an immediate error") + .note("uninhabited statics cannot be initialized, and any access would be an immediate error"); }, ); } @@ -204,7 +201,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let item = tcx.hir().item(id); let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else { - tcx.sess.delay_span_bug(item.span, "expected opaque item"); + tcx.sess.span_delayed_bug(item.span, "expected opaque item"); return; }; @@ -222,11 +219,11 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() { return; } - if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() { + if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, origin).is_err() { return; } - let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); + let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, origin); } /// Checks that an opaque type does not contain cycles. @@ -313,7 +310,7 @@ fn check_opaque_meets_bounds<'tcx>( Ok(()) => {} Err(ty_err) => { let ty_err = ty_err.to_string(tcx); - return Err(tcx.sess.delay_span_bug( + return Err(tcx.sess.span_delayed_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), )); @@ -482,7 +479,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { match assoc_item.kind { ty::AssocKind::Fn => { let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); - fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi); + forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, id.owner_id); @@ -507,7 +504,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { let origin = tcx.opaque_type_origin(id.owner_id.def_id); if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin - && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) + && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() { // Skip opaques from RPIT in traits with no default body. @@ -518,7 +515,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).instantiate_identity(); let generics = tcx.generics_of(id.owner_id); - check_type_params_are_used(tcx, &generics, pty_ty); + check_type_params_are_used(tcx, generics, pty_ty); } DefKind::ForeignMod => { let it = tcx.hir().item(id); @@ -655,7 +652,7 @@ pub(super) fn check_specialization_validity<'tcx>( if !tcx.is_impl_trait_in_trait(impl_item) { report_forbidden_specialization(tcx, impl_item, parent_impl); } else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, format!("parent item: {parent_impl:?} not marked as default"), ); @@ -703,7 +700,7 @@ fn check_impl_items_against_trait<'tcx>( tcx.associated_item(trait_item_id) } else { // Checked in `associated_item`. - tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait"); + tcx.sess.span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait"); continue; }; match ty_impl_item.kind { @@ -753,8 +750,7 @@ fn check_impl_items_against_trait<'tcx>( leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait()); if !is_implemented_here { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); match tcx.eval_default_body_stability(trait_item_id, full_impl_span) { EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable( tcx, @@ -811,8 +807,7 @@ fn check_impl_items_against_trait<'tcx>( } if !missing_items.is_empty() { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); missing_items_err(tcx, impl_id, &missing_items, full_impl_span); } @@ -900,7 +895,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { for attr in tcx.get_attrs(def.did(), sym::repr) { - for r in attr::parse_repr_attr(&tcx.sess, attr) { + for r in attr::parse_repr_attr(tcx.sess, attr) { if let attr::ReprPacked(pack) = r && let Some(repr_pack) = repr.pack && pack as u64 != repr_pack.bytes() @@ -1083,7 +1078,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if non_trivial_count > 0 || prev_non_exhaustive_1zst { tcx.struct_span_lint_hir( REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()), + tcx.local_def_id_to_hir_id(adt.did().expect_local()), span, "zero-sized fields in `repr(transparent)` cannot \ contain external non-exhaustive types", @@ -1098,7 +1093,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) "this {descr} contains `{field_ty}`, which {note}, \ and makes it not a breaking change to become \ non-zero-sized in the future." - )) + )); }, ) } else { @@ -1150,8 +1145,8 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_)); let has_non_units = def.variants().iter().any(|var| !is_unit(var)); - let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var)); - let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var)); + let disr_units = def.variants().iter().any(|var| is_unit(var) && has_disr(var)); + let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var)); if disr_non_unit || (disr_units && has_non_units) { let mut err = struct_span_err!( @@ -1178,7 +1173,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::VariantDiscr::Explicit(discr_def_id) => { // In the case the discriminant is both a duplicate and overflowed, let the user know if let hir::Node::AnonConst(expr) = - tcx.hir().get_by_def_id(discr_def_id.expect_local()) + tcx.hir_node_by_def_id(discr_def_id.expect_local()) && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node && *lit_value != dis.val @@ -1451,7 +1446,7 @@ fn opaque_type_cycle_error( label_match(capture.place.ty(), capture.get_path_span(tcx)); } // Label any coroutine locals that capture the opaque - if let DefKind::Coroutine = tcx.def_kind(closure_def_id) + if tcx.is_coroutine(closure_def_id) && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id) { for interior_ty in &coroutine_layout.field_tys { @@ -1468,8 +1463,11 @@ fn opaque_type_cycle_error( err.emit() } -pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { - debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine)); +pub(super) fn check_coroutine_obligations( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + debug_assert!(tcx.is_coroutine(def_id.to_def_id())); let typeck = tcx.typeck(def_id); let param_env = tcx.param_env(def_id); @@ -1482,8 +1480,9 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { // typeck writeback gives us predicates with their regions erased. // As borrowck already has checked lifetimes, we do not need to do it again. .ignoring_regions() - // Bind opaque types to `def_id` as they should have been checked by borrowck. - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) + // Bind opaque types to type checking root, as they should have been checked by borrowck, + // but may show up in some cases, like when (root) obligations are stalled in the new solver. + .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id)) .build(); let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx); @@ -1513,6 +1512,16 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + + // Check that any hidden types found when checking these stalled coroutine obligations + // are valid. + for (key, ty) in infcx.take_opaque_types() { + let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type); + let key = infcx.resolve_vars_if_possible(key); + sanity_check_found_hidden_type(tcx, key, hidden_type)?; + } + + Ok(()) } |