From 10e95f40c5ebf07b43e413d8b11ee8f70eeae755 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Tue, 11 Aug 2026 12:02:21 +0800 Subject: [PATCH 1/8] disable some tests for ohos target --- src/tools/compiletest/src/directives/directive_names.rs | 1 + tests/codegen-llvm/thread-local.rs | 1 + tests/debuginfo/pretty-huge-vec.rs | 1 + tests/ui/asm/aarch64/sym.rs | 1 + tests/ui/runtime/out-of-stack.rs | 1 + 5 files changed, 5 insertions(+) diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index b73e782252148..5025e2c868ca2 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -104,6 +104,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-nto", "ignore-nvptx64", "ignore-nvptx64-nvidia-cuda", + "ignore-ohos", "ignore-openbsd", "ignore-parallel-frontend", "ignore-pauthtest", diff --git a/tests/codegen-llvm/thread-local.rs b/tests/codegen-llvm/thread-local.rs index 8eb0443ebb9b5..70b655fd5cf61 100644 --- a/tests/codegen-llvm/thread-local.rs +++ b/tests/codegen-llvm/thread-local.rs @@ -6,6 +6,7 @@ //@ ignore-android does not use #[thread_local] //@ ignore-nto does not use #[thread_local] //@ ignore-qnx does not use #[thread_local] +//@ ignore-ohos does not use #[thread_local] #![crate_type = "lib"] diff --git a/tests/debuginfo/pretty-huge-vec.rs b/tests/debuginfo/pretty-huge-vec.rs index 2cea3f224c4a1..da006f1139d32 100644 --- a/tests/debuginfo/pretty-huge-vec.rs +++ b/tests/debuginfo/pretty-huge-vec.rs @@ -1,5 +1,6 @@ //@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) +//@ ignore-ohos: similiar to android //@ ignore-aix: FIXME(#137965) //@ compile-flags:-g //@ ignore-backends: gcc diff --git a/tests/ui/asm/aarch64/sym.rs b/tests/ui/asm/aarch64/sym.rs index 87c6d5ddfdc48..27113c694aac7 100644 --- a/tests/ui/asm/aarch64/sym.rs +++ b/tests/ui/asm/aarch64/sym.rs @@ -1,5 +1,6 @@ //@ only-aarch64 //@ only-linux +//@ ignore-ohos does not use #[thread_local] //@ needs-asm-support //@ run-pass diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs index 9b3878229417c..2e140bc9277a2 100644 --- a/tests/ui/runtime/out-of-stack.rs +++ b/tests/ui/runtime/out-of-stack.rs @@ -5,6 +5,7 @@ //@ ignore-android: FIXME (#20004) //@ needs-subprocess //@ ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590) +//@ ignore-ohos musl libc returns SIGSEGV for stack overflow rather than SIGABRT //@ ignore-nto no stack overflow handler used (no alternate stack available) //@ ignore-qnx no stack overflow handler used (no alternate stack available) //@ ignore-ios stack overflow handlers aren't enabled From de4e2e2a239d29228ad44ac5441ae4be599b7502 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:51:52 +0900 Subject: [PATCH 2/8] Ensure restriction paths are ancestors of items when lowering to HIR --- .../rustc_ast_lowering/src/diagnostics.rs | 32 ++++- compiler/rustc_ast_lowering/src/item.rs | 64 +++++++--- compiler/rustc_hir/src/hir.rs | 2 + compiler/rustc_resolve/src/diagnostics/mod.rs | 15 +-- compiler/rustc_resolve/src/late.rs | 46 +------ .../restriction_resolution_errors.stderr | 120 +++++++++--------- .../restriction-resolution-errors.stderr | 84 ++++++------ 7 files changed, 182 insertions(+), 181 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/diagnostics.rs b/compiler/rustc_ast_lowering/src/diagnostics.rs index 2fbf8fac4c64e..b0fada9d3cd9e 100644 --- a/compiler/rustc_ast_lowering/src/diagnostics.rs +++ b/compiler/rustc_ast_lowering/src/diagnostics.rs @@ -1,5 +1,5 @@ use rustc_errors::codes::*; -use rustc_errors::{DiagArgFromDisplay, DiagSymbolList}; +use rustc_errors::{DiagArgFromDisplay, DiagArgValue, DiagSymbolList, IntoDiagArg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -579,3 +579,33 @@ pub(crate) struct DelegationAttemptedBlockWithDefsRelowering { #[primary_span] pub span: Span, } + +/// Whether resolving `impl` or `mut` restriction paths +#[derive(Debug, Clone, Copy)] +pub(crate) enum ResolvingRestrictionKind { + Impl, + Mut, +} + +impl IntoDiagArg for ResolvingRestrictionKind { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + use std::borrow::Cow; + match self { + ResolvingRestrictionKind::Impl => DiagArgValue::Str(Cow::Borrowed("impl")), + ResolvingRestrictionKind::Mut => DiagArgValue::Str(Cow::Borrowed("mut")), + } + } +} + +#[derive(Diagnostic)] +#[diag( + "{$kind -> + [impl] trait implementation + *[mut] field mutation +} can only be restricted to ancestor modules" +)] +pub(crate) struct RestrictionAncestorOnly { + #[primary_span] + pub(crate) span: Span, + pub(crate) kind: ResolvingRestrictionKind, +} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3cc27be600965..316fe4edb61e6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -26,7 +26,7 @@ use super::{ FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, }; -use crate::diagnostics::ConstComptimeFn; +use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly}; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, @@ -498,7 +498,7 @@ impl<'hir> LoweringContext<'_, 'hir> { items, }) => { let constness = self.lower_constness(attrs, *constness); - let impl_restriction = self.lower_impl_restriction(impl_restriction); + let impl_restriction = self.lower_impl_restriction(impl_restriction, hir_id); let ident = self.lower_ident(*ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, @@ -895,7 +895,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, vis_span: self.lower_span(f.vis.span), - mut_restriction: self.lower_mut_restriction(f.mut_restriction()), + mut_restriction: self.lower_mut_restriction(f.mut_restriction(), hir_id), default: f .default_value() .map(|v| self.lower_anon_const_to_anon_const(v, v.value.span)), @@ -1797,26 +1797,46 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_restriction_kind(&mut self, kind: &RestrictionKind) -> hir::RestrictionKind<'hir> { - match kind { + fn lower_restriction_kind( + &mut self, + restriction_kind: &RestrictionKind, + hir_id: HirId, + resolving_kind: ResolvingRestrictionKind, + ) -> hir::RestrictionKind<'hir> { + match restriction_kind { RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted, RestrictionKind::Restricted { path, id, shorthand: _ } => { let res = self.get_partial_res(*id); + let parent_module = self.tcx.parent_module(hir_id); if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) { - hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path { - res: did, - segments: self.arena.alloc_from_iter(path.segments.iter().map(|segment| { - self.lower_path_segment( - path.span, - segment, - ParamMode::Explicit, - GenericArgsMode::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, - ) - })), - span: self.lower_span(path.span), - })) + if !self.tcx.is_descendant_of(parent_module, did) { + // If the restriction path is not an ancestor of the item, + // emit an error and recover by lowering the restriction to `Unrestricted`. + self.dcx() + .create_err(RestrictionAncestorOnly { + span: path.span, + kind: resolving_kind, + }) + .emit(); + hir::RestrictionKind::Unrestricted + } else { + hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path { + res: did, + segments: self.arena.alloc_from_iter(path.segments.iter().map( + |segment| { + self.lower_path_segment( + path.span, + segment, + ParamMode::Explicit, + GenericArgsMode::Err, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ) + }, + )), + span: self.lower_span(path.span), + })) + } } else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); hir::RestrictionKind::Unrestricted @@ -1828,16 +1848,18 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_impl_restriction( &mut self, r: &ImplRestriction, + hir_id: HirId, ) -> &'hir hir::ImplRestriction<'hir> { - let kind = self.lower_restriction_kind(&r.kind); + let kind = self.lower_restriction_kind(&r.kind, hir_id, ResolvingRestrictionKind::Impl); self.arena.alloc(hir::ImplRestriction { kind, span: self.lower_span(r.span) }) } pub(super) fn lower_mut_restriction( &mut self, r: &MutRestriction, + hir_id: HirId, ) -> &'hir hir::MutRestriction<'hir> { - let kind = self.lower_restriction_kind(&r.kind); + let kind = self.lower_restriction_kind(&r.kind, hir_id, ResolvingRestrictionKind::Mut); self.arena.alloc(hir::MutRestriction { kind, span: self.lower_span(r.span) }) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e4d6f052c2246..112f784825975 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4398,6 +4398,8 @@ pub enum RestrictionKind<'hir> { /// The restriction does not affect the item. Unrestricted, /// The restriction only applies outside of this path. + /// The path is guaranteed to resolve to an ancestor module + /// of the restricted item. Restricted(&'hir Path<'hir, DefId>), } diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index 9053d45a41191..d4ce0dc78ca1f 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -8,7 +8,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Spanned, Symbol}; use crate::Res; -use crate::late::{PatternSource, ResolvingRestrictionKind}; +use crate::late::PatternSource; pub(crate) mod impls; @@ -547,19 +547,6 @@ pub(crate) struct ExpectedModuleFound { #[diag("cannot determine resolution for the visibility", code = E0578)] pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); -#[derive(Diagnostic)] -#[diag( - "{$kind -> - [impl] trait implementation - *[mut] field mutation -} can only be restricted to ancestor modules" -)] -pub(crate) struct RestrictionAncestorOnly { - #[primary_span] - pub(crate) span: Span, - pub(crate) kind: ResolvingRestrictionKind, -} - #[derive(Diagnostic)] #[diag("cannot use a tool module through an import")] pub(crate) struct ToolModuleImported { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8b7c99e55edaa..8e4b55dbf9bc4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -426,23 +426,6 @@ pub(crate) enum AliasPossibility { Maybe, } -/// Whether resolving `impl` or `mut` restriction paths -#[derive(Debug, Clone, Copy)] -pub(crate) enum ResolvingRestrictionKind { - Impl, - Mut, -} - -impl IntoDiagArg for ResolvingRestrictionKind { - fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { - use std::borrow::Cow; - match self { - ResolvingRestrictionKind::Impl => DiagArgValue::Str(Cow::Borrowed("impl")), - ResolvingRestrictionKind::Mut => DiagArgValue::Str(Cow::Borrowed("mut")), - } - } -} - #[derive(Copy, Clone, Debug)] pub(crate) enum PathSource<'a, 'ast, 'ra> { /// Type paths `Path`. @@ -1502,7 +1485,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, extras: _ } = f; walk_list!(self, visit_attribute, attrs); try_visit!(self.visit_vis(vis)); - self.resolve_restriction_path(&f.mut_restriction().kind, ResolvingRestrictionKind::Mut); + self.resolve_restriction_path(&f.mut_restriction().kind); visit_opt!(self, visit_ident, ident); try_visit!(self.visit_ty(ty)); if let Some(v) = f.default_value() { @@ -2875,10 +2858,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ItemKind::Trait(Trait { generics, bounds, items, impl_restriction, .. }) => { // resolve paths for `impl` restrictions - self.resolve_restriction_path( - &impl_restriction.kind, - ResolvingRestrictionKind::Impl, - ); + self.resolve_restriction_path(&impl_restriction.kind); // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( @@ -4494,31 +4474,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn resolve_restriction_path( - &mut self, - restriction: &'ast ast::RestrictionKind, - kind: ResolvingRestrictionKind, - ) { + fn resolve_restriction_path(&mut self, restriction: &'ast ast::RestrictionKind) { match &restriction { ast::RestrictionKind::Unrestricted => (), ast::RestrictionKind::Restricted { path, id, shorthand: _ } => { self.smart_resolve_path(*id, &None, path, PathSource::Module); - if let Some(res) = self.r.partial_res_map[&id].full_res() - && let Some(def_id) = res.opt_def_id() - { - if !self.r.is_accessible_from( - Visibility::Restricted(def_id), - self.parent_scope.module, - ) { - self.r - .dcx() - .create_err(crate::diagnostics::RestrictionAncestorOnly { - span: path.span, - kind, - }) - .emit(); - } - } } } } diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.stderr b/tests/ui/impl-restriction/restriction_resolution_errors.stderr index 70af66c9186bf..e5e6281968a9b 100644 --- a/tests/ui/impl-restriction/restriction_resolution_errors.stderr +++ b/tests/ui/impl-restriction/restriction_resolution_errors.stderr @@ -1,75 +1,15 @@ -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:16:21 - | -LL | pub impl(in ::std) trait T2 {} - | ^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:18:21 - | -LL | pub impl(in self::c) trait T3 {} - | ^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:20:21 - | -LL | pub impl(in super::d) trait T4 {} - | ^^^^^^^^ - error[E0433]: too many leading `super` keywords within `crate::a::b` --> $DIR/restriction_resolution_errors.rs:26:35 | LL | pub impl(in super::super::super) trait T7 {} | ^^^^^ this `super` would go above the crate root -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:36:21 - | -LL | pub impl(in self::f) trait L1 {} - | ^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:40:21 - | -LL | pub impl(in super::h) trait L3 {} - | ^^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:49:13 - | -LL | pub impl(in crate::a) trait T13 {} - | ^^^^^^^^ - error[E0433]: too many leading `super` keywords within `crate` --> $DIR/restriction_resolution_errors.rs:56:10 | LL | pub impl(super) trait T17 {} | ^^^^^ this `super` would go above the crate root -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:58:13 - | -LL | pub impl(in external) trait T18 {} - | ^^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:61:13 - | -LL | pub impl(in crate::j) trait L4 {} - | ^^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:77:21 - | -LL | pub impl(in crate::m2) trait U2 {} - | ^^^^^^^^^ - -error: trait implementation can only be restricted to ancestor modules - --> $DIR/restriction_resolution_errors.rs:79:21 - | -LL | pub impl(in m6::m5) trait U4 {} - | ^^^^^^ - error[E0433]: cannot find module or crate `a` in this scope --> $DIR/restriction_resolution_errors.rs:14:21 | @@ -140,6 +80,66 @@ error[E0577]: expected module, found enum `m7` LL | pub impl(in m7) trait U5 {} | ^^ not a module +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:16:21 + | +LL | pub impl(in ::std) trait T2 {} + | ^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:18:21 + | +LL | pub impl(in self::c) trait T3 {} + | ^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:20:21 + | +LL | pub impl(in super::d) trait T4 {} + | ^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:36:21 + | +LL | pub impl(in self::f) trait L1 {} + | ^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:40:21 + | +LL | pub impl(in super::h) trait L3 {} + | ^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:49:13 + | +LL | pub impl(in crate::a) trait T13 {} + | ^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:58:13 + | +LL | pub impl(in external) trait T18 {} + | ^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:61:13 + | +LL | pub impl(in crate::j) trait L4 {} + | ^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:77:21 + | +LL | pub impl(in crate::m2) trait U2 {} + | ^^^^^^^^^ + +error: trait implementation can only be restricted to ancestor modules + --> $DIR/restriction_resolution_errors.rs:79:21 + | +LL | pub impl(in m6::m5) trait U4 {} + | ^^^^^^ + error: aborting due to 19 previous errors Some errors have detailed explanations: E0433, E0577. diff --git a/tests/ui/mut-restriction/restriction-resolution-errors.stderr b/tests/ui/mut-restriction/restriction-resolution-errors.stderr index 9bf1e4742a619..7e5390c37764f 100644 --- a/tests/ui/mut-restriction/restriction-resolution-errors.stderr +++ b/tests/ui/mut-restriction/restriction-resolution-errors.stderr @@ -1,57 +1,15 @@ -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:10:24 - | -LL | pub mut(in ::std) i2: i32, - | ^^^^^ - -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:11:24 - | -LL | pub mut(in self::c) i3: i32, - | ^^^^^^^ - -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:12:24 - | -LL | pub mut(in super::d) i4: i32, - | ^^^^^^^^ - error[E0433]: too many leading `super` keywords within `crate::a::b` --> $DIR/restriction-resolution-errors.rs:15:38 | LL | pub mut(in super::super::super) i7: i32, | ^^^^^ this `super` would go above the crate root -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:32:16 - | -LL | mut(in crate::a) e1: i32, - | ^^^^^^^^ - error[E0433]: too many leading `super` keywords within `crate` --> $DIR/restriction-resolution-errors.rs:36:13 | LL | mut(super) e5: i32, | ^^^^^ this `super` would go above the crate root -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:38:16 - | -LL | Tup(mut(in external) i32), - | ^^^^^^^^ - -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:52:24 - | -LL | pub mut(in crate::m2) i32, - | ^^^^^^^^^ - -error: field mutation can only be restricted to ancestor modules - --> $DIR/restriction-resolution-errors.rs:54:24 - | -LL | pub mut(in m6::m5) i32, - | ^^^^^^ - error[E0433]: cannot find module or crate `a` in this scope --> $DIR/restriction-resolution-errors.rs:9:24 | @@ -101,6 +59,48 @@ error[E0577]: expected module, found enum `m7` LL | pub mut(in m7) i32, | ^^ not a module +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:10:24 + | +LL | pub mut(in ::std) i2: i32, + | ^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:11:24 + | +LL | pub mut(in self::c) i3: i32, + | ^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:12:24 + | +LL | pub mut(in super::d) i4: i32, + | ^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:32:16 + | +LL | mut(in crate::a) e1: i32, + | ^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:38:16 + | +LL | Tup(mut(in external) i32), + | ^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:52:24 + | +LL | pub mut(in crate::m2) i32, + | ^^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:54:24 + | +LL | pub mut(in m6::m5) i32, + | ^^^^^^ + error: aborting due to 14 previous errors Some errors have detailed explanations: E0433, E0577. From a9431675fdda9a7b9c4bdde7b0f6324ff779f78a Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 26 Apr 2026 14:17:19 -0700 Subject: [PATCH 3/8] tests/ui/tuple: add annotations for reference rules Also includes `HELP` checks for add-tuple-within-arguments.rs to make it clear that the referenced rules are being tested --- tests/ui/tuple/add-tuple-within-arguments.rs | 5 +++++ tests/ui/tuple/add-tuple-within-arguments.stderr | 8 ++++---- tests/ui/tuple/coercion-never.rs | 2 ++ tests/ui/tuple/coercion-slice.rs | 3 +++ tests/ui/tuple/coercion-slice.stderr | 2 +- tests/ui/tuple/index-float.rs | 2 ++ tests/ui/tuple/index-invalid.rs | 4 ++++ tests/ui/tuple/index-invalid.stderr | 6 +++--- .../never-to-any-coercion-in-collection-issue-100727.rs | 2 ++ tests/ui/tuple/one-tuple.rs | 4 ++++ tests/ui/tuple/tup.rs | 2 ++ tests/ui/tuple/tuple-arity-mismatch.rs | 3 ++- tests/ui/tuple/tuple-arity-mismatch.stderr | 8 ++++---- tests/ui/tuple/tuple-index-not-tuple.rs | 1 + tests/ui/tuple/tuple-index-not-tuple.stderr | 4 ++-- tests/ui/tuple/tuple-index-out-of-bounds.rs | 4 ++++ tests/ui/tuple/tuple-index-out-of-bounds.stderr | 4 ++-- tests/ui/tuple/tuple-index.rs | 5 +++++ 18 files changed, 52 insertions(+), 17 deletions(-) diff --git a/tests/ui/tuple/add-tuple-within-arguments.rs b/tests/ui/tuple/add-tuple-within-arguments.rs index 01b13b29fb4cc..bcdbc372d260e 100644 --- a/tests/ui/tuple/add-tuple-within-arguments.rs +++ b/tests/ui/tuple/add-tuple-within-arguments.rs @@ -1,3 +1,6 @@ +//@ reference: expr.tuple.unary-tuple-restriction +//@ reference: type.tuple.syntax +//@ reference: type.tuple.restriction fn foo(s: &str, a: (i32, i32), s2: &str) {} fn bar(s: &str, a: (&str,), s2: &str) {} @@ -5,6 +8,8 @@ fn bar(s: &str, a: (&str,), s2: &str) {} fn main() { foo("hi", 1, 2, "hi"); //~^ ERROR function takes 3 arguments but 4 arguments were supplied + //~| HELP: wrap these arguments in parentheses to construct a tuple bar("hi", "hi", "hi"); //~^ ERROR mismatched types + //~| HELP: use a trailing comma to create a tuple with one element } diff --git a/tests/ui/tuple/add-tuple-within-arguments.stderr b/tests/ui/tuple/add-tuple-within-arguments.stderr index 6849128eaddde..4caedf6b37674 100644 --- a/tests/ui/tuple/add-tuple-within-arguments.stderr +++ b/tests/ui/tuple/add-tuple-within-arguments.stderr @@ -1,11 +1,11 @@ error[E0061]: function takes 3 arguments but 4 arguments were supplied - --> $DIR/add-tuple-within-arguments.rs:6:5 + --> $DIR/add-tuple-within-arguments.rs:9:5 | LL | foo("hi", 1, 2, "hi"); | ^^^ | note: function defined here - --> $DIR/add-tuple-within-arguments.rs:1:4 + --> $DIR/add-tuple-within-arguments.rs:4:4 | LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} | ^^^ ------------- @@ -15,7 +15,7 @@ LL | foo("hi", (1, 2), "hi"); | + + error[E0308]: mismatched types - --> $DIR/add-tuple-within-arguments.rs:8:15 + --> $DIR/add-tuple-within-arguments.rs:12:15 | LL | bar("hi", "hi", "hi"); | --- ^^^^ expected `(&str,)`, found `&str` @@ -25,7 +25,7 @@ LL | bar("hi", "hi", "hi"); = note: expected tuple `(&str,)` found reference `&'static str` note: function defined here - --> $DIR/add-tuple-within-arguments.rs:3:4 + --> $DIR/add-tuple-within-arguments.rs:6:4 | LL | fn bar(s: &str, a: (&str,), s2: &str) {} | ^^^ ---------- diff --git a/tests/ui/tuple/coercion-never.rs b/tests/ui/tuple/coercion-never.rs index 3e4c4480c6f1f..17d49fce828fe 100644 --- a/tests/ui/tuple/coercion-never.rs +++ b/tests/ui/tuple/coercion-never.rs @@ -5,6 +5,8 @@ // See also coercion-slice.rs // //@ check-pass +//@ reference: coerce.site.tuple +//@ reference: coerce.types.never fn main() { let _: ((),) = (loop {},); diff --git a/tests/ui/tuple/coercion-slice.rs b/tests/ui/tuple/coercion-slice.rs index 250265f28ff08..2165b71b10b18 100644 --- a/tests/ui/tuple/coercion-slice.rs +++ b/tests/ui/tuple/coercion-slice.rs @@ -3,6 +3,9 @@ // unifying match arms, for example. // // See also: coercion-never.rs +//@ reference: coerce.site.tuple +//@ reference: coerce.types.unsize +//@ reference: coerce.unsize.slice fn main() { let _: (&[u8],) = (&[],); diff --git a/tests/ui/tuple/coercion-slice.stderr b/tests/ui/tuple/coercion-slice.stderr index a8ae7db4490cb..2996a16d5917f 100644 --- a/tests/ui/tuple/coercion-slice.stderr +++ b/tests/ui/tuple/coercion-slice.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/coercion-slice.rs:11:23 + --> $DIR/coercion-slice.rs:14:23 | LL | let _: (&[u8],) = y; | -------- ^ expected `(&[u8],)`, found `(&[_; 0],)` diff --git a/tests/ui/tuple/index-float.rs b/tests/ui/tuple/index-float.rs index 2faf71cb01d33..ee080361fd87d 100644 --- a/tests/ui/tuple/index-float.rs +++ b/tests/ui/tuple/index-float.rs @@ -1,4 +1,6 @@ //@ check-pass +//@ reference: expr.tuple-index.syntax +//@ reference: comments.normal.tokenization fn main() { let tuple = (((),),); diff --git a/tests/ui/tuple/index-invalid.rs b/tests/ui/tuple/index-invalid.rs index d36f6cfe3df7f..5a810977d8b2f 100644 --- a/tests/ui/tuple/index-invalid.rs +++ b/tests/ui/tuple/index-invalid.rs @@ -1,3 +1,7 @@ +//@ reference: expr.tuple-index.index-name-operand +//@ reference: expr.tuple-index.index-syntax +//@ reference: lex.token.literal.int.tuple-field.eq +//@ reference: type.tuple.field-name fn main() { let _ = (((),),).1.0; //~ ERROR no field `1` on type `(((),),)` diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr index fee09b7947c12..8e24f0b135b33 100644 --- a/tests/ui/tuple/index-invalid.stderr +++ b/tests/ui/tuple/index-invalid.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `1` on type `(((),),)` - --> $DIR/index-invalid.rs:2:22 + --> $DIR/index-invalid.rs:6:22 | LL | let _ = (((),),).1.0; | ^ unknown field @@ -7,7 +7,7 @@ LL | let _ = (((),),).1.0; = note: available field is: `0` error[E0609]: no field `1` on type `((),)` - --> $DIR/index-invalid.rs:4:24 + --> $DIR/index-invalid.rs:8:24 | LL | let _ = (((),),).0.1; | ^ unknown field @@ -15,7 +15,7 @@ LL | let _ = (((),),).0.1; = note: available field is: `0` error[E0609]: no field `000` on type `(((),),)` - --> $DIR/index-invalid.rs:6:22 + --> $DIR/index-invalid.rs:10:22 | LL | let _ = (((),),).000.000; | ^^^ unknown field diff --git a/tests/ui/tuple/never-to-any-coercion-in-collection-issue-100727.rs b/tests/ui/tuple/never-to-any-coercion-in-collection-issue-100727.rs index f44c486e0f50b..60ca67f1dd42a 100644 --- a/tests/ui/tuple/never-to-any-coercion-in-collection-issue-100727.rs +++ b/tests/ui/tuple/never-to-any-coercion-in-collection-issue-100727.rs @@ -3,6 +3,8 @@ //@ check-pass //@ edition: 2021 +//@ reference: coerce.site.tuple +//@ reference: coerce.types.never #![allow(unreachable_code)] diff --git a/tests/ui/tuple/one-tuple.rs b/tests/ui/tuple/one-tuple.rs index a9723029e5db5..a9dd0bf6c06c0 100644 --- a/tests/ui/tuple/one-tuple.rs +++ b/tests/ui/tuple/one-tuple.rs @@ -1,4 +1,8 @@ //@ run-pass +//@ reference: expr.tuple.unary-tuple-restriction +//@ reference: patterns.tuple.syntax +//@ reference: statement.let.syntax +//@ reference: type.tuple.restriction // Why one-tuples? Because macros. diff --git a/tests/ui/tuple/tup.rs b/tests/ui/tuple/tup.rs index 7bc316e7bd0bd..2564c863f7802 100644 --- a/tests/ui/tuple/tup.rs +++ b/tests/ui/tuple/tup.rs @@ -1,4 +1,6 @@ //@ run-pass +//@ reference: patterns.tuple.syntax +//@ reference: type.tuple.constructor #![allow(non_camel_case_types)] diff --git a/tests/ui/tuple/tuple-arity-mismatch.rs b/tests/ui/tuple/tuple-arity-mismatch.rs index 0b7c9deec9f38..406770704f143 100644 --- a/tests/ui/tuple/tuple-arity-mismatch.rs +++ b/tests/ui/tuple/tuple-arity-mismatch.rs @@ -1,5 +1,6 @@ // Issue #6155 - +//@ reference: expr.tuple.type +//@ reference: type.tuple.field-number //@ dont-require-annotations: NOTE fn first((value, _): (isize, f64)) -> isize { value } diff --git a/tests/ui/tuple/tuple-arity-mismatch.stderr b/tests/ui/tuple/tuple-arity-mismatch.stderr index 49dd98b6e7370..5ae056ff888bc 100644 --- a/tests/ui/tuple/tuple-arity-mismatch.stderr +++ b/tests/ui/tuple/tuple-arity-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/tuple-arity-mismatch.rs:8:20 + --> $DIR/tuple-arity-mismatch.rs:9:20 | LL | let y = first ((1,2.0,3)); | ----- ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements @@ -9,13 +9,13 @@ LL | let y = first ((1,2.0,3)); = note: expected tuple `(isize, f64)` found tuple `(isize, f64, {integer})` note: function defined here - --> $DIR/tuple-arity-mismatch.rs:5:4 + --> $DIR/tuple-arity-mismatch.rs:6:4 | LL | fn first((value, _): (isize, f64)) -> isize { value } | ^^^^^ ------------------------ error[E0308]: mismatched types - --> $DIR/tuple-arity-mismatch.rs:14:20 + --> $DIR/tuple-arity-mismatch.rs:15:20 | LL | let y = first ((1,)); | ----- ^^^^ expected a tuple with 2 elements, found one with 1 element @@ -25,7 +25,7 @@ LL | let y = first ((1,)); = note: expected tuple `(isize, f64)` found tuple `(isize,)` note: function defined here - --> $DIR/tuple-arity-mismatch.rs:5:4 + --> $DIR/tuple-arity-mismatch.rs:6:4 | LL | fn first((value, _): (isize, f64)) -> isize { value } | ^^^^^ ------------------------ diff --git a/tests/ui/tuple/tuple-index-not-tuple.rs b/tests/ui/tuple/tuple-index-not-tuple.rs index c478e1c67695d..e9bb3ddf6bb5a 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.rs +++ b/tests/ui/tuple/tuple-index-not-tuple.rs @@ -1,3 +1,4 @@ +//@ reference: expr.tuple-index.required-type struct Point { x: isize, y: isize } struct Empty; diff --git a/tests/ui/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr index faf9a313478df..c9912531d04cf 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.stderr +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `0` on type `Point` - --> $DIR/tuple-index-not-tuple.rs:6:12 + --> $DIR/tuple-index-not-tuple.rs:7:12 | LL | origin.0; | ^ unknown field @@ -11,7 +11,7 @@ LL + origin.x; | error[E0609]: no field `0` on type `Empty` - --> $DIR/tuple-index-not-tuple.rs:8:11 + --> $DIR/tuple-index-not-tuple.rs:9:11 | LL | Empty.0; | ^ unknown field diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.rs b/tests/ui/tuple/tuple-index-out-of-bounds.rs index c772c0daa18eb..bca100c98335a 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.rs +++ b/tests/ui/tuple/tuple-index-out-of-bounds.rs @@ -1,3 +1,7 @@ +//@ reference: expr.tuple-index.index-name-operand +//@ reference: type.struct.tuple +//@ reference: type.tuple.field-name +//@ reference: type.tuple.field-number struct Point(i32, i32); fn main() { diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr index 2be9d5631f781..001e04dd72dbc 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `2` on type `Point` - --> $DIR/tuple-index-out-of-bounds.rs:7:12 + --> $DIR/tuple-index-out-of-bounds.rs:11:12 | LL | origin.2; | ^ unknown field @@ -7,7 +7,7 @@ LL | origin.2; = note: available fields are: `0`, `1` error[E0609]: no field `2` on type `({integer}, {integer})` - --> $DIR/tuple-index-out-of-bounds.rs:12:11 + --> $DIR/tuple-index-out-of-bounds.rs:16:11 | LL | tuple.2; | ^ unknown field diff --git a/tests/ui/tuple/tuple-index.rs b/tests/ui/tuple/tuple-index.rs index c98eb42af4524..55cfb908d1bbf 100644 --- a/tests/ui/tuple/tuple-index.rs +++ b/tests/ui/tuple/tuple-index.rs @@ -1,4 +1,9 @@ //@ run-pass +//@ reference: expr.tuple.fields +//@ reference: expr.tuple-index.result +//@ reference: type.struct.tuple +//@ reference: type.tuple.access +//@ reference: type.tuple.field-name struct Point(isize, isize); From 8cbe25f87bee3c6da2afdfee2069f80f803df9e6 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 12 Aug 2026 09:24:21 +1000 Subject: [PATCH 4/8] Stabilize `Write for Cursor` Was already stable when using explicit types (e.g. `Vec`). `WriteThroughCursor` is still unstable/hidden. --- library/core/src/io/cursor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/io/cursor.rs b/library/core/src/io/cursor.rs index fe4def531a84a..704900f9c590e 100644 --- a/library/core/src/io/cursor.rs +++ b/library/core/src/io/cursor.rs @@ -486,6 +486,7 @@ pub trait WriteThroughCursor: Sized { } #[doc(hidden)] +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Cursor { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { From e9669493951c408a2ce92dcd58e561e6f5f87687 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Tue, 11 Aug 2026 18:09:36 +0900 Subject: [PATCH 5/8] Check that non-ancestor `mut` restrictions do not cause an ICE. --- .../stricter-of-non-ancestor-160873.rs | 17 +++++++++++++++++ .../stricter-of-non-ancestor-160873.stderr | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/ui/mut-restriction/stricter-of-non-ancestor-160873.rs create mode 100644 tests/ui/mut-restriction/stricter-of-non-ancestor-160873.stderr diff --git a/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.rs b/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.rs new file mode 100644 index 0000000000000..90eb9be3a22ed --- /dev/null +++ b/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.rs @@ -0,0 +1,17 @@ +//! Issue: +//! This test checks that restricting struct expressions with +//! non-ancestor mutability restrictions do not cause an ICE. + +//@ edition: 2018.. +#![feature(mut_restriction)] + +pub mod inner { + pub struct InnerS { + pub mut(self) x: i32, + pub mut(in std) y: i32, //~ ERROR field mutation can only be restricted to ancestor modules + } +} + +fn main() { + let _ = inner::InnerS { x: 0, y: 0 }; //~ ERROR `InnerS` cannot be constructed using a `struct` expression outside `crate::inner` +} diff --git a/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.stderr b/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.stderr new file mode 100644 index 0000000000000..e911e5f7923db --- /dev/null +++ b/tests/ui/mut-restriction/stricter-of-non-ancestor-160873.stderr @@ -0,0 +1,17 @@ +error: field mutation can only be restricted to ancestor modules + --> $DIR/stricter-of-non-ancestor-160873.rs:11:20 + | +LL | pub mut(in std) y: i32, + | ^^^ + +error: `InnerS` cannot be constructed using a `struct` expression outside `crate::inner` + --> $DIR/stricter-of-non-ancestor-160873.rs:16:13 + | +LL | pub mut(self) x: i32, + | --------- field restricted here +... +LL | let _ = inner::InnerS { x: 0, y: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 207b77452bcd5f94fb16cd6c9689372dd53653de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Aug 2026 10:32:30 +0200 Subject: [PATCH 6/8] Normalize relative paths starting with a dot in CLI matching --- src/bootstrap/src/core/builder/cli_paths.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 5efbea64463fe..8f65382a8c167 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -83,14 +83,30 @@ pub(crate) fn match_paths_to_steps_and_run( // repository root, to match the paths registered by command-line steps. // // E.g. `/home/ferris/rust/tests/ui/asm/cfg.rs` => `tests/ui/asm/cfg.rs` + // + // It is also possible that someone passed a relative path starting with . or .. + // In that case, we have to remove that path prefix. let mut paths = paths .iter() .map(|path| { + // Here we "launder" the path through builder.src, to normalize relative path prefixes + // so ./tests/foo becomes just tests/foo + let path = if path.is_relative() { + builder + .src + .join(path) + .strip_prefix(&builder.src) + .expect("Cannot strip src path prefix") + .to_path_buf() + } else { + path.to_path_buf() + }; + if path.is_absolute() && path.exists() && let Ok(relative) = path.strip_prefix(&builder.src) { - relative + relative.to_path_buf() } else { path } From 7c78c1843156a6df1de90ff8f3ae678577c94d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Aug 2026 10:33:03 +0200 Subject: [PATCH 7/8] Improve error message for absolute paths --- src/bootstrap/src/core/builder/cli_paths.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 8f65382a8c167..51304bcd140b6 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -117,7 +117,9 @@ pub(crate) fn match_paths_to_steps_and_run( // If any absolute paths couldn't be made relative, stop now and report them. let bad_abs_paths = paths.iter().filter(|path| path.is_absolute()).collect::>(); if !bad_abs_paths.is_empty() { - eprintln!("ERROR: failed to resolve absolute paths: {bad_abs_paths:#?}"); + eprintln!( + "ERROR: the following paths do not exist on disk or point outside the source directory: {bad_abs_paths:#?}" + ); crate::exit!(1); } From 92c6c0656e076c07db78f21cceceab30b4a6ae0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Aug 2026 10:34:12 +0200 Subject: [PATCH 8/8] Add CLI snapshot test for a relative path starting with a dot --- .../cli_paths/snapshots/x_test_tests_ui_dot_prefix.snap | 7 +++++++ src/bootstrap/src/core/builder/cli_paths/tests.rs | 1 + 2 files changed, 8 insertions(+) create mode 100644 src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_ui_dot_prefix.snap diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_ui_dot_prefix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_ui_dot_prefix.snap new file mode 100644 index 0000000000000..cba08e4724819 --- /dev/null +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_ui_dot_prefix.snap @@ -0,0 +1,7 @@ +--- +source: src/bootstrap/src/core/builder/cli_paths/tests.rs +expression: test ./tests/ui +--- +[Test] test::Ui + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/ui) diff --git a/src/bootstrap/src/core/builder/cli_paths/tests.rs b/src/bootstrap/src/core/builder/cli_paths/tests.rs index f075e7408e7c0..b4dad0013b2de 100644 --- a/src/bootstrap/src/core/builder/cli_paths/tests.rs +++ b/src/bootstrap/src/core/builder/cli_paths/tests.rs @@ -199,6 +199,7 @@ declare_tests!( (x_test_tests, "test tests"), (x_test_tests_skip_coverage, "test tests --skip=coverage"), (x_test_tests_ui, "test tests/ui"), + (x_test_tests_ui_dot_prefix, "test ./tests/ui"), (x_test_tidy, "test tidy"), (x_test_tidyselftest, "test tidyselftest"), (x_test_ui, "test ui"),