From f57a64ae5af9907d108532ff437dc05020445397 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Wed, 21 May 2025 18:50:01 +0200 Subject: [PATCH 01/10] ci: improve citool job db errors --- src/ci/citool/src/jobs.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 5600d7b4db59b..60cbf50c7a3a1 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -85,14 +85,20 @@ impl JobDatabase { } pub fn load_job_db(db: &str) -> anyhow::Result { - let mut db: Value = serde_yaml::from_str(db)?; + let mut db: Value = serde_yaml::from_str(db).context("failed to parse YAML content")?; // We need to expand merge keys (<<), because serde_yaml can't deal with them // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges. - db.apply_merge()?; - db.apply_merge()?; - let db: JobDatabase = serde_yaml::from_value(db)?; + let apply_merge = |db: &mut Value| -> anyhow::Result<()> { + db.apply_merge().context("failed to apply merge keys") + }; + + // Apply merge twice to handle nested merges + apply_merge(&mut db)?; + apply_merge(&mut db)?; + + let db: JobDatabase = serde_yaml::from_value(db).context("failed to parse job database")?; Ok(db) } From ca912d794d42336ddd54389480b56bfc2bc6685f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 May 2025 14:55:47 +0000 Subject: [PATCH 02/10] Make captures state error more precise --- .../src/error_reporting/traits/fulfillment_errors.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 970160ba212af..7d8c4df6341c4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -841,16 +841,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() { + let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() { ty::Closure(def_id, args) => { - (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) + (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), false) } ty::CoroutineClosure(def_id, args) => ( def_id, args.as_coroutine_closure() .coroutine_closure_sig() .map_bound(|sig| sig.tupled_inputs_ty), - Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), + !args.as_coroutine_closure().tupled_upvars_ty().is_ty_var() + && args.as_coroutine_closure().has_self_borrows(), ), _ => return None, }; @@ -884,10 +885,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // If the closure has captures, then perhaps the reason that the trait // is unimplemented is because async closures don't implement `Fn`/`FnMut` // if they have captures. - if let Some(by_ref_captures) = by_ref_captures - && let ty::FnPtr(sig_tys, _) = by_ref_captures.kind() - && !sig_tys.skip_binder().output().is_unit() - { + if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce { let mut err = self.dcx().create_err(AsyncClosureNotFn { span: self.tcx.def_span(closure_def_id), kind: expected_kind.as_str(), From e0f80558716372902b2eda1e43ab2e169bfb3669 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 May 2025 18:07:29 +0000 Subject: [PATCH 03/10] Fix FnOnce impl for AsyncFn/AsyncFnMut closures in new solver --- .../src/solve/assembly/structural_traits.rs | 2 +- .../async-closures/async-fn-mut-impl-fn-once.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/ui/async-await/async-closures/async-fn-mut-impl-fn-once.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 2a2b462a36cbd..26ad72bea806c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -327,7 +327,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable(_: impl FnOnce() -> F) {} + +fn main() { + let mut i = 0; + let c = async || { + i += 1; + }; + call_once(c); +} From 85d2d843c3cff20beb242a0d1726630ad10b5ff9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 22 May 2025 13:25:45 +1000 Subject: [PATCH 04/10] Remove `is_empty` check in `filter_assoc_items_by_name_and_namespace`. It was added in #140052, but the subsequent changes in #140252 means it is no longer necessary. (Indeed, `Ident`s cannot be empty any more.) --- src/librustdoc/passes/collect_intra_doc_links.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f3e2138d1a575..37628f166002d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -59,12 +59,7 @@ fn filter_assoc_items_by_name_and_namespace( ident: Ident, ns: Namespace, ) -> impl Iterator { - let iter: Box> = if !ident.name.is_empty() { - Box::new(tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name)) - } else { - Box::new([].iter()) - }; - iter.filter(move |item| { + tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) } From c309065ece12632a522676c794e0befbceb213f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 22 May 2025 13:31:19 +1000 Subject: [PATCH 05/10] Remove `is_empty` check in `Ident::is_numeric`. `Ident`s can no longer be empty, so the test always succeeds. --- compiler/rustc_span/src/symbol.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fbe3b4ca6f5f6..dc77eb52b2e60 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2823,7 +2823,7 @@ impl Ident { /// Whether this would be the identifier for a tuple field like `self.0`, as /// opposed to a named field like `self.thing`. pub fn is_numeric(self) -> bool { - !self.name.is_empty() && self.as_str().bytes().all(|b| b.is_ascii_digit()) + self.as_str().bytes().all(|b| b.is_ascii_digit()) } } From 27677ef14393e7789f2d0a29bfdcf20bf657eddb Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Thu, 22 May 2025 09:53:35 +0200 Subject: [PATCH 06/10] ci: convert distcheck to free runner --- src/ci/github-actions/jobs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 005007bbccdd1..58a1db93e6e3c 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -324,7 +324,7 @@ auto: <<: *job-linux-4c - name: x86_64-gnu-distcheck - <<: *job-linux-8c + <<: *job-linux-4c # The x86_64-gnu-llvm-20 job is split into multiple jobs to run tests in parallel. # x86_64-gnu-llvm-20-1 skips tests that run in x86_64-gnu-llvm-20-{2,3}. From 806cd12f56446bd31aea495e83661f5c3cf3a17d Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Thu, 22 May 2025 12:48:12 +0200 Subject: [PATCH 07/10] ci: prepare aws access keys for migration --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bce8389d8ec2..566ae2235001c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -234,8 +234,8 @@ jobs: fi exit ${STATUS} env: - AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }} + AWS_ACCESS_KEY_ID: ${{ (github.repository == 'rust-lang/rust' && secrets.CACHES_AWS_ACCESS_KEY_ID) || env.CACHES_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ (github.repository == 'rust-lang/rust' && secrets.CACHES_AWS_SECRET_ACCESS_KEY) || secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }} - name: create github artifacts run: src/ci/scripts/create-doc-artifacts.sh @@ -257,8 +257,8 @@ jobs: - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: - AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} + AWS_ACCESS_KEY_ID: ${{ (github.repository == 'rust-lang/rust' && secrets.ARTIFACTS_AWS_ACCESS_KEY_ID) || env.ARTIFACTS_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ (github.repository == 'rust-lang/rust' && secrets.ARTIFACTS_AWS_SECRET_ACCESS_KEY) || secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy # builders *should* have the AWS credentials available. Still, explicitly # adding the condition is helpful as this way CI will not silently skip From bc9cdc960f7ba7a926cea97cf0cec77097ca7851 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 21 May 2025 18:37:39 +0100 Subject: [PATCH 08/10] Return correct error term kind on projection errors --- .../src/traits/project.rs | 29 ++++++++++++-- tests/crashes/140642.rs | 8 ---- .../const-generics/mgca/projection-error.rs | 17 ++++++++ .../mgca/projection-error.stderr | 39 +++++++++++++++++++ 4 files changed, 81 insertions(+), 12 deletions(-) delete mode 100644 tests/crashes/140642.rs create mode 100644 tests/ui/const-generics/mgca/projection-error.rs create mode 100644 tests/ui/const-generics/mgca/projection-error.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ca58da5ca6d55..ed0f34b5aa915 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -378,6 +378,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( term: projected_term, obligations: mut projected_obligations, })) => { + debug!("opt_normalize_projection_type: progress"); // if projection succeeded, then what we get out of this // is also non-normalized (consider: it was derived from // an impl, where-clause etc) and hence we must @@ -408,6 +409,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( Ok(Some(result.value)) } Ok(Projected::NoProgress(projected_ty)) => { + debug!("opt_normalize_projection_type: no progress"); let result = Normalized { value: projected_ty, obligations: PredicateObligations::new() }; infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); @@ -621,8 +623,17 @@ struct Progress<'tcx> { } impl<'tcx> Progress<'tcx> { - fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Progress { term: Ty::new_error(tcx, guar).into(), obligations: PredicateObligations::new() } + fn error_for_term( + tcx: TyCtxt<'tcx>, + alias_term: ty::AliasTerm<'tcx>, + guar: ErrorGuaranteed, + ) -> Self { + let err_term = if alias_term.kind(tcx).is_type() { + Ty::new_error(tcx, guar).into() + } else { + ty::Const::new_error(tcx, guar).into() + }; + Progress { term: err_term, obligations: PredicateObligations::new() } } fn with_addl_obligations(mut self, mut obligations: PredicateObligations<'tcx>) -> Self { @@ -650,7 +661,11 @@ fn project<'cx, 'tcx>( } if let Err(guar) = obligation.predicate.error_reported() { - return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar))); + return Ok(Projected::Progress(Progress::error_for_term( + selcx.tcx(), + obligation.predicate, + guar, + ))); } let mut candidates = ProjectionCandidateSet::None; @@ -1965,7 +1980,13 @@ fn confirm_impl_candidate<'cx, 'tcx>( let param_env = obligation.param_env; let assoc_term = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) { Ok(assoc_term) => assoc_term, - Err(guar) => return Ok(Projected::Progress(Progress::error(tcx, guar))), + Err(guar) => { + return Ok(Projected::Progress(Progress::error_for_term( + tcx, + obligation.predicate, + guar, + ))); + } }; // This means that the impl is missing a definition for the diff --git a/tests/crashes/140642.rs b/tests/crashes/140642.rs deleted file mode 100644 index ff75a6ec2f230..0000000000000 --- a/tests/crashes/140642.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #140642 -#![feature(min_generic_const_args)] - -pub trait Tr { - const SIZE: usize; -} - -fn mk_array(_x: T) -> [(); >::SIZE] {} diff --git a/tests/ui/const-generics/mgca/projection-error.rs b/tests/ui/const-generics/mgca/projection-error.rs new file mode 100644 index 0000000000000..d1c4fa8a492d3 --- /dev/null +++ b/tests/ui/const-generics/mgca/projection-error.rs @@ -0,0 +1,17 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +// Regression test for #140642. Test that normalizing const aliases +// containing erroneous types normalizes to a const error instead of +// a type error. + + +pub trait Tr { + const SIZE: usize; +} + +fn mk_array(_x: T) -> [(); >::SIZE] {} +//~^ ERROR: cannot find type `T` in this scope +//~| ERROR: cannot find type `T` in this scope + +fn main() {} diff --git a/tests/ui/const-generics/mgca/projection-error.stderr b/tests/ui/const-generics/mgca/projection-error.stderr new file mode 100644 index 0000000000000..e6888351da13a --- /dev/null +++ b/tests/ui/const-generics/mgca/projection-error.stderr @@ -0,0 +1,39 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/projection-error.rs:13:17 + | +LL | pub trait Tr { + | --------------- similarly named trait `Tr` defined here +... +LL | fn mk_array(_x: T) -> [(); >::SIZE] {} + | ^ + | +help: a trait with a similar name exists + | +LL | fn mk_array(_x: Tr) -> [(); >::SIZE] {} + | + +help: you might be missing a type parameter + | +LL | fn mk_array(_x: T) -> [(); >::SIZE] {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/projection-error.rs:13:29 + | +LL | pub trait Tr { + | --------------- similarly named trait `Tr` defined here +... +LL | fn mk_array(_x: T) -> [(); >::SIZE] {} + | ^ + | +help: a trait with a similar name exists + | +LL | fn mk_array(_x: T) -> [(); >::SIZE] {} + | + +help: you might be missing a type parameter + | +LL | fn mk_array(_x: T) -> [(); >::SIZE] {} + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. From 16b6ffe0dbced4eeb1828b3a5674786dedc56cfc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 May 2025 11:06:42 +0000 Subject: [PATCH 09/10] Don't allow poly_select in new solver --- .../traits/fulfillment_errors.rs | 10 ++++---- .../rustc_trait_selection/src/solve/select.rs | 4 +-- .../src/traits/select/mod.rs | 8 +++--- .../hr-projection-mismatch.current.stderr | 12 +++++++++ .../hr-projection-mismatch.next.stderr | 20 +++++++++++++++ .../hr-projection-mismatch.rs | 25 +++++++++++++++++++ 6 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 tests/ui/mismatched_types/hr-projection-mismatch.current.stderr create mode 100644 tests/ui/mismatched_types/hr-projection-mismatch.next.stderr create mode 100644 tests/ui/mismatched_types/hr-projection-mismatch.rs diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 970160ba212af..bfff60e49c714 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1503,11 +1503,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let Ok(Some(ImplSource::UserDefined(impl_data))) = SelectionContext::new(self) - .poly_select(&obligation.with( - self.tcx, - predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), - )) + let trait_ref = self.enter_forall_and_leak_universe( + predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), + ); + let Ok(Some(ImplSource::UserDefined(impl_data))) = + SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref)) else { return None; }; diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 4fdaf740287ba..1f3168fafb1da 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -5,7 +5,7 @@ use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_infer::traits::{ BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, - PolyTraitObligation, Selection, SelectionError, SelectionResult, + Selection, SelectionError, SelectionResult, TraitObligation, }; use rustc_macros::extension; use rustc_middle::{bug, span_bug}; @@ -17,7 +17,7 @@ use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; impl<'tcx> InferCtxt<'tcx> { fn select_in_new_trait_solver( &self, - obligation: &PolyTraitObligation<'tcx>, + obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 44a76f6e08327..f4ec528c6726e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -265,9 +265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - if self.infcx.next_trait_solver() { - return self.infcx.select_in_new_trait_solver(obligation); - } + assert!(!self.infcx.next_trait_solver()); let candidate = match self.select_from_obligation(obligation) { Err(SelectionError::Overflow(OverflowError::Canonical)) => { @@ -299,6 +297,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { + if self.infcx.next_trait_solver() { + return self.infcx.select_in_new_trait_solver(obligation); + } + self.poly_select(&Obligation { cause: obligation.cause.clone(), param_env: obligation.param_env, diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr new file mode 100644 index 0000000000000..a2cec972e4a99 --- /dev/null +++ b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/hr-projection-mismatch.rs:20:5 + | +LL | wrap::<_, Thing>(); + | ^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'a _` + found reference `&_` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.next.stderr b/tests/ui/mismatched_types/hr-projection-mismatch.next.stderr new file mode 100644 index 0000000000000..6ea0d43e1530c --- /dev/null +++ b/tests/ui/mismatched_types/hr-projection-mismatch.next.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `>::Assoc == &i32` + --> $DIR/hr-projection-mismatch.rs:20:15 + | +LL | wrap::<_, Thing>(); + | ^^^^^ type mismatch resolving `>::Assoc == &i32` + | +note: types differ + --> $DIR/hr-projection-mismatch.rs:14:18 + | +LL | type Assoc = &'a i32; + | ^^^^^^^ +note: required by a bound in `wrap` + --> $DIR/hr-projection-mismatch.rs:17:33 + | +LL | fn wrap Trait<'a, Assoc = T>>() {} + | ^^^^^^^^^ required by this bound in `wrap` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.rs b/tests/ui/mismatched_types/hr-projection-mismatch.rs new file mode 100644 index 0000000000000..f96314a3fca07 --- /dev/null +++ b/tests/ui/mismatched_types/hr-projection-mismatch.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . + +trait Trait<'a> { + type Assoc; +} + +struct Thing; + +impl<'a> Trait<'a> for Thing { + type Assoc = &'a i32; +} + +fn wrap Trait<'a, Assoc = T>>() {} + +fn foo() { + wrap::<_, Thing>(); + //[next]~^ ERROR type mismatch resolving `>::Assoc == &i32 + //[current]~^^ ERROR mismatched types +} + +fn main() {} From 09ae053f7a6d29909a309953182b6f067717cc83 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 May 2025 08:24:40 +0200 Subject: [PATCH 10/10] try_cast_aligned: avoid bare int-to-ptr casts --- library/core/src/ptr/const_ptr.rs | 12 +++++------- library/core/src/ptr/mut_ptr.rs | 12 +++++------- library/core/src/ptr/non_null.rs | 12 +++++------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f6109cafe86b1..19ed7599a5101 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -76,15 +76,13 @@ impl *const T { /// ```rust /// #![feature(pointer_try_cast_aligned)] /// - /// let aligned: *const u8 = 0x1000 as _; + /// let x = 0u64; /// - /// // i32 has at most 4-byte alignment, so this will succeed - /// assert!(aligned.try_cast_aligned::().is_some()); + /// let aligned: *const u64 = &x; + /// let unaligned = unsafe { aligned.byte_add(1) }; /// - /// let unaligned: *const u8 = 0x1001 as _; - /// - /// // i32 has at least 2-byte alignment, so this will fail - /// assert!(unaligned.try_cast_aligned::().is_none()); + /// assert!(aligned.try_cast_aligned::().is_some()); + /// assert!(unaligned.try_cast_aligned::().is_none()); /// ``` #[unstable(feature = "pointer_try_cast_aligned", issue = "141221")] #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 2662a4fdc3138..53aa3ab49388f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -58,15 +58,13 @@ impl *mut T { /// ```rust /// #![feature(pointer_try_cast_aligned)] /// - /// let aligned: *mut u8 = 0x1000 as _; + /// let mut x = 0u64; /// - /// // i32 has at most 4-byte alignment, so this will succeed - /// assert!(aligned.try_cast_aligned::().is_some()); + /// let aligned: *mut u64 = &mut x; + /// let unaligned = unsafe { aligned.byte_add(1) }; /// - /// let unaligned: *mut u8 = 0x1001 as _; - /// - /// // i32 has at least 2-byte alignment, so this will fail - /// assert!(unaligned.try_cast_aligned::().is_none()); + /// assert!(aligned.try_cast_aligned::().is_some()); + /// assert!(unaligned.try_cast_aligned::().is_none()); /// ``` #[unstable(feature = "pointer_try_cast_aligned", issue = "141221")] #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index bb344c6a0d316..7c9b898f8e99f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -501,15 +501,13 @@ impl NonNull { /// #![feature(pointer_try_cast_aligned)] /// use std::ptr::NonNull; /// - /// let aligned: NonNull = NonNull::new(0x1000 as _).unwrap(); + /// let mut x = 0u64; /// - /// // i32 has at most 4-byte alignment, so this will succeed - /// assert!(aligned.try_cast_aligned::().is_some()); + /// let aligned = NonNull::from_mut(&mut x); + /// let unaligned = unsafe { aligned.byte_add(1) }; /// - /// let unaligned: NonNull = NonNull::new(0x1001 as _).unwrap(); - /// - /// // i32 has at least 2-byte alignment, so this will fail - /// assert!(unaligned.try_cast_aligned::().is_none()); + /// assert!(aligned.try_cast_aligned::().is_some()); + /// assert!(unaligned.try_cast_aligned::().is_none()); /// ``` #[unstable(feature = "pointer_try_cast_aligned", issue = "141221")] #[must_use = "this returns the result of the operation, \