diff options
Diffstat (limited to 'compiler/rustc_hir_analysis')
38 files changed, 1033 insertions, 899 deletions
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 196d7d99e93..55a816a855a 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_hir_analysis" version = "0.0.0" -edition = "2021" +edition = "2024" [lib] test = false diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c28c1afcfe6..47d5976be09 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -72,19 +72,29 @@ hir_analysis_cmse_entry_generic = functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type hir_analysis_cmse_inputs_stack_spill = - arguments for `"{$abi_name}"` function too large to pass via registers + arguments for `{$abi}` function too large to pass via registers .label = {$plural -> [false] this argument doesn't *[true] these arguments don't } fit in the available registers - .note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers + .note = functions with the `{$abi}` ABI must pass all their arguments via the 4 32-bit available argument registers hir_analysis_cmse_output_stack_spill = - return value of `"{$abi_name}"` function too large to pass via registers + return value of `{$abi}` function too large to pass via registers .label = this type doesn't fit in the available registers - .note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers + .note1 = functions with the `{$abi}` ABI must pass their result via the available return registers .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size +hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field + +hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden + +hir_analysis_coerce_pointee_not_concrete_ty = `derive(CoercePointee)` is only applicable to `struct` + +hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}` + +hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout + hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions @@ -377,6 +387,8 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}` + hir_analysis_not_supported_delegation = {$descr} .label = callee defined here @@ -496,6 +508,12 @@ hir_analysis_specialization_trait = implementing `rustc_specialization_trait` tr hir_analysis_static_specialize = cannot specialize on `'static` lifetime +hir_analysis_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits} + +hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item + +hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait + hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature .note = this item must mention the opaque type in its signature in order to be able to register hidden types @@ -592,7 +610,7 @@ hir_analysis_value_of_associated_struct_already_specified = .label = re-bound here .previous_bound_label = `{$item_name}` bound here first -hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` +hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions} .label = C-variadic function must have a compatible calling convention hir_analysis_variances_of = {$variances} diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs deleted file mode 100644 index 9b02651a8bd..00000000000 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ /dev/null @@ -1,100 +0,0 @@ -//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the -//! [`rustc_middle::ty`] form. - -use rustc_hir::LangItem; -use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; -use rustc_span::Span; - -/// Collects together a list of type bounds. These lists of bounds occur in many places -/// in Rust's syntax: -/// -/// ```text -/// trait Foo: Bar + Baz { } -/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter -/// -/// fn foo<T: Bar + Baz>() { } -/// ^^^^^^^^^ bounding the type parameter `T` -/// -/// impl dyn Bar + Baz -/// ^^^^^^^^^ bounding the type-erased dynamic type -/// ``` -/// -/// Our representation is a bit mixed here -- in some cases, we -/// include the self type (e.g., `trait_bounds`) but in others we do not -#[derive(Default, PartialEq, Eq, Clone, Debug)] -pub(crate) struct Bounds<'tcx> { - clauses: Vec<(ty::Clause<'tcx>, Span)>, -} - -impl<'tcx> Bounds<'tcx> { - pub(crate) fn push_region_bound( - &mut self, - tcx: TyCtxt<'tcx>, - region: ty::PolyTypeOutlivesPredicate<'tcx>, - span: Span, - ) { - self.clauses - .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span)); - } - - pub(crate) fn push_trait_bound( - &mut self, - tcx: TyCtxt<'tcx>, - bound_trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - polarity: ty::PredicatePolarity, - ) { - let clause = ( - bound_trait_ref - .map_bound(|trait_ref| { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) - }) - .upcast(tcx), - span, - ); - // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. - if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) { - self.clauses.insert(0, clause); - } else { - self.clauses.push(clause); - } - } - - pub(crate) fn push_projection_bound( - &mut self, - tcx: TyCtxt<'tcx>, - projection: ty::PolyProjectionPredicate<'tcx>, - span: Span, - ) { - self.clauses.push(( - projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx), - span, - )); - } - - pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { - let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); - // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.clauses.insert(0, (trait_ref.upcast(tcx), span)); - } - - /// Push a `const` or `~const` bound as a `HostEffect` predicate. - pub(crate) fn push_const_bound( - &mut self, - tcx: TyCtxt<'tcx>, - bound_trait_ref: ty::PolyTraitRef<'tcx>, - constness: ty::BoundConstness, - span: Span, - ) { - if tcx.is_const_trait(bound_trait_ref.def_id()) { - self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span)); - } else { - tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait"); - } - } - - pub(crate) fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ { - self.clauses.iter().cloned() - } -} diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 6c534d58a7d..3236e0a3644 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -6,7 +6,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::{Node, intravisit}; +use rustc_hir::{LangItem, Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_lint_defs::builtin::{ @@ -15,11 +15,10 @@ use rustc_lint_defs::builtin::{ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::span_bug; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; -use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; +use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; @@ -27,6 +26,7 @@ use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_type_ir::fold::TypeFoldable; use tracing::{debug, instrument}; use ty::TypingMode; @@ -34,7 +34,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; use super::*; -use crate::check::intrinsicck::InlineAsmCtxt; pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) { if !tcx.sess.target.is_abi_supported(abi) { @@ -87,89 +86,76 @@ fn allowed_union_or_unsafe_field<'tcx>( typing_env: ty::TypingEnv<'tcx>, span: Span, ) -> bool { - // We don't just accept all !needs_drop fields, due to semver concerns. - let allowed = match ty.kind() { - ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) - ty::Tuple(tys) => { - // allow tuples of allowed types - tys.iter().all(|ty| allowed_union_or_unsafe_field(tcx, ty, typing_env, span)) - } - ty::Array(elem, _len) => { - // Like `Copy`, we do *not* special-case length 0. - allowed_union_or_unsafe_field(tcx, *elem, typing_env, span) - } - _ => { - // Fallback case: allow `ManuallyDrop` and things that are `Copy`, - // also no need to report an error if the type is unresolved. - ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || tcx.type_is_copy_modulo_regions(typing_env, ty) - || ty.references_error() - } - }; - if allowed && ty.needs_drop(tcx, typing_env) { - // This should never happen. But we can get here e.g. in case of name resolution errors. - tcx.dcx() - .span_delayed_bug(span, "we should never accept maybe-dropping union or unsafe fields"); + // HACK (not that bad of a hack don't worry): Some codegen tests don't even define proper + // impls for `Copy`. Let's short-circuit here for this validity check, since a lot of them + // use unions. We should eventually fix all the tests to define that lang item or use + // minicore stubs. + if ty.is_trivially_pure_clone_copy() { + return true; } - allowed + // If `BikeshedGuaranteedNoDrop` is not defined in a `#[no_core]` test, fall back to `Copy`. + // This is an underapproximation of `BikeshedGuaranteedNoDrop`, + let def_id = tcx + .lang_items() + .get(LangItem::BikeshedGuaranteedNoDrop) + .unwrap_or_else(|| tcx.require_lang_item(LangItem::Copy, Some(span))); + let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) else { + tcx.dcx().span_delayed_bug(span, "could not normalize field type"); + return true; + }; + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + infcx.predicate_must_hold_modulo_regions(&Obligation::new( + tcx, + ObligationCause::dummy_with_span(span), + param_env, + ty::TraitRef::new(tcx, def_id, [ty]), + )) } /// Check that the fields of the `union` do not need dropping. fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool { - let item_type = tcx.type_of(item_def_id).instantiate_identity(); - if let ty::Adt(def, args) = item_type.kind() { - assert!(def.is_union()); - - let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); - for field in &def.non_enum_variant().fields { - let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args)) - else { - tcx.dcx().span_delayed_bug(span, "could not normalize field type"); - continue; - }; + let def = tcx.adt_def(item_def_id); + assert!(def.is_union()); - if !allowed_union_or_unsafe_field(tcx, field_ty, typing_env, span) { - let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { - // We are currently checking the type this field came from, so it must be local. - Some(Node::Field(field)) => (field.span, field.ty.span), - _ => unreachable!("mir field has to correspond to hir field"), - }; - tcx.dcx().emit_err(errors::InvalidUnionField { - field_span, - sugg: errors::InvalidUnionFieldSuggestion { - lo: ty_span.shrink_to_lo(), - hi: ty_span.shrink_to_hi(), - }, - note: (), - }); - return false; - } + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); + let args = ty::GenericArgs::identity_for_item(tcx, item_def_id); + + for field in &def.non_enum_variant().fields { + if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) { + let (field_span, ty_span) = match tcx.hir_get_if_local(field.did) { + // We are currently checking the type this field came from, so it must be local. + Some(Node::Field(field)) => (field.span, field.ty.span), + _ => unreachable!("mir field has to correspond to hir field"), + }; + tcx.dcx().emit_err(errors::InvalidUnionField { + field_span, + sugg: errors::InvalidUnionFieldSuggestion { + lo: ty_span.shrink_to_lo(), + hi: ty_span.shrink_to_hi(), + }, + note: (), + }); + return false; } - } else { - span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind()); } + true } /// Check that the unsafe fields do not need dropping. fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) { let span = tcx.def_span(item_def_id); - let item_type = tcx.type_of(item_def_id).instantiate_identity(); - let ty::Adt(def, args) = item_type.kind() else { - span_bug!(span, "structs/enums must be ty::Adt, but got {:?}", item_type.kind()); - }; + let def = tcx.adt_def(item_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); + let args = ty::GenericArgs::identity_for_item(tcx, item_def_id); + for field in def.all_fields() { if !field.safety.is_unsafe() { continue; } - let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args)) - else { - tcx.dcx().span_delayed_bug(span, "could not normalize field type"); - continue; - }; - if !allowed_union_or_unsafe_field(tcx, field_ty, typing_env, span) { + if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) { let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else { unreachable!("field has to correspond to hir field") }; @@ -257,30 +243,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>( // First, try to look at any opaque expansion cycles, considering coroutine fields // (even though these aren't necessarily true errors). - if tcx - .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes) - .is_err() - { - // Look for true opaque expansion cycles, but ignore coroutines. - // This will give us any true errors. Coroutines are only problematic - // if they cause layout computation errors. - if tcx - .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No) - .is_err() - { - let reported = opaque_type_cycle_error(tcx, def_id); - return Err(reported); - } - - // And also look for cycle errors in the layout of coroutines. - if let Err(&LayoutError::Cycle(guar)) = - tcx.layout_of( - ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) - .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)), - ) - { - return Err(guar); - } + if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() { + let reported = opaque_type_cycle_error(tcx, def_id); + return Err(reported); } Ok(()) @@ -468,8 +433,8 @@ fn best_definition_site_of_opaque<'tcx>( impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { type NestedFilter = nested_filter::All; type Result = ControlFlow<(Span, LocalDefId)>; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result { if let hir::ExprKind::Closure(closure) = ex.kind { @@ -515,9 +480,9 @@ fn best_definition_site_of_opaque<'tcx>( None } hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { - let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); + let scope = tcx.hir_get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); let found = if scope == hir::CRATE_HIR_ID { - tcx.hir().walk_toplevel_module(&mut locator) + tcx.hir_walk_toplevel_module(&mut locator) } else { match tcx.hir_node(scope) { Node::Item(it) => locator.visit_item(it), @@ -913,7 +878,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { .emit(); } - let item = tcx.hir().foreign_item(item.id); + let item = tcx.hir_foreign_item(item.id); match &item.kind { hir::ForeignItemKind::Fn(sig, _, _) => { require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); @@ -928,13 +893,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } } - DefKind::GlobalAsm => { - let it = tcx.hir().expect_item(def_id); - let hir::ItemKind::GlobalAsm(asm) = it.kind else { - span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) - }; - InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id); - } _ => {} } } @@ -1527,7 +1485,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) // In the case the discriminant is both a duplicate and overflowed, let the user know if let hir::Node::AnonConst(expr) = tcx.hir_node_by_def_id(discr_def_id.expect_local()) - && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind + && 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 { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index a91d72e9225..c193aad2afd 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -182,12 +182,15 @@ fn compare_method_predicate_entailment<'tcx>( // obligations. let impl_m_def_id = impl_m.def_id.expect_local(); let impl_m_span = tcx.def_span(impl_m_def_id); - let cause = - ObligationCause::new(impl_m_span, impl_m_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + impl_m_span, + impl_m_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_m_def_id, trait_item_def_id: trait_m.def_id, kind: impl_m.kind, - }); + }, + ); // Create mapping from trait method to impl method. let impl_def_id = impl_m.container_id(tcx); @@ -248,12 +251,15 @@ fn compare_method_predicate_entailment<'tcx>( let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id); let predicate = ocx.normalize(&normalize_cause, param_env, predicate); - let cause = - ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + span, + impl_m_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_m_def_id, trait_item_def_id: trait_m.def_id, kind: impl_m.kind, - }); + }, + ); ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate)); } @@ -270,12 +276,15 @@ fn compare_method_predicate_entailment<'tcx>( let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id); let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition); - let cause = - ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + span, + impl_m_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_m_def_id, trait_item_def_id: trait_m.def_id, kind: impl_m.kind, - }); + }, + ); ocx.register_obligation(traits::Obligation::new( tcx, cause, @@ -492,13 +501,16 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); - let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); - let cause = - ObligationCause::new(return_span, impl_m_def_id, ObligationCauseCode::CompareImplItem { + let return_span = tcx.hir_fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); + let cause = ObligationCause::new( + return_span, + impl_m_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_m_def_id, trait_item_def_id: trait_m.def_id, kind: impl_m.kind, - }); + }, + ); // Create mapping from trait to impl (i.e. impl trait header + impl method identity args). let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto( @@ -534,12 +546,15 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id); let predicate = ocx.normalize(&normalize_cause, param_env, predicate); - let cause = - ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + span, + impl_m_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_m_def_id, trait_item_def_id: trait_m.def_id, kind: impl_m.kind, - }); + }, + ); ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate)); } @@ -606,13 +621,16 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( idx += 1; ( ty, - Ty::new_placeholder(tcx, ty::Placeholder { - universe, - bound: ty::BoundTy { - var: ty::BoundVar::from_usize(idx), - kind: ty::BoundTyKind::Anon, + Ty::new_placeholder( + tcx, + ty::Placeholder { + universe, + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(idx), + kind: ty::BoundTyKind::Anon, + }, }, - }), + ), ) }) .collect(); @@ -640,11 +658,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( "method `{}` has an incompatible return type for trait", trait_m.name ); - let hir = tcx.hir(); infcx.err_ctxt().note_type_err( &mut diag, &cause, - hir.get_if_local(impl_m.def_id) + tcx.hir_get_if_local(impl_m.def_id) .and_then(|node| node.fn_decl()) .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)), Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound { @@ -969,10 +986,13 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { return Err(guar); }; - Ok(ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion { - name: e.name, - index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32, - })) + Ok(ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { + name: e.name, + index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32, + }, + )) } } @@ -1013,8 +1033,7 @@ fn report_trait_method_mismatch<'tcx>( // argument pattern and type. let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); let span = tcx - .hir() - .body_param_names(body) + .hir_body_param_names(body) .zip(sig.decl.inputs.iter()) .map(|(param, ty)| param.span.to(ty.span)) .next() @@ -1102,15 +1121,14 @@ fn check_region_bounds_on_impl_item<'tcx>( // the moment, give a kind of vague error message. if trait_params != impl_params { let span = tcx - .hir() - .get_generics(impl_m.def_id.expect_local()) + .hir_get_generics(impl_m.def_id.expect_local()) .expect("expected impl item to have generics or else we can't compare them") .span; let mut generics_span = None; let mut bounds_span = vec![]; let mut where_span = None; - if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id) + if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) && let Some(trait_generics) = trait_node.generics() { generics_span = Some(trait_generics.span); @@ -1125,7 +1143,7 @@ fn check_region_bounds_on_impl_item<'tcx>( } } } - if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id) + if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) && let Some(impl_generics) = impl_node.generics() { let mut impl_bounds = 0; @@ -1967,12 +1985,15 @@ fn compare_type_predicate_entailment<'tcx>( let cause = ObligationCause::misc(span, impl_ty_def_id); let predicate = ocx.normalize(&cause, param_env, predicate); - let cause = - ObligationCause::new(span, impl_ty_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + span, + impl_ty_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_ty.def_id.expect_local(), trait_item_def_id: trait_ty.def_id, kind: impl_ty.kind, - }); + }, + ); ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate)); } @@ -1984,12 +2005,15 @@ fn compare_type_predicate_entailment<'tcx>( let normalize_cause = traits::ObligationCause::misc(span, impl_ty_def_id); let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition); - let cause = - ObligationCause::new(span, impl_ty_def_id, ObligationCauseCode::CompareImplItem { + let cause = ObligationCause::new( + span, + impl_ty_def_id, + ObligationCauseCode::CompareImplItem { impl_item_def_id: impl_ty_def_id, trait_item_def_id: trait_ty.def_id, kind: impl_ty.kind, - }); + }, + ); ocx.register_obligation(traits::Obligation::new( tcx, cause, @@ -2080,18 +2104,21 @@ pub(super) fn check_type_bounds<'tcx>( ObligationCause::new(impl_ty_span, impl_ty_def_id, code) }; - let mut obligations: Vec<_> = tcx - .explicit_item_bounds(trait_ty.def_id) - .iter_instantiated_copied(tcx, rebased_args) - .map(|(concrete_ty_bound, span)| { - debug!(?concrete_ty_bound); - traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound) - }) - .collect(); + let mut obligations: Vec<_> = util::elaborate( + tcx, + tcx.explicit_item_bounds(trait_ty.def_id).iter_instantiated_copied(tcx, rebased_args).map( + |(concrete_ty_bound, span)| { + debug!(?concrete_ty_bound); + traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound) + }, + ), + ) + .collect(); // Only in a const implementation do we need to check that the `~const` item bounds hold. if tcx.is_conditionally_const(impl_ty_def_id) { - obligations.extend( + obligations.extend(util::elaborate( + tcx, tcx.explicit_implied_const_bounds(trait_ty.def_id) .iter_instantiated_copied(tcx, rebased_args) .map(|(c, span)| { @@ -2102,7 +2129,7 @@ pub(super) fn check_type_bounds<'tcx>( c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe), ) }), - ); + )); } debug!(item_bounds=?obligations); @@ -2110,26 +2137,19 @@ pub(super) fn check_type_bounds<'tcx>( // to its definition type. This should be the param-env we use to *prove* the // predicate too, but we don't do that because of performance issues. // See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>. - let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args); - let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity(); let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); - for mut obligation in util::elaborate(tcx, obligations) { - let normalized_predicate = if infcx.next_trait_solver() { - obligation.predicate.fold_with(&mut ReplaceTy { - tcx, - from: trait_projection_ty, - to: impl_identity_ty, - }) - } else { - ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate) - }; - debug!(?normalized_predicate); - obligation.predicate = normalized_predicate; - - ocx.register_obligation(obligation); + for obligation in &mut obligations { + match ocx.deeply_normalize(&normalize_cause, normalize_param_env, obligation.predicate) { + Ok(pred) => obligation.predicate = pred, + Err(e) => { + return Err(infcx.err_ctxt().report_fulfillment_errors(e)); + } + } } + // Check that all obligations are satisfied by the implementation's // version. + ocx.register_obligations(obligations); let errors = ocx.select_all_or_error(); if !errors.is_empty() { let reported = infcx.err_ctxt().report_fulfillment_errors(errors); @@ -2141,22 +2161,6 @@ pub(super) fn check_type_bounds<'tcx>( ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types) } -struct ReplaceTy<'tcx> { - tcx: TyCtxt<'tcx>, - from: Ty<'tcx>, - to: Ty<'tcx>, -} - -impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if self.from == ty { self.to } else { ty.super_fold_with(self) } - } -} - /// Install projection predicates that allow GATs to project to their own /// definition types. This is not allowed in general in cases of default /// associated types in trait definitions, or when specialization is involved, @@ -2244,20 +2248,25 @@ fn param_env_with_gat_bounds<'tcx>( let kind = ty::BoundTyKind::Param(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Ty(kind); bound_vars.push(bound_var); - Ty::new_bound(tcx, ty::INNERMOST, ty::BoundTy { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind, - }) + Ty::new_bound( + tcx, + ty::INNERMOST, + ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, + ) .into() } GenericParamDefKind::Lifetime => { let kind = ty::BoundRegionKind::Named(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); - ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind, - }) + ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind, + }, + ) .into() } GenericParamDefKind::Const { .. } => { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 0e9e9b48ab3..4973d848959 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -96,7 +96,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // This opaque also needs to be from the impl method -- otherwise, // it's a refinement to a TAIT. - if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| { + if !tcx.hir_get_if_local(impl_opaque.def_id).is_some_and(|node| { matches!( node.expect_opaque_ty().origin, hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::FnReturn { parent, .. } @@ -327,7 +327,7 @@ fn report_mismatched_rpitit_signature<'tcx>( hir::FnRetTy::Return(ty) => (ty.span, ty.span, "", ""), }; let trait_return_span = - tcx.hir().get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output { + tcx.hir_get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output { hir::FnRetTy::DefaultReturn(_) => tcx.def_span(trait_m_def_id), hir::FnRetTy::Return(ty) => ty.span, }); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 40769ef7536..d468027602c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -140,6 +140,10 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::fmul_algebraic | sym::fdiv_algebraic | sym::frem_algebraic + | sym::round_ties_even_f16 + | sym::round_ties_even_f32 + | sym::round_ties_even_f64 + | sym::round_ties_even_f128 | sym::const_eval_select => hir::Safety::Safe, _ => hir::Safety::Unsafe, }; @@ -185,14 +189,19 @@ pub fn check_intrinsic_type( ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { - var: ty::BoundVar::ZERO, - kind: ty::BoundRegionKind::Anon, - }); - let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { - var: ty::BoundVar::from_u32(2), - kind: ty::BoundRegionKind::ClosureEnv, - }); + let region = ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon }, + ); + let env_region = ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_u32(2), + kind: ty::BoundRegionKind::ClosureEnv, + }, + ); let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]); (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty) }) @@ -411,26 +420,16 @@ pub fn check_intrinsic_type( sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::rintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::rintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::rintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::rintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::nearbyintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::nearbyintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::nearbyintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::nearbyintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), + sym::round_ties_even_f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), + sym::round_ties_even_f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), + sym::round_ties_even_f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), + sym::round_ties_even_f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::roundevenf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::roundevenf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::roundevenf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::roundevenf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::volatile_load | sym::unaligned_volatile_load => { (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)) } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 90e93bdbb50..e1727fc48a8 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; -use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; +use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Symbol, sym}; @@ -16,10 +16,11 @@ use rustc_target::asm::{ use crate::errors::RegisterTypeUnstable; -pub struct InlineAsmCtxt<'a, 'tcx> { +pub struct InlineAsmCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>, + target_features: &'tcx FxIndexSet<Symbol>, + expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>, } enum NonAsmTypeReason<'tcx> { @@ -29,25 +30,24 @@ enum NonAsmTypeReason<'tcx> { } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { - pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, + ) -> Self { InlineAsmCtxt { tcx, typing_env: ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env: ty::ParamEnv::empty(), }, - get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), + target_features: tcx.asm_target_features(def_id), + expr_ty: Box::new(get_operand_ty), } } - // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their - // defining scope. - pub fn new_in_fn( - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, - ) -> Self { - InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) } + fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { + (self.expr_ty)(expr) } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` @@ -139,9 +139,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>, - target_features: &FxIndexSet<Symbol>, ) -> Option<InlineAsmType> { - let ty = (self.get_operand_ty)(expr); + let ty = self.expr_ty(expr); if ty.has_non_region_infer() { bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty); } @@ -229,7 +228,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some((in_expr, Some(in_asm_ty))) = tied_input { if in_asm_ty != asm_ty { let msg = "incompatible types for asm inout argument"; - let in_expr_ty = (self.get_operand_ty)(in_expr); + let in_expr_ty = self.expr_ty(in_expr); self.tcx .dcx() .struct_span_err(vec![in_expr.span, expr.span], msg) @@ -291,7 +290,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // (!). In that case we still need the earlier check to verify that the // register class is usable at all. if let Some(feature) = feature { - if !target_features.contains(feature) { + if !self.target_features.contains(feature) { let msg = format!("`{feature}` target feature is not enabled"); self.tcx .dcx() @@ -351,14 +350,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { Some(asm_ty) } - pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) { - let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id()); + pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { let Some(asm_arch) = self.tcx.sess.asm_arch else { self.tcx.dcx().delayed_bug("target architecture does not support asm"); return; }; let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); - for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() { // Validate register classes against currently enabled target // features. We check that at least one type is available for // the enabled features. @@ -381,12 +379,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Err(msg) = reg.validate( asm_arch, self.tcx.sess.relocation_model(), - target_features, + self.target_features, &self.tcx.sess.target, op.is_clobber(), ) { let msg = format!("cannot use register `{}`: {}", reg.name(), msg); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); continue; } } @@ -401,7 +399,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { { match feature { Some(feature) => { - if target_features.contains(&feature) { + if self.target_features.contains(&feature) { missing_required_features.clear(); break; } else { @@ -426,7 +424,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { reg_class.name(), feature ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -440,7 +438,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { .intersperse(", ") .collect::<String>(), ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -448,52 +446,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } } - match *op { + match op { hir::InlineAsmOperand::In { reg, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - true, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); } hir::InlineAsmOperand::Out { reg, late: _, expr } => { if let Some(expr) = expr { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } } hir::InlineAsmOperand::InOut { reg, late: _, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => { - let in_ty = self.check_asm_operand_type( - idx, - reg, - in_expr, - asm.template, - true, - None, - target_features, - ); + let in_ty = + self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, @@ -502,7 +469,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, Some((in_expr, in_ty)), - target_features, ); } } @@ -514,11 +480,25 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ); } // Typeck has checked that SymFn refers to a function. - hir::InlineAsmOperand::SymFn { anon_const } => { - debug_assert_matches!( - self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), - ty::Error(_) | ty::FnDef(..) - ); + hir::InlineAsmOperand::SymFn { expr } => { + let ty = self.expr_ty(expr); + match ty.kind() { + ty::FnDef(..) => {} + ty::Error(_) => {} + _ => { + self.tcx + .dcx() + .struct_span_err(op_sp, "invalid `sym` operand") + .with_span_label( + expr.span, + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help( + "`sym` operands must refer to either a function or a static", + ) + .emit(); + } + } } // AST lowering guarantees that SymStatic points to a static. hir::InlineAsmOperand::SymStatic { .. } => {} diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 96b33bdd250..1c5455710db 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -127,9 +127,9 @@ fn get_owner_return_paths( def_id: LocalDefId, ) -> Option<(LocalDefId, ReturnsVisitor<'_>)> { let hir_id = tcx.local_def_id_to_hir_id(def_id); - let parent_id = tcx.hir().get_parent_item(hir_id).def_id; + let parent_id = tcx.hir_get_parent_item(hir_id).def_id; tcx.hir_node_by_def_id(parent_id).body_id().map(|body_id| { - let body = tcx.hir().body(body_id); + let body = tcx.hir_body(body_id); let mut visitor = ReturnsVisitor::default(); visitor.visit_body(body); (parent_id, visitor) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index d43c65c0023..255f5fee52a 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -424,7 +424,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi // that share the parent environment. We handle const blocks in // `visit_inline_const`. hir::ExprKind::Closure(&hir::Closure { body, .. }) => { - let body = visitor.tcx.hir().body(body); + let body = visitor.tcx.hir_body(body); visitor.visit_body(body); } hir::ExprKind::AssignOp(_, left_expr, right_expr) => { @@ -844,7 +844,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { fn visit_body(&mut self, body: &hir::Body<'tcx>) { let body_id = body.id(); - let owner_id = self.tcx.hir().body_owner_def_id(body_id); + let owner_id = self.tcx.hir_body_owner_def_id(body_id); debug!( "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})", @@ -855,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { ); self.enter_body(body.value.hir_id, |this| { - if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { + if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. this.cx.var_parent = this.cx.parent.take(); for param in body.params { @@ -906,7 +906,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_local(self, Some(l.pat), l.init) } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { - let body = self.tcx.hir().body(c.body); + let body = self.tcx.hir_body(c.body); self.visit_body(body); } } @@ -924,7 +924,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { return tcx.region_scope_tree(typeck_root_def_id); } - let scope_tree = if let Some(body) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) { + let scope_tree = if let Some(body) = tcx.hir_maybe_body_owned_by(def_id.expect_local()) { let mut visitor = ScopeResolutionVisitor { tcx, scope_tree: ScopeTree::default(), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 20eb96f3ab1..e6ea6eddcaa 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -12,10 +12,10 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{AmbigArg, ItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION; use rustc_macros::LintDiagnostic; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::query::Providers; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, @@ -142,33 +142,7 @@ where return Ok(()); } - let is_bevy = 'is_bevy: { - // We don't want to emit this for dependents of Bevy, for now. - // See #119956 - let is_bevy_paramset = |def: ty::AdtDef<'_>| { - let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did)); - adt_did.contains("ParamSet") - }; - for ty in assumed_wf_types.iter() { - match ty.kind() { - ty::Adt(def, _) => { - if is_bevy_paramset(*def) { - break 'is_bevy true; - } - } - ty::Ref(_, ty, _) => match ty.kind() { - ty::Adt(def, _) => { - if is_bevy_paramset(*def) { - break 'is_bevy true; - } - } - _ => {} - }, - _ => {} - } - } - false - }; + let is_bevy = assumed_wf_types.visit_with(&mut ContainsBevyParamSet { tcx }).is_break(); // If we have set `no_implied_bounds_compat`, then do not attempt compatibility. // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`, @@ -193,6 +167,31 @@ where } } +struct ContainsBevyParamSet<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + // We only care to match `ParamSet<T>` or `&ParamSet<T>`. + match t.kind() { + ty::Adt(def, _) => { + if self.tcx.item_name(def.did()) == sym::ParamSet + && self.tcx.crate_name(def.did().krate) == sym::bevy_ecs + { + return ControlFlow::Break(()); + } + } + ty::Ref(_, ty, _) => ty.visit_with(self)?, + _ => {} + } + + ControlFlow::Continue(()) + } +} + fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let node = tcx.hir_node_by_def_id(def_id); let mut res = match node { @@ -388,7 +387,12 @@ fn check_trait_item<'tcx>( hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span), _ => (None, trait_item.span), }; + check_dyn_incompatible_self_trait_by_name(tcx, trait_item); + + // Check that an item definition in a subtrait is shadowing a supertrait item. + lint_item_shadowing_supertrait_item(tcx, def_id); + let mut res = check_associated_item(tcx, def_id, span, method_sig); if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) { @@ -675,10 +679,10 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // Same for the region. In our example, 'a corresponds // to the 'me parameter. let region_param = gat_generics.param_at(*region_a_idx, tcx); - let region_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion { - index: region_param.index, - name: region_param.name, - }); + let region_param = ty::Region::new_early_param( + tcx, + ty::EarlyParamRegion { index: region_param.index, name: region_param.name }, + ); // The predicate we expect to see. (In our example, // `Self: 'me`.) bounds.insert( @@ -704,16 +708,16 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( debug!("required clause: {region_a} must outlive {region_b}"); // Translate into the generic parameters of the GAT. let region_a_param = gat_generics.param_at(*region_a_idx, tcx); - let region_a_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion { - index: region_a_param.index, - name: region_a_param.name, - }); + let region_a_param = ty::Region::new_early_param( + tcx, + ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name }, + ); // Same for the region. let region_b_param = gat_generics.param_at(*region_b_idx, tcx); - let region_b_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion { - index: region_b_param.index, - name: region_b_param.name, - }); + let region_b_param = ty::Region::new_early_param( + tcx, + ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name }, + ); // The predicate we expect to see. bounds.insert( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( @@ -849,7 +853,7 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// In such cases, suggest using `Self` instead. fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { let (trait_name, trait_def_id) = - match tcx.hir_node_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { + match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { hir::ItemKind::Trait(..) => (item.ident, item.owner_id), _ => return, @@ -898,6 +902,45 @@ fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitI } } +fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) { + let item_name = tcx.item_name(trait_item_def_id.to_def_id()); + let trait_def_id = tcx.local_parent(trait_item_def_id); + + let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id()) + .skip(1) + .flat_map(|supertrait_def_id| { + tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name) + }) + .collect(); + if !shadowed.is_empty() { + let shadowee = if let [shadowed] = shadowed[..] { + errors::SupertraitItemShadowee::Labeled { + span: tcx.def_span(shadowed.def_id), + supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()), + } + } else { + let (traits, spans): (Vec<_>, Vec<_>) = shadowed + .iter() + .map(|item| { + (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id)) + }) + .unzip(); + errors::SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() } + }; + + tcx.emit_node_span_lint( + SUPERTRAIT_ITEM_SHADOWING_DEFINITION, + tcx.local_def_id_to_hir_id(trait_item_def_id), + tcx.def_span(trait_item_def_id), + errors::SupertraitItemShadowing { + item: item_name, + subtrait: tcx.item_name(trait_def_id.to_def_id()), + shadowee, + }, + ); + } +} + fn check_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_item: &'tcx hir::ImplItem<'tcx>, @@ -1118,7 +1161,7 @@ fn check_type_defn<'tcx>( // be refactored to check the instantiate-ability of the code better. if let Some(def_id) = def_id.as_local() && let hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id) - && let expr = &tcx.hir().body(anon.body).value + && let expr = &tcx.hir_body(anon.body).value && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let Res::Def(DefKind::ConstParam, _def_id) = path.res { @@ -1647,10 +1690,15 @@ fn check_fn_or_method<'tcx>( } // If the function has a body, additionally require that the return type is sized. - check_sized_if_body(wfcx, def_id, sig.output(), match hir_decl.output { - hir::FnRetTy::Return(ty) => Some(ty.span), - hir::FnRetTy::DefaultReturn(_) => None, - }); + check_sized_if_body( + wfcx, + def_id, + sig.output(), + match hir_decl.output { + hir::FnRetTy::Return(ty) => Some(ty.span), + hir::FnRetTy::DefaultReturn(_) => None, + }, + ); } fn check_sized_if_body<'tcx>( @@ -1660,7 +1708,7 @@ fn check_sized_if_body<'tcx>( maybe_span: Option<Span>, ) { let tcx = wfcx.tcx(); - if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) { + if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) { let span = maybe_span.unwrap_or(body.value.span); wfcx.register_bound( diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 68b7b44c36d..750c09887a1 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -13,11 +13,11 @@ pub(crate) fn provide(providers: &mut Providers) { fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) { let mut used_trait_imports = UnordSet::<LocalDefId>::default(); - // FIXME: Use `tcx.hir().par_body_owners()` when we implement creating `DefId`s + // FIXME: Use `tcx.hir_par_body_owners()` when we implement creating `DefId`s // for anon constants during their parents' typeck. // Doing so at current will produce queries cycle errors because it may typeck // on anon constants directly. - for item_def_id in tcx.hir().body_owners() { + for item_def_id in tcx.hir_body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend_unord(imports.items().copied()); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 3511dbc6252..b46b805f0a9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -48,6 +48,10 @@ pub(super) fn check_trait<'tcx>( checker .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?; checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?; + checker.check( + lang_items.coerce_pointee_validated_trait(), + visit_implementation_of_coerce_pointee_validity, + )?; Ok(()) } @@ -333,10 +337,11 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() tcx, cause.clone(), param_env, - ty::TraitRef::new(tcx, dispatch_from_dyn_trait, [ - field.ty(tcx, args_a), - field.ty(tcx, args_b), - ]), + ty::TraitRef::new( + tcx, + dispatch_from_dyn_trait, + [field.ty(tcx, args_a), field.ty(tcx, args_b)], + ), )); } let errors = ocx.select_all_or_error(); @@ -674,7 +679,7 @@ fn infringing_fields_error<'tcx>( suggest_constraining_type_params( tcx, - tcx.hir().get_generics(impl_did).expect("impls always have generics"), + tcx.hir_get_generics(impl_did).expect("impls always have generics"), &mut err, bounds .iter() @@ -782,3 +787,32 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err .with_note(why_disqualified) .emit()) } + +fn visit_implementation_of_coerce_pointee_validity( + checker: &Checker<'_>, +) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty(); + let span = tcx.def_span(checker.impl_def_id); + if !tcx.is_builtin_derived(checker.impl_def_id.into()) { + return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span })); + } + let ty::Adt(def, _args) = self_ty.kind() else { + return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span })); + }; + let did = def.did(); + // Now get a more precise span of the `struct`. + let span = tcx.def_span(did); + if !def.is_struct() { + return Err(tcx + .dcx() + .emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() })); + } + if !def.repr().transparent() { + return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span })); + } + if def.all_fields().next().is_none() { + return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span })); + } + Ok(()) +} diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index a86dede48bf..c9a9180c5c9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -25,7 +25,7 @@ pub(crate) fn crate_inherent_impls( let mut collect = InherentCollect { tcx, impls_map: Default::default() }; let mut res = Ok(()); - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { res = res.and(collect.check_item(id)); } @@ -113,7 +113,7 @@ impl<'tcx> InherentCollect<'tcx> { ty: Ty<'tcx>, ) -> Result<(), ErrorGuaranteed> { let items = self.tcx.associated_item_def_ids(impl_def_id); - if !self.tcx.hir().rustc_coherence_is_core() { + if !self.tcx.hir_rustc_coherence_is_core() { if self.tcx.features().rustc_attrs() { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 5127e73d978..dc616576c9c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -18,7 +18,7 @@ pub(crate) fn crate_inherent_impls_overlap_check( ) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; let mut res = Ok(()); - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { res = res.and(inherent_overlap_checker.check_item(id)); } res @@ -251,10 +251,13 @@ impl<'tcx> InherentOverlapChecker<'tcx> { for ident in &idents_to_add { connected_region_ids.insert(*ident, id_to_set); } - connected_regions.insert(id_to_set, ConnectedRegion { - idents: idents_to_add, - impl_blocks: std::iter::once(i).collect(), - }); + connected_regions.insert( + id_to_set, + ConnectedRegion { + idents: idents_to_add, + impl_blocks: std::iter::once(i).collect(), + }, + ); } // Take the only id inside the list &[id_to_set] => { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index ce7319f6561..dd91d70b004 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -20,7 +20,6 @@ use std::ops::Bound; use rustc_abi::ExternAbi; use rustc_ast::Recovered; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordMap; use rustc_errors::{ @@ -277,8 +276,8 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -469,7 +468,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { let item = self .tcx .hir() - .expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id); + .expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id); match &item.kind { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) @@ -614,9 +613,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { if !infer_replacements.is_empty() { diag.multipart_suggestion( format!( - "try replacing `_` with the type{} in the corresponding trait method signature", - rustc_errors::pluralize!(infer_replacements.len()), - ), + "try replacing `_` with the type{} in the corresponding trait method \ + signature", + rustc_errors::pluralize!(infer_replacements.len()), + ), infer_replacements, Applicability::MachineApplicable, ); @@ -668,7 +668,7 @@ fn get_new_lifetime_name<'tcx>( #[instrument(level = "debug", skip_all)] fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { - let it = tcx.hir().item(item_id); + let it = tcx.hir_item(item_id); debug!(item = %it.ident, id = %it.hir_id()); let def_id = item_id.owner_id.def_id; let icx = ItemCtxt::new(tcx, def_id); @@ -679,10 +679,10 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(_) - | hir::ItemKind::GlobalAsm(_) => {} + | hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::ForeignMod { items, .. } => { for item in *items { - let item = tcx.hir().foreign_item(item.id); + let item = tcx.hir_foreign_item(item.id); tcx.ensure_ok().generics_of(item.owner_id); tcx.ensure_ok().type_of(item.owner_id); tcx.ensure_ok().predicates_of(item.owner_id); @@ -789,7 +789,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { - let trait_item = tcx.hir().trait_item(trait_item_id); + let trait_item = tcx.hir_trait_item(trait_item_id); let def_id = trait_item_id.owner_id; tcx.ensure_ok().generics_of(def_id); let icx = ItemCtxt::new(tcx, def_id.def_id); @@ -864,7 +864,7 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - let impl_item = tcx.hir().impl_item(impl_item_id); + let impl_item = tcx.hir_impl_item(impl_item_id); let icx = ItemCtxt::new(tcx, def_id.def_id); match impl_item.kind { hir::ImplItemKind::Fn(..) => { @@ -1348,7 +1348,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn } Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { - let adt_def_id = tcx.hir().get_parent_item(hir_id).def_id.to_def_id(); + let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id(); let ty = tcx.type_of(adt_def_id).instantiate_identity(); let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity()); // constructors for structs with `layout_scalar_valid_range` are unsafe to call @@ -1689,10 +1689,10 @@ fn polarity_of_impl( /// the lifetimes that are declared. For fns or methods, we have to /// screen out those that do not appear in any where-clauses etc using /// `resolve_lifetime::early_bound_lifetimes`. -fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( +fn early_bound_lifetimes_from_generics<'a, 'tcx>( tcx: TyCtxt<'tcx>, generics: &'a hir::Generics<'a>, -) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> { +) -> impl Iterator<Item = &'a hir::GenericParam<'a>> { generics.params.iter().filter(move |param| match param.kind { GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id), _ => false, @@ -1768,7 +1768,7 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId { .. }), .. - } = tcx.hir().body(body).value + } = tcx.hir_body(body).value else { bug!() }; diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 4a508fc0cf6..63c445fa6a3 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -11,6 +11,15 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { } for id in tcx.hir_crate_items(()).opaques() { + if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } + | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = + tcx.hir().expect_opaque_ty(id).origin + && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) + && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + { + continue; + } + let ty = tcx.type_of(id).instantiate_identity(); let span = tcx.def_span(id); tcx.dcx().emit_err(crate::errors::TypeOf { span, ty }); @@ -43,7 +52,7 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { } pub(crate) fn def_parents(tcx: TyCtxt<'_>) { - for iid in tcx.hir().items() { + for iid in tcx.hir_free_items() { let did = iid.owner_id.def_id; if tcx.has_attr(did, sym::rustc_dump_def_parents) { struct AnonConstFinder<'tcx> { @@ -54,8 +63,8 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> { type NestedFilter = nested_filter::All; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) { @@ -68,7 +77,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible // to see what its def parent is. let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] }; - intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid)); + intravisit::walk_item(&mut anon_ct_finder, tcx.hir_item(iid)); for did in [did].into_iter().chain(anon_ct_finder.anon_consts) { let span = tcx.def_span(did); @@ -90,14 +99,14 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { let def_id = id.owner_id.def_id; let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else { continue; }; - let vtable_entries = match tcx.hir().item(id).kind { + let vtable_entries = match tcx.hir_item(id).kind { hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => { let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity(); if trait_ref.has_non_region_param() { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c0902398a54..2cdd9a3a934 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -71,7 +71,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { | Node::Variant(_) | Node::Ctor(..) | Node::Field(_) => { - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir_get_parent_item(hir_id); Some(parent_id.to_def_id()) } // FIXME(#43408) always enable this once `lazy_normalization` is @@ -90,12 +90,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let parent_did = if let DefKind::AnonConst = tcx.def_kind(parent_did) { parent_did } else { - tcx.hir().get_parent_item(hir_id).to_def_id() + tcx.hir_get_parent_item(hir_id).to_def_id() }; debug!(?parent_did); let mut in_param_ty = false; - for (_parent, node) in tcx.hir().parent_iter(hir_id) { + for (_parent, node) in tcx.hir_parent_iter(hir_id) { if let Some(generics) = node.generics() { let mut visitor = AnonConstInParamTyDetector { in_param_ty: false, ct: hir_id }; @@ -189,8 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Exclude `GlobalAsm` here which cannot have generics. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) if asm.operands.iter().any(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => { + hir::InlineAsmOperand::Const { anon_const } => { anon_const.hir_id == hir_id } _ => false, diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index e37a11b6844..1c1a246cc15 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -13,7 +13,6 @@ use tracing::{debug, instrument}; use super::ItemCtxt; use super::predicates_of::assert_only_contains_predicates_from; -use crate::bounds::Bounds; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; /// For associated types we include both bounds written on the type @@ -30,53 +29,55 @@ fn associated_type_bounds<'tcx>( span: Span, filter: PredicateFilter, ) -> &'tcx [(ty::Clause<'tcx>, Span)] { - let item_ty = Ty::new_projection_from_args( - tcx, - assoc_item_def_id.to_def_id(), - GenericArgs::identity_for_item(tcx, assoc_item_def_id), - ); - - let icx = ItemCtxt::new(tcx, assoc_item_def_id); - let mut bounds = Bounds::default(); - icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); - // Associated types are implicitly sized unless a `?Sized` bound is found - match filter { - PredicateFilter::All - | PredicateFilter::SelfOnly - | PredicateFilter::SelfTraitThatDefines(_) - | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + ty::print::with_reduced_queries!({ + let item_ty = Ty::new_projection_from_args( + tcx, + assoc_item_def_id.to_def_id(), + GenericArgs::identity_for_item(tcx, assoc_item_def_id), + ); + + let icx = ItemCtxt::new(tcx, assoc_item_def_id); + let mut bounds = Vec::new(); + icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); + // Associated types are implicitly sized unless a `?Sized` bound is found + match filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(_) + | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + } + // `ConstIfConst` is only interested in `~const` bounds. + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} } - // `ConstIfConst` is only interested in `~const` bounds. - PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} - } - let trait_def_id = tcx.local_parent(assoc_item_def_id); - let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); - - let item_trait_ref = ty::TraitRef::identity(tcx, tcx.parent(assoc_item_def_id.to_def_id())); - let bounds_from_parent = - trait_predicates.predicates.iter().copied().filter_map(|(clause, span)| { - remap_gat_vars_and_recurse_into_nested_projections( - tcx, - filter, - item_trait_ref, - assoc_item_def_id, - span, - clause, - ) - }); - - let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); - debug!( - "associated_type_bounds({}) = {:?}", - tcx.def_path_str(assoc_item_def_id.to_def_id()), - all_bounds - ); + let trait_def_id = tcx.local_parent(assoc_item_def_id); + let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); + + let item_trait_ref = ty::TraitRef::identity(tcx, tcx.parent(assoc_item_def_id.to_def_id())); + let bounds_from_parent = + trait_predicates.predicates.iter().copied().filter_map(|(clause, span)| { + remap_gat_vars_and_recurse_into_nested_projections( + tcx, + filter, + item_trait_ref, + assoc_item_def_id, + span, + clause, + ) + }); + + let all_bounds = tcx.arena.alloc_from_iter(bounds.into_iter().chain(bounds_from_parent)); + debug!( + "associated_type_bounds({}) = {:?}", + tcx.def_path_str(assoc_item_def_id.to_def_id()), + all_bounds + ); - assert_only_contains_predicates_from(filter, all_bounds, item_ty); + assert_only_contains_predicates_from(filter, all_bounds, item_ty); - all_bounds + all_bounds + }) } /// The code below is quite involved, so let me explain. @@ -242,10 +243,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> { // Allocate a new var idx, and insert a new bound ty. let var = ty::BoundVar::from_usize(self.still_bound_vars.len()); self.still_bound_vars.push(ty::BoundVariableKind::Ty(old_bound.kind)); - let mapped = Ty::new_bound(self.tcx, ty::INNERMOST, ty::BoundTy { - var, - kind: old_bound.kind, - }); + let mapped = Ty::new_bound( + self.tcx, + ty::INNERMOST, + ty::BoundTy { var, kind: old_bound.kind }, + ); self.mapping.insert(old_bound.var, mapped.into()); mapped }; @@ -265,10 +267,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> { } else { let var = ty::BoundVar::from_usize(self.still_bound_vars.len()); self.still_bound_vars.push(ty::BoundVariableKind::Region(old_bound.kind)); - let mapped = ty::Region::new_bound(self.tcx, ty::INNERMOST, ty::BoundRegion { - var, - kind: old_bound.kind, - }); + let mapped = ty::Region::new_bound( + self.tcx, + ty::INNERMOST, + ty::BoundRegion { var, kind: old_bound.kind }, + ); self.mapping.insert(old_bound.var, mapped.into()); mapped }; @@ -323,7 +326,7 @@ fn opaque_type_bounds<'tcx>( ) -> &'tcx [(ty::Clause<'tcx>, Span)] { ty::print::with_reduced_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); // Opaque types are implicitly sized unless a `?Sized` bound is found match filter { @@ -339,7 +342,7 @@ fn opaque_type_bounds<'tcx>( } debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.clauses()) + tcx.arena.alloc_slice(&bounds) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8a975786a92..5b511d27074 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -13,7 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span}; use tracing::{debug, instrument, trace}; use super::item_bounds::explicit_item_bounds_with_filter; -use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; use crate::delegation::inherit_predicates_for_delegation_item; @@ -178,7 +177,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // on a trait we must also consider the bounds that follow the trait's name, // like `trait Foo: A + B + C`. if let Some(self_bounds) = is_trait { - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds( tcx.types.self_param, self_bounds, @@ -186,7 +185,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ty::List::empty(), PredicateFilter::All, ); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); } // In default impls, we can assume that the self type implements @@ -209,7 +208,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen GenericParamKind::Lifetime { .. } => (), GenericParamKind::Type { .. } => { let param_ty = icx.lowerer().lower_ty_param(param.hir_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); // Params are implicitly sized unless a `?Sized` bound is found icx.lowerer().add_sized_bound( &mut bounds, @@ -219,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen param.span, ); trace!(?bounds); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); trace!(?predicates); } hir::GenericParamKind::Const { .. } => { @@ -264,7 +263,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds( ty, bound_pred.bounds, @@ -272,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen bound_vars, PredicateFilter::All, ); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); } hir::WherePredicateKind::RegionPredicate(region_pred) => { @@ -350,10 +349,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>( for param in opaque_own_params { let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()); if let ty::ReEarlyParam(..) = *orig_lifetime { - let dup_lifetime = ty::Region::new_early_param(tcx, ty::EarlyParamRegion { - index: param.index, - name: param.name, - }); + let dup_lifetime = ty::Region::new_early_param( + tcx, + ty::EarlyParamRegion { index: param.index, name: param.name }, + ); let span = tcx.def_span(param.def_id); predicates.push(( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime)) @@ -383,8 +382,7 @@ fn const_evaluatable_predicates_of<'tcx>( fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def); let (_, parent_node) = tcx - .hir() - .parent_iter(hir_id) + .hir_parent_iter(hir_id) .skip_while(|(_, n)| matches!(n, Node::ConstArg(..))) .next() .unwrap(); @@ -436,7 +434,7 @@ fn const_evaluatable_predicates_of<'tcx>( self_ty.instantiate_identity().visit_with(&mut collector); } - if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) { + if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) { debug!("visit fn sig"); let fn_sig = tcx.fn_sig(def_id); let fn_sig = fn_sig.instantiate_identity(); @@ -627,7 +625,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); let self_param_ty = tcx.types.self_param; - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); let where_bounds_that_match = @@ -635,7 +633,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( // Combine the two lists to form the complete set of superbounds: let implied_bounds = - &*tcx.arena.alloc_from_iter(bounds.clauses().chain(where_bounds_that_match)); + &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match)); debug!(?implied_bounds); // Now require that immediate supertraits are lowered, which will, in @@ -826,7 +824,7 @@ pub(super) fn type_param_predicates<'tcx>( // `where T: Foo`. let param_id = tcx.local_def_id_to_hir_id(def_id); - let param_owner = tcx.hir().ty_param_owner(def_id); + let param_owner = tcx.hir_ty_param_owner(def_id); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner { @@ -904,7 +902,7 @@ impl<'tcx> ItemCtxt<'tcx> { param_def_id: LocalDefId, filter: PredicateFilter, ) -> Vec<(ty::Clause<'tcx>, Span)> { - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); for predicate in hir_generics.predicates { let hir_id = predicate.hir_id; @@ -938,7 +936,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - bounds.clauses().collect() + bounds } } @@ -1007,7 +1005,7 @@ pub(super) fn const_conditions<'tcx>( }; let icx = ItemCtxt::new(tcx, def_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); for pred in generics.predicates { match pred.kind { @@ -1027,12 +1025,12 @@ pub(super) fn const_conditions<'tcx>( } if let Some((def_id, supertraits)) = trait_def_id_and_supertraits { - bounds.push_const_bound( - tcx, - ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())), - ty::BoundConstness::Maybe, + // We've checked above that the trait is conditionally const. + bounds.push(( + ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())) + .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), DUMMY_SP, - ); + )); icx.lowerer().lower_bounds( tcx.types.self_param, @@ -1045,7 +1043,7 @@ pub(super) fn const_conditions<'tcx>( ty::ConstConditions { parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()), - predicates: tcx.arena.alloc_from_iter(bounds.clauses().map(|(clause, span)| { + predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| { ( clause.kind().map_bound(|clause| match clause { ty::ClauseKind::HostEffect(ty::HostEffectPredicate { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 76006354717..6b61d317d3f 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -160,7 +160,7 @@ enum Scope<'a> { impl<'a> Scope<'a> { // A helper for debugging scopes without printing parent scopes - fn debug_truncated(&'a self) -> impl fmt::Debug + 'a { + fn debug_truncated(&self) -> impl fmt::Debug { fmt::from_fn(move |f| match self { Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f .debug_struct("Binder") @@ -305,21 +305,15 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria } /// Whether this opaque always captures lifetimes in scope. -/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024` -/// is enabled. We don't check the span of the edition, since this is done -/// on a per-opaque basis to account for nested opaques. -fn opaque_captures_all_in_scope_lifetimes<'tcx>( - tcx: TyCtxt<'tcx>, - opaque: &'tcx hir::OpaqueTy<'tcx>, -) -> bool { +/// Right now, this is all RPITIT and TAITs, and when the opaque +/// is coming from a span corresponding to edition 2024. +fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool { match opaque.origin { // if the opaque has the `use<...>` syntax, the user is telling us that they only want // to account for those lifetimes, so do not try to be clever. _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false, hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true, - _ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => { - true - } + _ if opaque.span.at_least_rust_2024() => true, hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(), } } @@ -422,12 +416,12 @@ enum NonLifetimeBinderAllowed { impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_nested_body(&mut self, body: hir::BodyId) { - let body = self.tcx.hir().body(body); + let body = self.tcx.hir_body(body); self.with(Scope::Body { id: body.id(), s: self.scope }, |this| { this.visit_body(body); }); @@ -519,8 +513,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) { let captures = RefCell::new(FxIndexMap::default()); - let capture_all_in_scope_lifetimes = - opaque_captures_all_in_scope_lifetimes(self.tcx, opaque); + let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque); if capture_all_in_scope_lifetimes { let lifetime_ident = |def_id: LocalDefId| { let name = self.tcx.item_name(def_id.to_def_id()); @@ -630,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Static(..) - | hir::ItemKind::GlobalAsm(..) => { + | hir::ItemKind::GlobalAsm { .. } => { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } @@ -1049,7 +1042,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL match param.source { hir::GenericParamSource::Generics => { let parent_def_id = tcx.local_parent(param_def_id); - let generics = tcx.hir().get_generics(parent_def_id).unwrap(); + let generics = tcx.hir_get_generics(parent_def_id).unwrap(); let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id); let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap(); @@ -1143,20 +1136,23 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .params .iter() .map(|param| { - (param.def_id, match param.kind { - GenericParamKind::Lifetime { .. } => { - if self.tcx.is_late_bound(param.hir_id) { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - ResolvedArg::late(late_bound_idx, param) - } else { + ( + param.def_id, + match param.kind { + GenericParamKind::Lifetime { .. } => { + if self.tcx.is_late_bound(param.hir_id) { + let late_bound_idx = named_late_bound_vars; + named_late_bound_vars += 1; + ResolvedArg::late(late_bound_idx, param) + } else { + ResolvedArg::early(param) + } + } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { ResolvedArg::early(param) } - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - ResolvedArg::early(param) - } - }) + }, + ) }) .collect(); @@ -1247,7 +1243,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin && let hir::LifetimeName::Param(param_id) = lifetime_ref.res && let Some(generics) = - self.tcx.hir().get_generics(self.tcx.local_parent(param_id)) + self.tcx.hir_get_generics(self.tcx.local_parent(param_id)) && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) && param.is_elided_lifetime() && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async() @@ -1261,7 +1257,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { ); if let Some(generics) = - self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) + self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id) { let new_param_sugg = if let Some(span) = generics.span_for_lifetime_suggestion() { @@ -1337,7 +1333,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; def = ResolvedArg::Error(guar); } else if let Some(body_id) = outermost_body { - let fn_id = self.tcx.hir().body_owner(body_id); + let fn_id = self.tcx.hir_body_owner(body_id); match self.tcx.hir_node(fn_id) { Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. }) | Node::TraitItem(hir::TraitItem { @@ -2163,10 +2159,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Walk the generics of the item for a trait bound whose self type /// corresponds to the expected res, and return the trait def id. - fn for_each_trait_bound_on_res( - &self, - expected_res: Res, - ) -> impl Iterator<Item = DefId> + use<'tcx, '_> { + fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> { std::iter::from_coroutine( #[coroutine] move || { @@ -2262,8 +2255,8 @@ fn is_late_bound_map( tcx: TyCtxt<'_>, owner_id: hir::OwnerId, ) -> Option<&FxIndexSet<hir::ItemLocalId>> { - let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?; - let generics = tcx.hir().get_generics(owner_id.def_id)?; + let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?; + let generics = tcx.hir_get_generics(owner_id.def_id)?; let mut late_bound = FxIndexSet::default(); @@ -2273,7 +2266,7 @@ fn is_late_bound_map( } let mut appears_in_output = - AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() }; + AllCollector { has_fully_capturing_opaque: false, regions: Default::default() }; intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output); if appears_in_output.has_fully_capturing_opaque { appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id)); @@ -2286,7 +2279,7 @@ fn is_late_bound_map( // Subtle point: because we disallow nested bindings, we can just // ignore binders here and scrape up all names we see. let mut appears_in_where_clause = - AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() }; + AllCollector { has_fully_capturing_opaque: true, regions: Default::default() }; appears_in_where_clause.visit_generics(generics); debug!(?appears_in_where_clause.regions); @@ -2452,23 +2445,21 @@ fn is_late_bound_map( } } - struct AllCollector<'tcx> { - tcx: TyCtxt<'tcx>, + struct AllCollector { has_fully_capturing_opaque: bool, regions: FxHashSet<LocalDefId>, } - impl<'v> Visitor<'v> for AllCollector<'v> { - fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { + impl<'tcx> Visitor<'tcx> for AllCollector { + fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if let hir::LifetimeName::Param(def_id) = lifetime_ref.res { self.regions.insert(def_id); } } - fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) { + fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) { if !self.has_fully_capturing_opaque { - self.has_fully_capturing_opaque = - opaque_captures_all_in_scope_lifetimes(self.tcx, opaque); + self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque); } intravisit::walk_opaque_ty(self, opaque); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 4e12db190fd..d564dc9699a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node = tcx.hir_node(parent_node_id); - let find_sym_fn = |&(op, op_sp)| match op { - hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => { - Some((anon_const, op_sp)) - } - _ => None, - }; - let find_const = |&(op, op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => { Some((anon_const, op_sp)) @@ -59,31 +52,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) - if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => - { - let ty = tcx.typeck(def_id).node_type(hir_id); - - match ty.kind() { - ty::Error(_) => ty, - ty::FnDef(..) => ty, - _ => { - let guar = tcx - .dcx() - .struct_span_err(op_sp, "invalid `sym` operand") - .with_span_label( - tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ) - .with_help("`sym` operands must refer to either a function or a static") - .emit(); - - Ty::new_error(tcx, guar) - } - } - } - Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -106,8 +75,8 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx } } } - Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { - tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) + Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => { + tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) } // Sort of affects the type system, but only for the purpose of diagnostics // so no need for ConstArg. @@ -257,7 +226,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } } ImplItemKind::Type(ty) => { - if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() { + if tcx.impl_trait_ref(tcx.hir_get_parent_item(hir_id)).is_none() { check_feature_inherent_assoc_ty(tcx, item.span); } @@ -313,12 +282,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_adt(tcx, def, args) } + ItemKind::GlobalAsm { .. } => tcx.typeck(def_id).node_type(hir_id), ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm(..) | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind); @@ -341,7 +310,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def { VariantData::Unit(..) | VariantData::Struct { .. } => { - tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity() + tcx.type_of(tcx.hir_get_parent_item(hir_id)).instantiate_identity() } VariantData::Tuple(_, _, ctor) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id); @@ -451,7 +420,7 @@ fn infer_placeholder_type<'tcx>( ); } else { with_forced_trimmed_paths!(err.span_note( - tcx.hir().body(body_id).value.span, + tcx.hir_body(body_id).value.span, format!("however, the inferred type `{ty}` cannot be named"), )); } @@ -494,7 +463,7 @@ fn infer_placeholder_type<'tcx>( ); } else { with_forced_trimmed_paths!(diag.span_note( - tcx.hir().body(body_id).value.span, + tcx.hir_body(body_id).value.span, format!("however, the inferred type `{ty}` cannot be named"), )); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index e2b9fe0f9f7..399c4fbe55a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -83,13 +83,13 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( #[instrument(skip(tcx), level = "debug")] pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { let hir_id = tcx.local_def_id_to_hir_id(def_id); - let scope = tcx.hir().get_defining_scope(hir_id); + let scope = tcx.hir_get_defining_scope(hir_id); let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; debug!(?scope); if scope == hir::CRATE_HIR_ID { - tcx.hir().walk_toplevel_module(&mut locator); + tcx.hir_walk_toplevel_module(&mut locator); } else { trace!("scope={:#?}", tcx.hir_node(scope)); match tcx.hir_node(scope) { @@ -298,8 +298,8 @@ impl TaitConstraintLocator<'_> { impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { type NestedFilter = nested_filter::All; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(closure) = ex.kind { @@ -441,8 +441,8 @@ impl RpitConstraintChecker<'_> { impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(closure) = ex.kind { diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index ed45833b614..4dbdfa3d85a 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -41,10 +41,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> { if let ty::ReEarlyParam(param) = r.kind() && let Some(index) = self.remap_table.get(¶m.index).copied() { - return ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion { - index, - name: param.name, - }); + return ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { index, name: param.name }, + ); } r } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9769be30226..1a0b0edb257 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1,8 +1,10 @@ //! Errors emitted by `rustc_hir_analysis`. +use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, + Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, + MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -646,10 +648,11 @@ pub(crate) struct MainFunctionGenericParameters { #[derive(Diagnostic)] #[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] -pub(crate) struct VariadicFunctionCompatibleConvention { +pub(crate) struct VariadicFunctionCompatibleConvention<'a> { #[primary_span] #[label] pub span: Span, + pub conventions: &'a str, } #[derive(Diagnostic)] @@ -1181,6 +1184,42 @@ pub(crate) struct DispatchFromDynRepr { } #[derive(Diagnostic)] +#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)] +pub(crate) struct CoercePointeeNotStruct { + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)] +pub(crate) struct CoercePointeeNotConcreteType { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)] +pub(crate) struct CoercePointeeNoUserValidityAssertion { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)] +pub(crate) struct CoercePointeeNotTransparent { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)] +pub(crate) struct CoercePointeeNoField { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[help] pub(crate) struct InherentTyOutsideRelevant { @@ -1378,6 +1417,15 @@ pub(crate) struct CrossCrateTraitsDefined { pub traits: String, } +#[derive(Diagnostic)] +#[diag(hir_analysis_no_variant_named, code = E0599)] +pub struct NoVariantNamed<'tcx> { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub ty: Ty<'tcx>, +} + // FIXME(fmease): Deduplicate: #[derive(Diagnostic)] @@ -1653,7 +1701,7 @@ pub(crate) struct CmseInputsStackSpill { #[label] pub span: Span, pub plural: bool, - pub abi_name: &'static str, + pub abi: ExternAbi, } #[derive(Diagnostic)] @@ -1664,7 +1712,7 @@ pub(crate) struct CmseOutputStackSpill { #[primary_span] #[label] pub span: Span, - pub abi_name: &'static str, + pub abi: ExternAbi, } #[derive(Diagnostic)] @@ -1695,3 +1743,28 @@ pub(crate) struct RegisterTypeUnstable<'a> { pub span: Span, pub ty: Ty<'a>, } + +#[derive(LintDiagnostic)] +#[diag(hir_analysis_supertrait_item_shadowing)] +pub(crate) struct SupertraitItemShadowing { + pub item: Symbol, + pub subtrait: Symbol, + #[subdiagnostic] + pub shadowee: SupertraitItemShadowee, +} + +#[derive(Subdiagnostic)] +pub(crate) enum SupertraitItemShadowee { + #[note(hir_analysis_supertrait_item_shadowee)] + Labeled { + #[primary_span] + span: Span, + supertrait: Symbol, + }, + #[note(hir_analysis_supertrait_item_multiple_shadowee)] + Several { + #[primary_span] + spans: MultiSpan, + traits: DiagSymbolList, + }, +} diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index b2501d647a5..610b293a114 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -134,9 +134,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { // is from the 'of_trait' field of the enclosing impl let parent = self.tcx.parent_hir_node(self.path_segment.hir_id); - let parent_item = self.tcx.hir_node_by_def_id( - self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id, - ); + let parent_item = self + .tcx + .hir_node_by_def_id(self.tcx.hir_get_parent_item(self.path_segment.hir_id).def_id); // Get the HIR id of the trait ref let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else { @@ -343,7 +343,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let mut ret = Vec::new(); let mut ty_id = None; - for (id, node) in self.tcx.hir().parent_iter(path_hir_id) { + for (id, node) in self.tcx.hir_parent_iter(path_hir_id) { debug!(?id); if let hir::Node::Ty(_) = node { ty_id = Some(id); @@ -437,8 +437,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ) -> String { let is_in_a_method_call = self .tcx - .hir() - .parent_iter(self.path_segment.hir_id) + .hir_parent_iter(self.path_segment.hir_id) .skip(1) .find_map(|(_, node)| match node { hir::Node::Expr(expr) => Some(expr), @@ -451,7 +450,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ) }); - let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig); + let fn_sig = self.tcx.hir_get_if_local(self.def_id).and_then(hir::Node::fn_sig); let is_used_in_input = |def_id| { fn_sig.is_some_and(|fn_sig| { fn_sig.decl.inputs.iter().any(|ty| match ty.kind { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index e949d4a1126..dd346ed1f97 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -8,7 +8,7 @@ use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; -use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt}; +use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast}; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; @@ -16,7 +16,6 @@ use smallvec::SmallVec; use tracing::{debug, instrument}; use super::errors::GenericsArgsErrExtend; -use crate::bounds::Bounds; use crate::errors; use crate::hir_ty_lowering::{ AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason, @@ -28,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. pub(crate) fn add_sized_bound( &self, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, @@ -102,8 +101,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { seen_sized_unbound = true; continue; } - // There was a `?Trait` bound, but it was not `?Sized`; warn. - self.dcx().span_warn( + // There was a `?Trait` bound, but it was not `?Sized` + self.dcx().span_err( unbound.span, "relaxing a default bound only does something for `?Sized`; \ all other traits are not bound by default", @@ -113,10 +112,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; // we don't need to do anything. - } else if sized_def_id.is_some() { + } else if let Some(sized_def_id) = sized_def_id { // There was no `?Sized`, `!Sized` or explicit `Sized` bound; // add `Sized` if it's available. - bounds.push_sized(tcx, self_ty, span); + let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); + // Preferable to put this obligation first, since we report better errors for sized ambiguity. + bounds.insert(0, (trait_ref.upcast(tcx), span)); } } @@ -146,7 +147,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, param_ty: Ty<'tcx>, hir_bounds: I, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, bound_vars: &'tcx ty::List<ty::BoundVariableKind>, predicate_filter: PredicateFilter, ) where @@ -189,14 +190,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound); - bounds.push_region_bound( - self.tcx(), - ty::Binder::bind_with_vars( - ty::OutlivesPredicate(param_ty, region), - bound_vars, - ), - lifetime.ident.span, + let bound = ty::Binder::bind_with_vars( + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)), + bound_vars, ); + bounds.push((bound.upcast(self.tcx()), lifetime.ident.span)); } hir::GenericBound::Use(..) => { // We don't actually lower `use` into the type layer. @@ -219,7 +217,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, constraint: &hir::AssocItemConstraint<'tcx>, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, duplicates: &mut FxIndexMap<DefId, Span>, path_span: Span, predicate_filter: PredicateFilter, @@ -389,14 +387,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfAndAssociatedTypeBounds => { - bounds.push_projection_bound( - tcx, - projection_term.map_bound(|projection_term| ty::ProjectionPredicate { + let bound = projection_term.map_bound(|projection_term| { + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_term, term, - }), - constraint.span, - ); + }) + }); + bounds.push((bound.upcast(tcx), constraint.span)); } // SelfTraitThatDefines is only interested in trait predicates. PredicateFilter::SelfTraitThatDefines(_) => {} @@ -640,13 +637,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut num_bound_vars = candidate.bound_vars().len(); let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| { let arg = match param.kind { - ty::GenericParamDefKind::Lifetime => { - ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { + ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_usize(num_bound_vars), kind: ty::BoundRegionKind::Named(param.def_id, param.name), - }) - .into() - } + }, + ) + .into(), ty::GenericParamDefKind::Type { .. } => { let guar = *emitted_bad_param_err.get_or_insert_with(|| { self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type { @@ -737,8 +736,7 @@ fn check_assoc_const_binding_type<'tcx>( .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty }); let enclosing_item_owner_id = tcx - .hir() - .parent_owner_iter(hir_id) + .hir_parent_owner_iter(hir_id) .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id)) .unwrap(); let generics = tcx.generics_of(enclosing_item_owner_id); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 4c8f2735b97..5fed2e35287 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -17,8 +17,6 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: ExternAbi, fn_sig: ty::PolyFnSig<'tcx>, ) { - let abi_name = abi.name(); - match abi { ExternAbi::CCmseNonSecureCall => { let hir_node = tcx.hir_node(hir_id); @@ -56,7 +54,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( .to(bare_fn_ty.decl.inputs[index].span) .to(bare_fn_ty.decl.inputs.last().unwrap().span); let plural = bare_fn_ty.param_names.len() - index != 1; - dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { @@ -69,7 +67,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(true) => {} Ok(false) => { let span = bare_fn_ty.decl.output.span(); - dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { @@ -92,7 +90,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( // ^^^^^^ let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span); let plural = decl.inputs.len() - index != 1; - dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { @@ -105,7 +103,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(true) => {} Ok(false) => { let span = decl.output.span(); - dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index e59ff02642c..3eb4945ebf8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; @@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; use super::HirTyLowerer; -use crate::bounds::Bounds; use crate::hir_ty_lowering::{ GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason, }; @@ -36,7 +35,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let dummy_self = tcx.types.trait_object_dummy_self; - let mut user_written_bounds = Bounds::default(); + let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); for trait_bound in hir_bounds.iter() { if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { @@ -59,16 +58,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let (trait_bounds, mut projection_bounds) = - traits::expand_trait_aliases(tcx, user_written_bounds.clauses()); - let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds + let (elaborated_trait_bounds, elaborated_projection_bounds) = + traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); + let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds .into_iter() .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); // We don't support empty trait objects. if regular_traits.is_empty() && auto_traits.is_empty() { - let guar = - self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses()); + let guar = self.report_trait_object_with_no_traits_error( + span, + user_written_bounds.iter().copied(), + ); return Ty::new_error(tcx, guar); } // We don't support >1 principal @@ -84,7 +85,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check that there are no gross dyn-compatibility violations; // most importantly, that the supertraits don't contain `Self`, // to avoid ICEs. - for (clause, span) in user_written_bounds.clauses() { + for (clause, span) in user_written_bounds { if let Some(trait_pred) = clause.as_trait_clause() { let violations = hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id()); @@ -102,30 +103,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // Map the projection bounds onto a key that makes it easy to remove redundant + // bounds that are constrained by supertraits of the principal def id. + // + // Also make sure we detect conflicting bounds from expanding a trait alias and + // also specifying it manually, like: + // ``` + // type Alias = Trait<Assoc = i32>; + // let _: &dyn Alias<Assoc = u32> = /* ... */; + // ``` + let mut projection_bounds = FxIndexMap::default(); + for (proj, proj_span) in elaborated_projection_bounds { + let key = ( + proj.skip_binder().projection_term.def_id, + tcx.anonymize_bound_vars( + proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)), + ), + ); + if let Some((old_proj, old_proj_span)) = + projection_bounds.insert(key, (proj, proj_span)) + && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj) + { + let item = tcx.item_name(proj.item_def_id()); + self.dcx() + .struct_span_err( + span, + format!( + "conflicting associated type bounds for `{item}` when \ + expanding trait alias" + ), + ) + .with_span_label( + old_proj_span, + format!("`{item}` is specified to be `{}` here", old_proj.term()), + ) + .with_span_label( + proj_span, + format!("`{item}` is specified to be `{}` here", proj.term()), + ) + .emit(); + } + } + let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = FxIndexSet::default(); - if let Some((principal_trait, spans)) = &principal_trait { - let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx); - for ClauseWithSupertraitSpan { pred, supertrait_span } in - traits::elaborate(tcx, [ClauseWithSupertraitSpan::new( - pred, + let mut needed_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { + let principal_trait = principal_trait.map_bound(|trait_pred| { + assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); + trait_pred.trait_ref + }); + + for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate( + tcx, + [ClauseWithSupertraitSpan::new( + ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx), *spans.last().unwrap(), - )]) - .filter_only_self() + )], + ) + .filter_only_self() { - debug!("observing object predicate `{pred:?}`"); + let clause = clause.instantiate_supertrait(tcx, principal_trait); + debug!("observing object predicate `{clause:?}`"); - let bound_predicate = pred.kind(); + let bound_predicate = clause.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ty::ClauseKind::Trait(pred) => { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); needed_associated_types.extend( - tcx.associated_items(trait_ref.def_id()) + tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() + // We only care about associated types. .filter(|item| item.kind == ty::AssocKind::Type) + // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit. .filter(|item| !item.is_impl_trait_in_trait()) // If the associated type has a `where Self: Sized` bound, // we do not need to constrain the associated type. @@ -133,7 +185,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|item| (item.def_id, trait_ref)), ); } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { + ty::ClauseKind::Projection(pred) => { let pred = bound_predicate.rebind(pred); // A `Self` within the original bound will be instantiated with a // `trait_object_dummy_self`, so check for that. @@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See // the discussion in #56288 for alternatives. if !references_self { - // Include projections defined on supertraits. - projection_bounds.push((pred, supertrait_span)); + let key = ( + pred.skip_binder().projection_term.def_id, + tcx.anonymize_bound_vars( + pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)), + ), + ); + if !projection_bounds.contains_key(&key) { + projection_bounds.insert(key, (pred, supertrait_span)); + } } self.check_elaborated_projection_mentions_input_lifetimes( @@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // types that we expect to be provided by the user, so the following loop // removes all the associated types that have a corresponding `Projection` // clause, either from expanding trait aliases or written by the user. - for &(projection_bound, span) in &projection_bounds { + for &(projection_bound, span) in projection_bounds.values() { let def_id = projection_bound.item_def_id(); - let trait_ref = tcx.anonymize_bound_vars( - projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), - ); - needed_associated_types.swap_remove(&(def_id, trait_ref)); if tcx.generics_require_sized_self(def_id) { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, @@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + let mut missing_assoc_types = FxIndexSet::default(); + let projection_bounds: Vec<_> = needed_associated_types + .into_iter() + .filter_map(|key| { + if let Some(assoc) = projection_bounds.get(&key) { + Some(*assoc) + } else { + missing_assoc_types.insert(key); + None + } + }) + .collect(); + if let Err(guar) = self.check_for_required_assoc_tys( principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), - needed_associated_types, + missing_assoc_types, potential_assoc_types, hir_bounds, ) { @@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) }); - let existential_projections = projection_bounds.iter().map(|(bound, _)| { + let existential_projections = projection_bounds.into_iter().map(|(bound, _)| { bound.map_bound(|mut b| { assert_eq!(b.projection_term.self_ty(), dummy_self); @@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) }); - let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| { - assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive); - assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self); + let mut auto_trait_predicates: Vec<_> = auto_traits + .into_iter() + .map(|(trait_pred, _)| { + assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive); + assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self); - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id())) - }); + ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id())) + }) + .collect(); + auto_trait_predicates.dedup(); // N.b. principal, projections, auto traits // FIXME: This is actually wrong with multiple principals in regards to symbol mangling @@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .chain(auto_trait_predicates) .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); - v.dedup(); let existential_predicates = tcx.mk_poly_existential_predicates(&v); // Use explicitly-specified region bound, unless the bound is missing. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 79aa2f4b8cc..d644a1f224c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err, }; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; @@ -223,9 +223,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // inside an opaque type while we're interested in the overarching type alias (TAIT). // FIXME: However, for trait aliases, this incorrectly returns the enclosing module... && let item_def_id = - tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id)) + tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id)) // FIXME: ...which obviously won't have any generics. - && let Some(generics) = tcx.hir().get_generics(item_def_id.def_id) + && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id) { // FIXME: Suggest adding supertrait bounds if we have a `Self` type param. // FIXME(trait_alias): Suggest adding `Self: Trait` to @@ -979,7 +979,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qself: &hir::Ty<'_>, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next() + if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next() && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Path(hir::QPath::TypeRelative( @@ -1027,7 +1027,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone, args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone, - err_extend: GenericsArgsErrExtend<'_>, + err_extend: GenericsArgsErrExtend<'a>, ) -> ErrorGuaranteed { #[derive(PartialEq, Eq, Hash)] enum ProhibitGenericsArg { @@ -1047,23 +1047,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; }); + let segments: Vec<_> = segments.collect(); let types_and_spans: Vec<_> = segments - .clone() + .iter() .flat_map(|segment| { if segment.args().args.is_empty() { None } else { Some(( match segment.res { - hir::def::Res::PrimTy(ty) => { + Res::PrimTy(ty) => { format!("{} `{}`", segment.res.descr(), ty.name()) } - hir::def::Res::Def(_, def_id) + Res::Def(_, def_id) if let Some(name) = self.tcx().opt_item_name(def_id) => { format!("{} `{name}`", segment.res.descr()) } - hir::def::Res::Err => "this type".to_string(), + Res::Err => "this type".to_string(), _ => segment.res.descr().to_string(), }, segment.ident.span, @@ -1074,11 +1075,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let this_type = listify(&types_and_spans, |(t, _)| t.to_string()) .expect("expected one segment to deny"); - let arg_spans: Vec<Span> = segments - .clone() - .flat_map(|segment| segment.args().args) - .map(|arg| arg.span()) - .collect(); + let arg_spans: Vec<Span> = + segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect(); let mut kinds = Vec::with_capacity(4); prohibit_args.iter().for_each(|arg| match arg { @@ -1103,7 +1101,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { for (what, span) in types_and_spans { err.span_label(span, format!("not allowed on {what}")); } - generics_args_err_extend(self.tcx(), segments, &mut err, err_extend); + generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend); err.emit() } @@ -1280,8 +1278,7 @@ pub fn prohibit_assoc_item_constraint( // Get the parent impl block based on the binding we have // and the trait DefId let impl_block = tcx - .hir() - .parent_iter(constraint.hir_id) + .hir_parent_iter(constraint.hir_id) .find_map(|(_, node)| node.impl_block_of_trait(def_id)); let type_with_constraints = @@ -1400,7 +1397,7 @@ pub enum GenericsArgsErrExtend<'tcx> { }, SelfTyParam(Span), Param(DefId), - DefVariant, + DefVariant(&'tcx [hir::PathSegment<'tcx>]), None, } @@ -1408,7 +1405,7 @@ fn generics_args_err_extend<'a>( tcx: TyCtxt<'_>, segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone, err: &mut Diag<'_>, - err_extend: GenericsArgsErrExtend<'_>, + err_extend: GenericsArgsErrExtend<'a>, ) { match err_extend { GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => { @@ -1496,6 +1493,32 @@ fn generics_args_err_extend<'a>( ]; err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect); } + GenericsArgsErrExtend::DefVariant(segments) => { + let args: Vec<Span> = segments + .iter() + .filter_map(|segment| match segment.res { + Res::Def( + DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum, + _, + ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())), + _ => None, + }) + .collect(); + if args.len() > 1 + && let Some(span) = args.into_iter().last() + { + err.note( + "generic arguments are not allowed on both an enum and its variant's path \ + segments simultaneously; they are only valid in one place or the other", + ); + err.span_suggestion_verbose( + span, + "remove the generics arguments from one of the path segments", + String::new(), + Applicability::MaybeIncorrect, + ); + } + } GenericsArgsErrExtend::PrimTy(prim_ty) => { let name = prim_ty.name_str(); for segment in segments { @@ -1512,9 +1535,6 @@ fn generics_args_err_extend<'a>( GenericsArgsErrExtend::OpaqueTy => { err.note("`impl Trait` types can't have type parameters"); } - GenericsArgsErrExtend::DefVariant => { - err.note("enum variants can't have type parameters"); - } GenericsArgsErrExtend::Param(def_id) => { let span = tcx.def_ident_span(def_id).unwrap(); let kind = tcx.def_descr(def_id); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 43137397870..8d58a3bfbd3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( } Res::Def(DefKind::TyParam, src_def_id) => { if let Some(param_local_id) = param.def_id.as_local() { - let param_name = tcx.hir().ty_param_name(param_local_id); + let param_name = tcx.hir_ty_param_name(param_local_id); let param_type = tcx.type_of(param.def_id).instantiate_identity(); if param_type.is_suggestable(tcx, false) { err.span_suggestion( @@ -110,7 +110,7 @@ fn generic_arg_mismatch_err( err.help(format!("`{}` is a function item, not a type", tcx.item_name(id))); err.help("function item types cannot be named directly"); } else if let hir::ConstArgKind::Anon(anon) = cnst.kind - && let body = tcx.hir().body(anon.body) + && let body = tcx.hir_body(anon.body) && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind && let Res::Def(DefKind::Fn { .. }, id) = path.res @@ -542,8 +542,7 @@ pub(crate) fn check_generic_arg_count( // ``` let parent_is_impl_block = cx .tcx() - .hir() - .parent_owner_iter(seg.hir_id) + .hir_parent_owner_iter(seg.hir_id) .next() .is_some_and(|(_, owner_node)| owner_node.is_impl_block()); if parent_is_impl_block { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 44f7a035a10..f5e075367f3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -130,7 +130,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { diag: &mut Diag<'_, G>, ) { let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id; if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }), .. @@ -191,7 +191,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Make sure that we are in the condition to suggest `impl Trait`. fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id; // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>` // and suggest `Trait0<Ty = impl Trait1>`. // Functions are found in three different contexts. @@ -321,7 +321,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { - let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id); + let mut parents = self.tcx().hir_parent_iter(self_ty.hir_id); if let Some((_, hir::Node::AssocItemConstraint(constraint))) = parents.next() && let Some(obj_ty) = constraint.ty() diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 079e8921627..750770178ee 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -49,11 +49,13 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; +use rustc_type_ir::Upcast; use tracing::{debug, instrument}; -use crate::bounds::Bounds; use crate::check::check_abi_fn_ptr; -use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType}; +use crate::errors::{ + AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed, +}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -217,7 +219,7 @@ impl AssocItemQSelf { fn to_string(&self, tcx: TyCtxt<'_>) -> String { match *self { Self::Trait(def_id) => tcx.def_path_str(def_id), - Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(), + Self::TyParam(def_id, _) => tcx.hir_ty_param_name(def_id).to_string(), Self::SelfTyAlias => kw::SelfUpper.to_string(), } } @@ -342,8 +344,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } rbv::ResolvedArg::EarlyBound(def_id) => { - let name = tcx.hir().ty_param_name(def_id); - let item_def_id = tcx.hir().ty_param_owner(def_id); + let name = tcx.hir_ty_param_name(def_id); + let item_def_id = tcx.hir_ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name }) @@ -691,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constness: hir::BoundConstness, polarity: hir::BoundPolarity, self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); @@ -720,6 +722,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bound_vars, ); + debug!(?poly_trait_ref); + let polarity = match polarity { rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive, rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, @@ -741,6 +745,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } }; + // We deal with const conditions later. + match predicate_filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(..) + | PredicateFilter::SelfAndAssociatedTypeBounds => { + let bound = poly_trait_ref.map_bound(|trait_ref| { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) + }); + let bound = (bound.upcast(tcx), span); + // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. + if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) { + bounds.insert(0, bound); + } else { + bounds.push(bound); + } + } + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} + } + if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness && !self.tcx().is_const_trait(trait_def_id) { @@ -765,58 +789,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion_pre, suggestion, }); - } - - match predicate_filter { - // This is only concerned with trait predicates. - PredicateFilter::SelfTraitThatDefines(..) => { - bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); - } - PredicateFilter::All - | PredicateFilter::SelfOnly - | PredicateFilter::SelfAndAssociatedTypeBounds => { - debug!(?poly_trait_ref); - bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); - - match constness { - hir::BoundConstness::Always(span) => { - if polarity == ty::PredicatePolarity::Positive { - bounds.push_const_bound( - tcx, - poly_trait_ref, - ty::BoundConstness::Const, - span, - ); + } else { + match predicate_filter { + // This is only concerned with trait predicates. + PredicateFilter::SelfTraitThatDefines(..) => {} + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfAndAssociatedTypeBounds => { + match constness { + hir::BoundConstness::Always(span) => { + if polarity == ty::PredicatePolarity::Positive { + bounds.push(( + poly_trait_ref + .to_host_effect_clause(tcx, ty::BoundConstness::Const), + span, + )); + } } + hir::BoundConstness::Maybe(_) => { + // We don't emit a const bound here, since that would mean that we + // unconditionally need to prove a `HostEffect` predicate, even when + // the predicates are being instantiated in a non-const context. This + // is instead handled in the `const_conditions` query. + } + hir::BoundConstness::Never => {} } - hir::BoundConstness::Maybe(_) => { - // We don't emit a const bound here, since that would mean that we - // unconditionally need to prove a `HostEffect` predicate, even when - // the predicates are being instantiated in a non-const context. This - // is instead handled in the `const_conditions` query. - } - hir::BoundConstness::Never => {} } - } - // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert - // `~const` bounds. All other predicates are handled in their respective queries. - // - // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering - // here because we only call this on self bounds, and deal with the recursive case - // in `lower_assoc_item_constraint`. - PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness { - hir::BoundConstness::Maybe(span) => { - if polarity == ty::PredicatePolarity::Positive { - bounds.push_const_bound( - tcx, - poly_trait_ref, - ty::BoundConstness::Maybe, - span, - ); + // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert + // `~const` bounds. All other predicates are handled in their respective queries. + // + // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering + // here because we only call this on self bounds, and deal with the recursive case + // in `lower_assoc_item_constraint`. + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => { + match constness { + hir::BoundConstness::Maybe(span) => { + if polarity == ty::PredicatePolarity::Positive { + bounds.push(( + poly_trait_ref + .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), + span, + )); + } + } + hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {} } } - hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {} - }, + } } let mut dup_constraints = FxIndexMap::default(); @@ -1188,14 +1207,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let msg = format!("expected type, found variant `{assoc_ident}`"); self.dcx().span_err(span, msg) } else if qself_ty.is_enum() { - let mut err = struct_span_code_err!( - self.dcx(), - assoc_ident.span, - E0599, - "no variant named `{}` found for enum `{}`", - assoc_ident, - qself_ty, - ); + let mut err = self.dcx().create_err(NoVariantNamed { + span: assoc_ident.span, + ident: assoc_ident, + ty: qself_ty, + }); let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(variant_name) = find_best_match_for_name( @@ -1210,11 +1226,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { adt_def.variants().iter().find(|s| s.name == variant_name) { let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())]; - if let hir::Node::Stmt(hir::Stmt { - kind: hir::StmtKind::Semi(ref expr), - .. + if let hir::Node::Stmt(&hir::Stmt { + kind: hir::StmtKind::Semi(expr), .. }) - | hir::Node::Expr(ref expr) = tcx.parent_hir_node(hir_ref_id) + | hir::Node::Expr(expr) = tcx.parent_hir_node(hir_ref_id) && let hir::ExprKind::Struct(..) = expr.kind { match variant.ctor { @@ -1657,8 +1672,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(item_def_id = ?def_id); // FIXME: document why/how this is different from `tcx.local_parent(def_id)` - let parent_def_id = - tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id(); + let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id(); debug!(?parent_def_id); // If the trait in segment is the same as the trait defining the item, @@ -1694,7 +1708,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn prohibit_generic_args<'a>( &self, segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone, - err_extend: GenericsArgsErrExtend<'_>, + err_extend: GenericsArgsErrExtend<'a>, ) -> Result<(), ErrorGuaranteed> { let args_visitors = segments.clone().flat_map(|segment| segment.args().args); let mut result = Ok(()); @@ -1911,7 +1925,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { path.segments.iter().enumerate().filter_map(|(index, seg)| { if !indices.contains(&index) { Some(seg) } else { None } }), - GenericsArgsErrExtend::DefVariant, + GenericsArgsErrExtend::DefVariant(&path.segments), ); let GenericPathSegment(def_id, index) = generic_segments.last().unwrap(); @@ -1976,7 +1990,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(hir::Node::Item(&hir::Item { kind: hir::ItemKind::Impl(impl_), .. - })) = tcx.hir().get_if_local(def_id) + })) = tcx.hir_get_if_local(def_id) { err.span_note(impl_.self_ty.span, "not a concrete type"); } @@ -2053,10 +2067,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let item_def_id = tcx.hir().ty_param_owner(def_id); + let item_def_id = tcx.hir_ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) + Ty::new_param(tcx, index, tcx.hir_ty_param_name(def_id)) } Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), @@ -2154,11 +2168,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") } // FIXME(const_generics): create real const to allow fn items as const paths - Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message( - tcx, - span, - "fn items cannot be used as const args", - ), + Res::Def(DefKind::Fn | DefKind::AssocFn, did) => { + self.dcx().span_delayed_bug(span, "function items cannot be used as const args"); + let args = self.lower_generic_args_of_path_segment( + span, + did, + path.segments.last().unwrap(), + ); + ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args)) + } // Exhaustive match to be clear about what exactly we're considering to be // an invalid Res for a const path. @@ -2209,7 +2227,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> { let tcx = self.tcx(); - let expr = &tcx.hir().body(anon.body).value; + let expr = &tcx.hir_body(anon.body).value; debug!(?expr); let ty = tcx @@ -2219,10 +2237,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match self.try_lower_anon_const_lit(ty, expr) { Some(v) => v, - None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { - def: anon.def_id.to_def_id(), - args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), - }), + None => ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst { + def: anon.def_id.to_def_id(), + args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), + }, + ), } } @@ -2375,7 +2396,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Impl trait in bindings lower as an infer var with additional // set of type bounds. let self_ty = self.ty_infer(None, hir_ty.span); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); self.lower_bounds( self_ty, hir_bounds.iter(), @@ -2383,11 +2404,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::List::empty(), PredicateFilter::All, ); - self.register_trait_ascription_bounds( - bounds.clauses().collect(), - hir_ty.hir_id, - hir_ty.span, - ); + self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); self_ty } // If we encounter a type relative path with RTN generics, then it must have @@ -2554,27 +2571,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // reject function types that violate cmse ABI requirements cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); - // Find any late-bound regions declared in return type that do - // not appear in the arguments. These are not well-formed. - // - // Example: - // for<'a> fn() -> &'a str <-- 'a is bad - // for<'a> fn(&'a String) -> &'a str <-- 'a is ok - let inputs = bare_fn_ty.inputs(); - let late_bound_in_args = - tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned())); - let output = bare_fn_ty.output(); - let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output); - - self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| { - struct_span_code_err!( - self.dcx(), - decl.output.span(), - E0581, - "return type references {}, which is not constrained by the fn input types", - br_name - ) - }); + if !bare_fn_ty.references_error() { + // Find any late-bound regions declared in return type that do + // not appear in the arguments. These are not well-formed. + // + // Example: + // for<'a> fn() -> &'a str <-- 'a is bad + // for<'a> fn(&'a String) -> &'a str <-- 'a is ok + let inputs = bare_fn_ty.inputs(); + let late_bound_in_args = + tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned())); + let output = bare_fn_ty.output(); + let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output); + + self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| { + struct_span_code_err!( + self.dcx(), + decl.output.span(), + E0581, + "return type references {}, which is not constrained by the fn input types", + br_name + ) + }); + } bare_fn_ty } diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index f5abcd23440..0b1be8e4f7a 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -22,8 +22,6 @@ fn diagnostic_hir_wf_check<'tcx>( tcx: TyCtxt<'tcx>, (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc), ) -> Option<ObligationCause<'tcx>> { - let hir = tcx.hir(); - let def_id = match loc { WellFormedLoc::Ty(def_id) => def_id, WellFormedLoc::Param { function, param_idx: _ } => function, @@ -187,7 +185,7 @@ fn diagnostic_hir_wf_check<'tcx>( ref node => bug!("Unexpected node {:?}", node), }, WellFormedLoc::Param { function: _, param_idx } => { - let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap(); + let fn_decl = tcx.hir_fn_decl_by_hir_id(hir_id).unwrap(); // Get return type if param_idx as usize == fn_decl.inputs.len() { match fn_decl.output { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 3af4318544e..bdfbd540e40 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -80,7 +80,6 @@ This API is completely unstable and subject to change. pub mod check; pub mod autoderef; -mod bounds; mod check_unused; mod coherence; mod collect; @@ -93,6 +92,7 @@ mod impl_wf_check; mod outlives; mod variance; +pub use errors::NoVariantNamed; use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -100,6 +100,8 @@ use rustc_middle::middle; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; +use rustc_session::parse::feature_err; +use rustc_span::symbol::sym; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -114,9 +116,48 @@ fn require_c_abi_if_c_variadic( abi: ExternAbi, span: Span, ) { - if decl.c_variadic && !abi.supports_varargs() { - tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span }); + const CONVENTIONS_UNSTABLE: &str = + "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; + const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; + const UNSTABLE_EXPLAIN: &str = + "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; + + // ABIs which can stably use varargs + if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { + return; } + + // ABIs with feature-gated stability + let extended_abi_support = tcx.features().extended_varargs_abi_support(); + let extern_system_varargs = tcx.features().extern_system_varargs(); + + // If the feature gate has been enabled, we can stop here + if extern_system_varargs && let ExternAbi::System { .. } = abi { + return; + }; + if extended_abi_support && abi.supports_varargs() { + return; + }; + + // Looks like we need to pick an error to emit. + // Is there any feature which we could have enabled to make this work? + match abi { + ExternAbi::System { .. } => { + feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN) + } + abi if abi.supports_varargs() => { + feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) + } + _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention { + span, + conventions: if tcx.sess.opts.unstable_features.is_nightly_build() { + CONVENTIONS_UNSTABLE + } else { + CONVENTIONS_STABLE + }, + }), + } + .emit(); } pub fn provide(providers: &mut Providers) { @@ -143,7 +184,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // what we are intending to discard, to help future type-based refactoring. type R = Result<(), ErrorGuaranteed>; - tcx.hir().par_for_each_module(|module| { + tcx.par_hir_for_each_module(|module| { let _: R = tcx.ensure_ok().check_mod_type_wf(module); }); @@ -168,7 +209,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // Make sure we evaluate all static and (non-associated) const items, even if unused. // If any of these fail to evaluate, we do not want this crate to pass compilation. - tcx.hir().par_body_owners(|item_def_id| { + tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id), @@ -186,7 +227,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries // cycle errors because it may typeck on anon constants directly. - tcx.hir().par_body_owners(|item_def_id| { + tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); @@ -210,7 +251,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. - let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id); + let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id); collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty) } @@ -221,6 +262,6 @@ pub fn lower_const_arg_for_rustdoc<'tcx>( hir_ct: &hir::ConstArg<'tcx>, feed: FeedConstTy, ) -> Const<'tcx> { - let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id); + let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id); collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed) } diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs index ab50d9e86ef..4233896c372 100644 --- a/compiler/rustc_hir_analysis/src/outlives/dump.rs +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::sym; pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { if !tcx.has_attr(id.owner_id, sym::rustc_outlives) { continue; } diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 036163b9f14..a0faa5e8429 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -28,7 +28,7 @@ pub(super) fn infer_predicates( let mut predicates_added = false; // Visit all the crates and infer predicates - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { let item_did = id.owner_id; debug!("InferVisitor::visit_item(item={:?})", item_did); diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index c43917649de..32b05dcc569 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -37,7 +37,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau // parent of generics returned by `generics_of` // // In the above code we want the anon const to have predicates in its param env for `'b: 'a` - let item_def_id = tcx.hir().get_parent_item(id); + let item_def_id = tcx.hir_get_parent_item(id); // In the above code example we would be calling `inferred_outlives_of(Foo)` here tcx.inferred_outlives_of(item_def_id) } else { |
