diff options
| author | bors <bors@rust-lang.org> | 2025-09-18 16:55:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-09-18 16:55:05 +0000 |
| commit | 0c0c58b8e453f552ebd7f3a1545acdd109de028c (patch) | |
| tree | 80fc20e71f5764072222045136debf7ce9297697 /compiler | |
| parent | 4cd91ef8223ef54111d21aa9e9e71b3b26477dd3 (diff) | |
| parent | 24d6259dce2040994897fc6ef765b06cf0270630 (diff) | |
| download | rust-0c0c58b8e453f552ebd7f3a1545acdd109de028c.tar.gz rust-0c0c58b8e453f552ebd7f3a1545acdd109de028c.zip | |
Auto merge of #146727 - matthiaskrgr:rollup-98812uj, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang/rust#146434 (c-variadic: allow c-variadic inherent and trait methods) - rust-lang/rust#146487 (Improve `core::num` coverage) - rust-lang/rust#146597 (Add span for struct tail recursion limit error) - rust-lang/rust#146622 (Add regression test for issue rust-lang/rust#91831) - rust-lang/rust#146717 (Clean up universe evaluation during type test evaluation) - rust-lang/rust#146723 (Include patch in release notes) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
18 files changed, 94 insertions, 61 deletions
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index e5405a7ad91..5e10c5a77d9 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -64,8 +64,6 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect -ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list - ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions .label = `extern "{$abi}"` because of this .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dc221c2fb1a..f773b02058e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -696,7 +696,7 @@ impl<'a> AstValidator<'a> { match fn_ctxt { FnCtxt::Foreign => return, - FnCtxt::Free => match sig.header.ext { + FnCtxt::Free | FnCtxt::Assoc(_) => match sig.header.ext { Extern::Implicit(_) => { if !matches!(sig.header.safety, Safety::Unsafe(_)) { self.dcx().emit_err(errors::CVariadicMustBeUnsafe { @@ -726,11 +726,6 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(err); } }, - FnCtxt::Assoc(_) => { - // For now, C variable argument lists are unsupported in associated functions. - let err = errors::CVariadicAssociatedFunction { span: variadic_param.span }; - self.dcx().emit_err(err); - } } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index e09ca5b81c8..fd75e999d13 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -319,13 +319,6 @@ pub(crate) struct ExternItemAscii { } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_associated_function)] -pub(crate) struct CVariadicAssociatedFunction { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(ast_passes_c_variadic_no_extern)] #[help] pub(crate) struct CVariadicNoExtern { diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 94379cdebf7..6be90994015 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -166,13 +166,9 @@ impl RegionTracker { } } - /// Determine if the tracked universes of the two SCCs are compatible. - pub(crate) fn universe_compatible_with(&self, other: Self) -> bool { - // HACK: We first check whether we can name the highest existential universe - // of `other`. This only exists to avoid errors in case that scc already - // depends on a placeholder it cannot name itself. - self.max_nameable_universe().can_name(other.max_nameable_universe()) - || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe()) + /// Determine if we can name all the placeholders in `other`. + pub(crate) fn can_name_all_placeholders(&self, other: Self) -> bool { + other.reachable_placeholders.can_be_named_by(self.max_nameable_universe.0) } /// If this SCC reaches a placeholder it can't name, return it. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f57456949bb..5f4bfd9df48 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -571,11 +571,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// Returns `true` if all the elements in the value of `scc_b` are nameable + /// Returns `true` if all the placeholders in the value of `scc_b` are nameable /// in `scc_a`. Used during constraint propagation, and only once /// the value of `scc_b` has been computed. - fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool { - self.scc_annotations[scc_a].universe_compatible_with(self.scc_annotations[scc_b]) + fn can_name_all_placeholders( + &self, + scc_a: ConstraintSccIndex, + scc_b: ConstraintSccIndex, + ) -> bool { + self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) } /// Once regions have been propagated, this method is used to see @@ -964,16 +968,22 @@ impl<'tcx> RegionInferenceContext<'tcx> { return true; } + let fr_static = self.universal_regions().fr_static; + // If we are checking that `'sup: 'sub`, and `'sub` contains // some placeholder that `'sup` cannot name, then this is only // true if `'sup` outlives static. - if !self.universe_compatible(sub_region_scc, sup_region_scc) { + // + // Avoid infinite recursion if `sub_region` is already `'static` + if sub_region != fr_static + && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) + { debug!( "sub universe `{sub_region_scc:?}` is not nameable \ by super `{sup_region_scc:?}`, promoting to static", ); - return self.eval_outlives(sup_region, self.universal_regions().fr_static); + return self.eval_outlives(sup_region, fr_static); } // Both the `sub_region` and `sup_region` consist of the union diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 2627ed899a9..aece0bda346 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -230,8 +230,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location: impl NormalizeLocation, ) -> Ty<'tcx> { let tcx = self.tcx(); + let body = self.body; + + let cause = ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ); + if self.infcx.next_trait_solver() { - let body = self.body; let param_env = self.infcx.param_env; // FIXME: Make this into a real type op? self.fully_perform_op( @@ -241,10 +247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { |ocx| { let structurally_normalize = |ty| { ocx.structurally_normalize_ty( - &ObligationCause::misc( - location.to_locations().span(body), - body.source.def_id().expect_local(), - ), + &cause, param_env, ty, ) @@ -253,6 +256,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tail = tcx.struct_tail_raw( ty, + &cause, structurally_normalize, || {}, ); @@ -265,7 +269,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } else { let mut normalize = |ty| self.normalize(ty, location); - let tail = tcx.struct_tail_raw(ty, &mut normalize, || {}); + let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {}); normalize(tail) } } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 37c6c4a61d8..7c41258ebfe 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,6 +1,7 @@ use rustc_abi::{BackendRepr, FieldIdx, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; @@ -196,6 +197,7 @@ fn reconstruct_place_meta<'tcx>( // Traverse the type, and update `last_valtree` as we go. let tail = tcx.struct_tail_raw( layout.ty, + &ObligationCause::dummy(), |ty| ty, || { let branches = last_valtree.unwrap_branch(); diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 6d95b6917e2..2fbea5b61cf 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -1,3 +1,4 @@ +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -74,8 +75,14 @@ impl<'a, 'tcx> Expectation<'tcx> { /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 /// for examples of where this comes up,. pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { + let span = match ty.kind() { + ty::Adt(adt_def, _) => fcx.tcx.def_span(adt_def.did()), + _ => fcx.tcx.def_span(fcx.body_id), + }; + let cause = ObligationCause::misc(span, fcx.body_id); + // FIXME: This is not right, even in the old solver... - match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() { + match fcx.tcx.struct_tail_raw(ty, &cause, |ty| ty, || {}).kind() { ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty), _ => ExpectHasType(ty), } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 3444523974a..833ce433d56 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -424,6 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !ty.references_error() { let tail = self.tcx.struct_tail_raw( ty, + &self.misc(span), |ty| { if self.next_trait_solver() { self.try_structurally_resolve_type(span, ty) diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index dad402ec696..e3e1393b5f9 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -71,6 +71,8 @@ pub enum TypeMismatchReason { #[diag(middle_recursion_limit_reached)] #[help] pub(crate) struct RecursionLimitReached<'tcx> { + #[primary_span] + pub span: Span, pub ty: Ty<'tcx>, pub suggested_limit: rustc_hir::limit::Limit, } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index ab8a3142953..0c7bddf60d9 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -823,6 +823,9 @@ impl DynCompatibilityViolation { DynCompatibilityViolation::Method(name, MethodViolationCode::AsyncFn, _) => { format!("method `{name}` is `async`").into() } + DynCompatibilityViolation::Method(name, MethodViolationCode::CVariadic, _) => { + format!("method `{name}` is C-variadic").into() + } DynCompatibilityViolation::Method( name, MethodViolationCode::WhereClauseReferencesSelf, @@ -977,6 +980,9 @@ pub enum MethodViolationCode { /// e.g., `fn foo<A>()` Generic, + /// e.g., `fn (mut ap: ...)` + CVariadic, + /// the method's receiver (`self` argument) can't be dispatched on UndispatchableReceiver(Option<Span>), } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9524057eebc..c477e65f5d6 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -22,6 +22,7 @@ use {rustc_abi as abi, rustc_hir as hir}; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; +use crate::traits::ObligationCause; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt}; @@ -384,6 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_raw( pointee, + &ObligationCause::dummy(), |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(ty) => ty, Err(e) => Ty::new_error_with_message( diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2bea7977999..de35e5e847c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -23,6 +23,7 @@ use ty::util::IntTypeExt; use super::GenericParamDefKind; use crate::infer::canonical::Canonical; +use crate::traits::ObligationCause; use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, @@ -1638,7 +1639,7 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, ) -> Result<Ty<'tcx>, Ty<'tcx>> { - let tail = tcx.struct_tail_raw(self, normalize, || {}); + let tail = tcx.struct_tail_raw(self, &ObligationCause::dummy(), normalize, || {}); match tail.kind() { // Sized types ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b79b67c5927..4f039381e50 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -24,6 +24,7 @@ use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; use crate::query::Providers; +use crate::traits::ObligationCause; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, @@ -216,7 +217,12 @@ impl<'tcx> TyCtxt<'tcx> { typing_env: ty::TypingEnv<'tcx>, ) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {}) + tcx.struct_tail_raw( + ty, + &ObligationCause::dummy(), + |ty| tcx.normalize_erasing_regions(typing_env, ty), + || {}, + ) } /// Returns true if a type has metadata. @@ -248,6 +254,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn struct_tail_raw( self, mut ty: Ty<'tcx>, + cause: &ObligationCause<'tcx>, mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, // This is currently used to allow us to walk a ValTree // in lockstep with the type in order to get the ValTree branch that @@ -261,9 +268,11 @@ impl<'tcx> TyCtxt<'tcx> { Limit(0) => Limit(2), limit => limit * 2, }; - let reported = self - .dcx() - .emit_err(crate::error::RecursionLimitReached { ty, suggested_limit }); + let reported = self.dcx().emit_err(crate::error::RecursionLimitReached { + span: cause.span, + ty, + suggested_limit, + }); return Ty::new_error(self, reported); } match *ty.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index bcd11d6918d..3260dd712b9 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -426,6 +426,9 @@ fn virtual_call_violations_for_method<'tcx>( if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) { errors.push(code); } + if sig.skip_binder().c_variadic { + errors.push(MethodViolationCode::CVariadic); + } // We can't monomorphize things like `fn foo<A>(...)`. let own_counts = tcx.generics_of(method.def_id).own_counts(); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 884d53732fe..042d6def84c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1057,6 +1057,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( Some(LangItem::PointeeTrait) => { let tail = selcx.tcx().struct_tail_raw( self_ty, + &obligation.cause, |ty| { // We throw away any obligations we get from this, since we normalize // and confirm these obligations once again during confirmation diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 643e3db8f83..c4cb43011ad 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -10,6 +10,7 @@ use rustc_hashes::Hash64; use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::layout::{ FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, }; @@ -390,30 +391,31 @@ fn layout_of_uncached<'tcx>( let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); - let metadata_ty = - match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) { - Ok(metadata_ty) => metadata_ty, - Err(mut err) => { - // Usually `<Ty as Pointee>::Metadata` can't be normalized because - // its struct tail cannot be normalized either, so try to get a - // more descriptive layout error here, which will lead to less confusing - // diagnostics. - // - // We use the raw struct tail function here to get the first tail - // that is an alias, which is likely the cause of the normalization - // error. - match tcx.try_normalize_erasing_regions( - cx.typing_env, - tcx.struct_tail_raw(pointee, |ty| ty, || {}), - ) { - Ok(_) => {} - Err(better_err) => { - err = better_err; - } + let metadata_ty = match tcx + .try_normalize_erasing_regions(cx.typing_env, pointee_metadata) + { + Ok(metadata_ty) => metadata_ty, + Err(mut err) => { + // Usually `<Ty as Pointee>::Metadata` can't be normalized because + // its struct tail cannot be normalized either, so try to get a + // more descriptive layout error here, which will lead to less confusing + // diagnostics. + // + // We use the raw struct tail function here to get the first tail + // that is an alias, which is likely the cause of the normalization + // error. + match tcx.try_normalize_erasing_regions( + cx.typing_env, + tcx.struct_tail_raw(pointee, &ObligationCause::dummy(), |ty| ty, || {}), + ) { + Ok(_) => {} + Err(better_err) => { + err = better_err; } - return Err(error(cx, LayoutError::NormalizationFailure(pointee, err))); } - }; + return Err(error(cx, LayoutError::NormalizationFailure(pointee, err))); + } + }; let metadata_layout = cx.layout_of(metadata_ty)?; // If the metadata is a 1-zst, then the pointer is thin. diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 18a9a7c22d9..e91e5055e90 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -353,6 +353,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) let tail = tcx.struct_tail_raw( tcx.type_of(impl_def_id).instantiate_identity(), + &cause, |ty| { ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| { Ty::new_error_with_message( |
