From 4a5a7153e28c70ba18810e7d3f3b5f631cbbb095 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Nov 2026 13:23:55 +1100 Subject: [PATCH 01/15] Avoid building `Canonicalizer` unnecessarily in `canonicalize_response` Currently we build it even when the `NEEDS_CANONICAL` test fails. --- .../src/canonical/canonicalizer.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 6b159074493f9..2de01ad02de8a 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -86,17 +86,17 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { max_input_universe: ty::UniverseIndex, value: T, ) -> ty::Canonical { + if !value.has_type_flags(NEEDS_CANONICAL) { + let var_kinds = delegate.cx().mk_canonical_var_kinds(&[]); + return Canonical { max_universe: ty::UniverseIndex::ROOT, var_kinds, value }; + } + let mut canonicalizer = Canonicalizer::new(delegate, CanonicalizeMode::Response { max_input_universe }); - let value = if value.has_type_flags(NEEDS_CANONICAL) { - value.fold_with(&mut canonicalizer) - } else { - value - }; + let value = value.fold_with(&mut canonicalizer); debug_assert!(!value.has_infer(), "unexpected infer in {value:?}"); debug_assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); let (max_universe, var_kinds) = canonicalizer.finalize(); - Canonical { max_universe, var_kinds, value } } From 79195a2503138c8feae19b24d84fdbc0dc3192f0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Nov 2026 13:42:50 +1100 Subject: [PATCH 02/15] Inline and remove `canonicalize_param_env` It has a single call site. This will enable an optimization in the next commit. --- .../src/canonical/canonicalizer.rs | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 2de01ad02de8a..47412939f2554 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -100,20 +100,19 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { Canonical { max_universe, var_kinds, value } } - // The return value is the canonicalized `param_env`, plus a canonicalizer suitable for - // canonicalizing the rest of the input. (For efficiency, and when appropriate, the returned - // canonicalizer will be the same one used on `param_env`, with suitable modifications.) - fn canonicalize_param_env(delegate: &'a D, param_env: I::ParamEnv) -> (I::ParamEnv, Self) { - if !param_env.has_type_flags(NEEDS_CANONICAL) { - let rest_canonicalizer = Canonicalizer::new( - delegate, - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { - param_env_var_kinds: None, - }), - ); - - return (param_env, rest_canonicalizer); - } + /// When canonicalizing query inputs, we keep `'static` in the `param_env` + /// but erase it everywhere else. We generally don't want to depend on region + /// identity, so while it should not matter whether `'static` is kept in the + /// value or opaque type storage as well, this prevents us from accidentally + /// relying on it in the future. + /// + /// We want to keep the option of canonicalizing `'static` to an existential + /// variable in the future by changing the way we detect global where-bounds. + pub(super) fn canonicalize_input>( + delegate: &'a D, + input: QueryInput, + ) -> (Vec, ty::Canonical>) { + let param_env = input.goal.param_env; // Do the `env` canonicalization, and then convert the canonicalizer to `rest` form for // subsequent use, also returning the optionally interned (i.e., uniquely identified) @@ -151,14 +150,27 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { (param_env, rest_canonicalizer, param_env_var_kinds) }; - // Check whether we can use the global cache for this param_env. As we only use + // First canonicalize the `param_env` while keeping `'static`. This produces a + // canonicalizer that can canonicalize the rest of the input without keeping `'static`. + // + // For this, we first check if `param_env` even needs canonicalization. If it does, then + // we check whether we can use the global cache for this param_env. As we only use // the `param_env` itself as the cache key, considering any additional information // during its canonicalization would be incorrect. We always canonicalize region // inference variables in a separate universe, so these are fine. However, we do // track the universe of type and const inference variables so these must not be // globally cached. We don't rely on any additional information when canonicalizing // placeholders. - if !param_env.has_non_region_infer() { + let (param_env, mut rest_canonicalizer) = if !param_env.has_type_flags(NEEDS_CANONICAL) { + let rest_canonicalizer = Canonicalizer::new( + delegate, + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: None, + }), + ); + + (param_env, rest_canonicalizer) + } else if !param_env.has_non_region_infer() { delegate.cx().with_canonical_param_env_cache(|cache| match cache.0.entry(param_env) { Entry::Vacant(e) => { // Cache miss. Do `env` canonicalization and get `rest_canonicalizer`, and @@ -201,25 +213,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // Do `env` canonicalization and get `rest_canonicalizer`. let (param_env, rest_canonicalizer, _) = do_env_and_make_rest(false); (param_env, rest_canonicalizer) - } - } - - /// When canonicalizing query inputs, we keep `'static` in the `param_env` - /// but erase it everywhere else. We generally don't want to depend on region - /// identity, so while it should not matter whether `'static` is kept in the - /// value or opaque type storage as well, this prevents us from accidentally - /// relying on it in the future. - /// - /// We want to keep the option of canonicalizing `'static` to an existential - /// variable in the future by changing the way we detect global where-bounds. - pub(super) fn canonicalize_input>( - delegate: &'a D, - input: QueryInput, - ) -> (Vec, ty::Canonical>) { - // First canonicalize the `param_env` while keeping `'static`. This produces a - // canonicalizer that can canonicalize the rest of the input without keeping `'static`. - let (param_env, mut rest_canonicalizer) = - Self::canonicalize_param_env(delegate, input.goal.param_env); + }; let predicate = input.goal.predicate; let predicate = predicate.fold_with(&mut rest_canonicalizer); From ca1554c763639edf970ea34b40709de25fddbaca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Nov 2026 14:37:07 +1100 Subject: [PATCH 03/15] Early return in `canonicalize_input` Do a `NEEDS_CANONICAL` check on the entire input. We already have such checks on the relevant parts, but this lets us entirely avoid building a `Canonicalizer` when the check fails. --- .../rustc_next_trait_solver/src/canonical/canonicalizer.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 47412939f2554..38af80b472d1c 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -112,6 +112,12 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { delegate: &'a D, input: QueryInput, ) -> (Vec, ty::Canonical>) { + if !input.has_type_flags(NEEDS_CANONICAL) { + let max_universe = ty::UniverseIndex::ROOT; + let var_kinds = delegate.cx().mk_canonical_var_kinds(&[]); + return (vec![], Canonical { max_universe, var_kinds, value: input }); + } + let param_env = input.goal.param_env; // Do the `env` canonicalization, and then convert the canonicalizer to `rest` form for From 942135b7274e2f0f264a0c741c6bc3faf316e4e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Nov 2026 15:54:49 +1100 Subject: [PATCH 04/15] Remove bool arg from `do_env_and_make_rest` It causes it to intern or not intern. Instead we can just let the call site that passes in `true` do its own interning. --- .../src/canonical/canonicalizer.rs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 38af80b472d1c..c85ca9cfd123f 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -69,7 +69,6 @@ enum CanonicalizeMode { pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner> { delegate: &'a D, - // Immutable field. canonicalize_mode: CanonicalizeMode, // Mutable fields. @@ -121,9 +120,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let param_env = input.goal.param_env; // Do the `env` canonicalization, and then convert the canonicalizer to `rest` form for - // subsequent use, also returning the optionally interned (i.e., uniquely identified) - // canonicalized variable kind list in case cache is used, so it can also be cached. - let do_env_and_make_rest = |intern_var_kinds: bool| { + // subsequent use. + let do_env_and_make_rest = || { let mut env_canonicalizer = Canonicalizer::new( delegate, CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv), @@ -143,17 +141,15 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // // We clear the cache rather than deleting it or replacing it with an empty cache. This // lets the allocated capacity be reused later. - let param_env_var_kinds = intern_var_kinds - .then(|| delegate.cx().mk_canonical_var_kinds(&env_canonicalizer.state.var_kinds)); let mut rest_canonicalizer = Canonicalizer { canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { - param_env_var_kinds, + param_env_var_kinds: None, }), ..env_canonicalizer }; rest_canonicalizer.state.cache.clear(); - (param_env, rest_canonicalizer, param_env_var_kinds) + (param_env, rest_canonicalizer) }; // First canonicalize the `param_env` while keeping `'static`. This produces a @@ -179,13 +175,20 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } else if !param_env.has_non_region_infer() { delegate.cx().with_canonical_param_env_cache(|cache| match cache.0.entry(param_env) { Entry::Vacant(e) => { - // Cache miss. Do `env` canonicalization and get `rest_canonicalizer`, and - // fill in the cache entry. - let (param_env, rest_canonicalizer, var_kinds) = do_env_and_make_rest(true); + // Cache miss. Do `env` canonicalization and get `rest_canonicalizer`, make the + // interned (i.e., uniquely identified) canonicalized variable kind list so it + // can also be cached, and fill in the cache entry. + let (param_env, mut rest_canonicalizer) = do_env_and_make_rest(); + let var_kinds = + delegate.cx().mk_canonical_var_kinds(&rest_canonicalizer.state.var_kinds); + rest_canonicalizer.canonicalize_mode = + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: Some(var_kinds), + }); e.insert(CanonicalParamEnvCacheEntry { param_env, variables: rest_canonicalizer.state.variables.clone(), - var_kinds: var_kinds.unwrap(), + var_kinds, // SAFETY: The iterated elements go straight back into a hashmap. #[allow(rustc::potential_query_instability)] variable_lookup_table: rest_canonicalizer @@ -217,7 +220,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }) } else { // Do `env` canonicalization and get `rest_canonicalizer`. - let (param_env, rest_canonicalizer, _) = do_env_and_make_rest(false); + let (param_env, rest_canonicalizer) = do_env_and_make_rest(); (param_env, rest_canonicalizer) }; From d7064be5882ede683de881385048939f100a15d3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Nov 2026 16:32:38 +1100 Subject: [PATCH 05/15] Factor out repetitive code --- .../src/canonical/canonicalizer.rs | 90 ++++++++----------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index c85ca9cfd123f..9780bf8bbadd2 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -4,8 +4,9 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, CanonicalizerState, - Const, Flags, InferCtxtLike, Interner, PlaceholderConst, PlaceholderType, PredicateProxy, - Region, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Const, Flags, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, + PredicateProxy, Region, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, }; use crate::delegate::SolverDelegate; @@ -383,21 +384,11 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } }, ty::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_ty(), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_ty(), CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, ty::Bool @@ -434,6 +425,30 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { Ty::new_canonical_bound(self.cx(), var) } + + #[inline] + fn new_placeholder_ty(&self) -> CanonicalVarKind { + CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( + ty::UniverseIndex::ROOT, + self.state.variables.len().into(), + )) + } + + #[inline] + fn new_placeholder_region(&self) -> CanonicalVarKind { + CanonicalVarKind::PlaceholderRegion(PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.state.variables.len().into(), + )) + } + + #[inline] + fn new_placeholder_const(&self) -> CanonicalVarKind { + CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( + ty::UniverseIndex::ROOT, + self.state.variables.len().into(), + )) + } } impl, I: Interner> TypeFolder for Canonicalizer<'_, D, I> { @@ -454,10 +469,7 @@ impl, I: Interner> TypeFolder for Canonicaliz // when checking whether a `ParamEnv` candidate is global. ty::ReStatic => match self.canonicalize_mode { CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { .. }) => { - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) + self.new_placeholder_region() } CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) | CanonicalizeMode::Response { .. } => return r, @@ -471,34 +483,19 @@ impl, I: Interner> TypeFolder for Canonicaliz // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_region(), CanonicalizeMode::Response { .. } => return r, }, ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_region(), CanonicalizeMode::Response { .. } => { panic!("unexpected region in response: {r:?}") } }, ty::RePlaceholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_region(), CanonicalizeMode::Response { max_input_universe } => { // If we have a placeholder region inside of a query, it must be from // a new universe, unless from the root universe, which is used for @@ -519,12 +516,7 @@ impl, I: Interner> TypeFolder for Canonicaliz "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_region(), CanonicalizeMode::Response { .. } => { CanonicalVarKind::Region(self.delegate.universe_of_region(vid).unwrap()) } @@ -576,23 +568,13 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => unimplemented!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_const(), CanonicalizeMode::Response { .. } => { CanonicalVarKind::PlaceholderConst(placeholder) } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => { - CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( - ty::UniverseIndex::ROOT, - self.state.variables.len().into(), - )) - } + CanonicalizeMode::Input(_) => self.new_placeholder_const(), CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, // FIXME: See comment above -- we could fold the region separately or something. From e6d76cd4eae4f0621e50b6d6c1a9f2a426b5bd0a Mon Sep 17 00:00:00 2001 From: Yassa-hue Date: Tue, 10 Nov 2026 19:36:31 +0200 Subject: [PATCH 06/15] Remove unnecessary mut from HirIdValidator::check_nested_id --- compiler/rustc_passes/src/hir_id_validator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index c0a8ec210769e..8585b9ca8a8db 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -83,7 +83,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } } - fn check_nested_id(&mut self, id: LocalDefId) { + fn check_nested_id(&self, id: LocalDefId) { let Some(owner) = self.owner else { return }; let def_parent = self.tcx.local_parent(id); let def_parent_hir_id = self.tcx.local_def_id_to_hir_id(def_parent); From 5f413f0ca50a06ff6fdf71c219eb7d55a0190ff6 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 10 Nov 2026 21:34:22 +0100 Subject: [PATCH 07/15] std: map more errno values to ErrorKind on Hermit `decode_error_kind` for Hermit only knew 15 errno values and returned `Uncategorized` for all others. For example, removing a non-empty directory failed with `Uncategorized` instead of `DirectoryNotEmpty`. Hermit uses the Linux errno numbering, so use the same mapping as on Unix. `hermit-abi` defines no `ENOTSUP` and `EWOULDBLOCK` is an alias of `EAGAIN`, so both need no separate arm. --- library/std/src/sys/io/error/hermit.rs | 58 +++++++++++++++++++------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/library/std/src/sys/io/error/hermit.rs b/library/std/src/sys/io/error/hermit.rs index 28735c4c8275c..dee57e62ecf31 100644 --- a/library/std/src/sys/io/error/hermit.rs +++ b/library/std/src/sys/io/error/hermit.rs @@ -10,23 +10,49 @@ pub fn is_interrupted(errno: i32) -> bool { } pub fn decode_error_kind(errno: i32) -> io::ErrorKind { + use hermit_abi::errno::*; + use io::ErrorKind::*; match errno { - hermit_abi::errno::EACCES => io::ErrorKind::PermissionDenied, - hermit_abi::errno::EADDRINUSE => io::ErrorKind::AddrInUse, - hermit_abi::errno::EADDRNOTAVAIL => io::ErrorKind::AddrNotAvailable, - hermit_abi::errno::EAGAIN => io::ErrorKind::WouldBlock, - hermit_abi::errno::ECONNABORTED => io::ErrorKind::ConnectionAborted, - hermit_abi::errno::ECONNREFUSED => io::ErrorKind::ConnectionRefused, - hermit_abi::errno::ECONNRESET => io::ErrorKind::ConnectionReset, - hermit_abi::errno::EEXIST => io::ErrorKind::AlreadyExists, - hermit_abi::errno::EINTR => io::ErrorKind::Interrupted, - hermit_abi::errno::EINVAL => io::ErrorKind::InvalidInput, - hermit_abi::errno::ENOENT => io::ErrorKind::NotFound, - hermit_abi::errno::ENOTCONN => io::ErrorKind::NotConnected, - hermit_abi::errno::EPERM => io::ErrorKind::PermissionDenied, - hermit_abi::errno::EPIPE => io::ErrorKind::BrokenPipe, - hermit_abi::errno::ETIMEDOUT => io::ErrorKind::TimedOut, - _ => io::ErrorKind::Uncategorized, + E2BIG => ArgumentListTooLong, + EADDRINUSE => AddrInUse, + EADDRNOTAVAIL => AddrNotAvailable, + EBUSY => ResourceBusy, + ECONNABORTED => ConnectionAborted, + ECONNREFUSED => ConnectionRefused, + ECONNRESET => ConnectionReset, + EDEADLK => Deadlock, + EDQUOT => QuotaExceeded, + EEXIST => AlreadyExists, + EFBIG => FileTooLarge, + EHOSTUNREACH => HostUnreachable, + EINTR => Interrupted, + EINVAL => InvalidInput, + EISDIR => IsADirectory, + ELOOP => FilesystemLoop, + ENOENT => NotFound, + ENOMEM => OutOfMemory, + ENOSPC => StorageFull, + EMLINK => TooManyLinks, + ENAMETOOLONG => InvalidFilename, + ENETDOWN => NetworkDown, + ENETUNREACH => NetworkUnreachable, + ENOTCONN => NotConnected, + ENOTDIR => NotADirectory, + ENOTEMPTY => DirectoryNotEmpty, + EPIPE => BrokenPipe, + EROFS => ReadOnlyFilesystem, + ESPIPE => NotSeekable, + ESTALE => StaleNetworkFileHandle, + ETIMEDOUT => TimedOut, + ETXTBSY => ExecutableFileBusy, + EXDEV => CrossesDevices, + EINPROGRESS => InProgress, + EMFILE | ENFILE => TooManyOpenFiles, + EIO => InputOutputError, + EACCES | EPERM => PermissionDenied, + ENOSYS | EOPNOTSUPP => Unsupported, + EAGAIN => WouldBlock, + _ => Uncategorized, } } From e982cc300b862e321700606bae2fbea81ffb1f26 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Oct 2026 10:31:31 +0100 Subject: [PATCH 08/15] std Miri testing: use skip_unsupported_miri_tests to control when tests should be skipped in Miri due to missing shims --- library/std/Cargo.toml | 2 ++ library/std/src/fs/tests.rs | 3 ++- library/std/src/net/socket_addr/tests.rs | 2 ++ library/std/src/net/tcp/tests.rs | 4 ++++ library/std/src/net/tests.rs | 1 + library/std/src/net/udp/tests.rs | 2 ++ library/std/src/os/darwin/fs/dirs.rs | 1 + library/std/src/os/fd/owned.rs | 2 +- library/std/src/os/net/linux_ext/tests.rs | 2 ++ library/std/src/os/unix/fs/tests.rs | 2 ++ library/std/src/os/unix/net/tests.rs | 2 ++ library/std/src/os/windows/fs/dirs.rs | 1 + library/std/src/process/tests.rs | 2 ++ library/std/src/sys/fs/windows/tests.rs | 2 ++ .../src/sys/net/connection/socket/tests.rs | 2 ++ library/std/src/sys/pal/unix/conf/tests.rs | 1 + .../src/sys/platform_version/darwin/tests.rs | 2 ++ .../std/src/sys/process/unix/common/tests.rs | 2 ++ .../std/src/sys/process/unix/pidfd/tests.rs | 2 ++ .../std/src/sys/process/unix/unix/tests.rs | 2 ++ library/std/src/sys/process/windows/tests.rs | 2 ++ library/std/tests/create_dir_all_bare.rs | 2 +- library/std/tests/env_modify.rs | 5 ++-- library/std/tests/pipe_subprocess.rs | 2 +- library/std/tests/process_spawning.rs | 2 +- library/std/tests/switch-stdout.rs | 2 +- library/std/tests/thread.rs | 2 +- library/std/tests/thread_local/tests.rs | 2 +- library/std/tests/win_delete_self.rs | 2 +- library/std/tests/windows_unix_socket.rs | 2 +- src/bootstrap/mk/Makefile.in | 23 +++++++------------ .../miri/src/shims/windows/foreign_items.rs | 8 +++++++ src/tools/miri/tests/pass/shims/io.rs | 3 ++- 33 files changed, 68 insertions(+), 28 deletions(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2f21b78352abb..6248f3c79fb57 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -166,6 +166,8 @@ check-cfg = [ 'cfg(target_has_reliable_f16_math)', 'cfg(target_has_reliable_f128)', 'cfg(target_has_reliable_f128_math)', + # Controlling which tests we run in Miri. + 'cfg(skip_unsupported_miri_tests)', ] [lints.cargo] diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index c06154ecf0b6b..46ed6597c9b06 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // fs API support in Miri is quite spotty + use rand::RngCore; use super::Dir; @@ -2567,7 +2569,6 @@ fn test_eq_windows_file_type() { /// Regression test for https://github.com/rust-lang/rust/issues/50619. #[test] #[cfg(target_os = "linux")] -#[cfg_attr(miri, ignore)] // Cannot spawn processes on Miri fn test_read_dir_infinite_loop() { use crate::io::ErrorKind; use crate::process::Command; diff --git a/library/std/src/net/socket_addr/tests.rs b/library/std/src/net/socket_addr/tests.rs index 2f3e3add5c22d..3eedb86b1650c 100644 --- a/library/std/src/net/socket_addr/tests.rs +++ b/library/std/src/net/socket_addr/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(all(windows, skip_unsupported_miri_tests)))] // Miri has no net support on Windows + use crate::net::tests::{sa4, sa6, tsa}; use crate::net::*; diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 9aeddff864918..de62bd66c5c74 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(all(windows, skip_unsupported_miri_tests)))] // Miri has no net support on Windows + use rand::Rng; use crate::io::prelude::*; @@ -898,6 +900,7 @@ fn ttl() { #[test] #[cfg_attr(target_env = "sgx", ignore)] #[cfg(any(target_family = "unix", target_os = "windows"))] +#[cfg(not(skip_unsupported_miri_tests))] // socket flag not supported by Miri fn hop_limit() { let hlim = 100; @@ -979,6 +982,7 @@ fn connect_timeout_valid() { // macOS with `EINVAL`; `write_all` should now transfer it via short sends. #[test] #[cfg(all(target_pointer_width = "64", unix))] +#[cfg(not(skip_unsupported_miri_tests))] // read-only mmap not supported by Miri fn write_buffer_larger_than_c_int_max() { const LEN: usize = crate::ffi::c_int::MAX as usize + 1; diff --git a/library/std/src/net/tests.rs b/library/std/src/net/tests.rs index 213c9a5a3e3a1..f07a7f6e8894a 100644 --- a/library/std/src/net/tests.rs +++ b/library/std/src/net/tests.rs @@ -88,6 +88,7 @@ impl Drop for ZeroedMmap { } #[test] +#[cfg(not(all(windows, skip_unsupported_miri_tests)))] // Miri has no net support on Windows fn hostname_smoketest() { // Just a smoke test to ensure it can be called. let name = crate::net::hostname(); diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 6296e07044c55..f5dd0464f430b 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // UDP sockets are not supported in Miri + use crate::io::ErrorKind; use crate::net::tests::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid}; use crate::net::*; diff --git a/library/std/src/os/darwin/fs/dirs.rs b/library/std/src/os/darwin/fs/dirs.rs index 6aaa910981b0b..d5d1449d9973b 100644 --- a/library/std/src/os/darwin/fs/dirs.rs +++ b/library/std/src/os/darwin/fs/dirs.rs @@ -291,6 +291,7 @@ mod sys { #[cfg(test)] #[cfg(target_vendor = "apple")] +#[cfg(not(skip_unsupported_miri_tests))] // macOS sysdir APIs are not supported in Miri mod tests { use super::*; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index fa775a9373427..594de872a17de 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -94,7 +94,7 @@ impl BorrowedFd<'_> { /// Converts a `BorrowedFd` into a reference to a file-like type. /// - #[cfg_attr(all(unix, not(miri)), doc = "```")] + #[cfg_attr(unix, doc = "```")] #[cfg_attr(not(unix), doc = "```ignore (needs unix)")] /// # #![feature(fd_view)] /// # use std::fs::File; diff --git a/library/std/src/os/net/linux_ext/tests.rs b/library/std/src/os/net/linux_ext/tests.rs index a63524e63b6d8..e76cc1e44d7f5 100644 --- a/library/std/src/os/net/linux_ext/tests.rs +++ b/library/std/src/os/net/linux_ext/tests.rs @@ -1,4 +1,5 @@ #[test] +#[cfg(not(skip_unsupported_miri_tests))] // socket flag not supported by Miri fn quickack() { use crate::net::tests::LOCALHOST_IP4; use crate::net::{TcpListener, TcpStream}; @@ -28,6 +29,7 @@ fn quickack() { #[test] #[cfg(target_os = "linux")] +#[cfg(not(skip_unsupported_miri_tests))] // socket flag not supported by Miri fn deferaccept() { use crate::net::tests::LOCALHOST_IP4; use crate::net::{TcpListener, TcpStream}; diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs index 52e0fe940a81f..3b7b0ef0ce0ba 100644 --- a/library/std/src/os/unix/fs/tests.rs +++ b/library/std/src/os/unix/fs/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // fs API support in Miri is quite spotty + use super::*; #[test] diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 4014767461389..d310aa81db3e5 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // Unix domain sockets are not supported in Miri + use super::*; use crate::io::prelude::*; use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; diff --git a/library/std/src/os/windows/fs/dirs.rs b/library/std/src/os/windows/fs/dirs.rs index 52710375e6eb2..56cf055d3299b 100644 --- a/library/std/src/os/windows/fs/dirs.rs +++ b/library/std/src/os/windows/fs/dirs.rs @@ -287,6 +287,7 @@ mod sys { } #[cfg(test)] +#[cfg(not(skip_unsupported_miri_tests))] // Windows known directory APIs are not supported in Miri mod tests { use super::*; diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index e31cb002c0265..ecb42906e8ca8 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // process spawning is not supported in Miri + use super::{Command, Output, Stdio}; use crate::io::prelude::*; use crate::io::{BorrowedBuf, ErrorKind}; diff --git a/library/std/src/sys/fs/windows/tests.rs b/library/std/src/sys/fs/windows/tests.rs index b53dfddecf627..dc57598d8984d 100644 --- a/library/std/src/sys/fs/windows/tests.rs +++ b/library/std/src/sys/fs/windows/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // Windows fs APIs are not supported in Miri + use super::{get_path_canonical, get_path_fallback}; use crate::env; use crate::fs::{File, canonicalize}; diff --git a/library/std/src/sys/net/connection/socket/tests.rs b/library/std/src/sys/net/connection/socket/tests.rs index cc072420b754b..d1c001d9d424d 100644 --- a/library/std/src/sys/net/connection/socket/tests.rs +++ b/library/std/src/sys/net/connection/socket/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(all(windows, skip_unsupported_miri_tests)))] // Miri has no net support on Windows + use super::*; use crate::collections::HashMap; diff --git a/library/std/src/sys/pal/unix/conf/tests.rs b/library/std/src/sys/pal/unix/conf/tests.rs index a84086037ce0b..76aed1c6e608b 100644 --- a/library/std/src/sys/pal/unix/conf/tests.rs +++ b/library/std/src/sys/pal/unix/conf/tests.rs @@ -26,6 +26,7 @@ fn test_parse_glibc_version() { // logic is correct. #[test] #[cfg(target_vendor = "apple")] +#[cfg(not(skip_unsupported_miri_tests))] // macOS conf API is not supported in Miri fn test_confstr() { for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { diff --git a/library/std/src/sys/platform_version/darwin/tests.rs b/library/std/src/sys/platform_version/darwin/tests.rs index 17b2cc18ec096..24895c73bf3d6 100644 --- a/library/std/src/sys/platform_version/darwin/tests.rs +++ b/library/std/src/sys/platform_version/darwin/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // macOS version APIs are not supported in Miri + use super::public_extern::*; use super::*; use crate::process::Command; diff --git a/library/std/src/sys/process/unix/common/tests.rs b/library/std/src/sys/process/unix/common/tests.rs index eacb4d2d43122..c652488d0570b 100644 --- a/library/std/src/sys/process/unix/common/tests.rs +++ b/library/std/src/sys/process/unix/common/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // process spawning is not supported in Miri + use super::*; use crate::ffi::OsStr; use crate::sys::{cvt, cvt_nz}; diff --git a/library/std/src/sys/process/unix/pidfd/tests.rs b/library/std/src/sys/process/unix/pidfd/tests.rs index 4cc2368c25a22..97578eea370f3 100644 --- a/library/std/src/sys/process/unix/pidfd/tests.rs +++ b/library/std/src/sys/process/unix/pidfd/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // pidfd is not supported in Miri + use super::PidFd as InternalPidFd; use crate::assert_matches; use crate::os::fd::AsRawFd; diff --git a/library/std/src/sys/process/unix/unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs index e360b61851b2e..22b65bae4a6dc 100644 --- a/library/std/src/sys/process/unix/unix/tests.rs +++ b/library/std/src/sys/process/unix/unix/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // process spawning is not supported in Miri + use crate::os::unix::process::{CommandExt, ExitStatusExt}; use crate::panic::catch_unwind; use crate::process::Command; diff --git a/library/std/src/sys/process/windows/tests.rs b/library/std/src/sys/process/windows/tests.rs index bc5e0d5c7fc97..22b5334c76472 100644 --- a/library/std/src/sys/process/windows/tests.rs +++ b/library/std/src/sys/process/windows/tests.rs @@ -1,3 +1,5 @@ +#![cfg(not(skip_unsupported_miri_tests))] // process spawning is not supported in Miri + use super::child_pipe::{Pipes, child_pipe}; use super::{Arg, make_command_line}; use crate::ffi::{OsStr, OsString}; diff --git a/library/std/tests/create_dir_all_bare.rs b/library/std/tests/create_dir_all_bare.rs index 30f800c5aa2e6..c3e91b8c613c8 100644 --- a/library/std/tests/create_dir_all_bare.rs +++ b/library/std/tests/create_dir_all_bare.rs @@ -31,7 +31,7 @@ impl Drop for CurrentDir { } #[test] -#[cfg_attr(all(miri, windows), ignore)] // File system access on Windows not supported by Miri +#[cfg_attr(all(windows, skip_unsupported_miri_tests), ignore)] // File system access on Windows not supported by Miri fn create_dir_all_bare() { let tmpdir = common::tmpdir(); CurrentDir::with(tmpdir.path(), || { diff --git a/library/std/tests/env_modify.rs b/library/std/tests/env_modify.rs index 71d15bc1c47c0..9eefe0cc25126 100644 --- a/library/std/tests/env_modify.rs +++ b/library/std/tests/env_modify.rs @@ -179,8 +179,9 @@ fn env_home_dir() { } } -#[test] // miri shouldn't detect any data race in this fn -#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)] +// This is primarily a Miri test (ensuring there are no data races), but can also run natively. +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_env_get_set_multithreaded() { let getter = thread::spawn(|| { for _ in 0..100 { diff --git a/library/std/tests/pipe_subprocess.rs b/library/std/tests/pipe_subprocess.rs index c14db690224db..35ad327ef4f48 100644 --- a/library/std/tests/pipe_subprocess.rs +++ b/library/std/tests/pipe_subprocess.rs @@ -1,7 +1,7 @@ fn main() { // No `Command` on Miri, emscripten or L4Re #[cfg(all( - not(miri), + not(skip_unsupported_miri_tests), any(unix, windows), not(any(target_os = "emscripten", target_os = "l4re")) ))] diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs index b7a9a1077696b..e634ee5155eab 100644 --- a/library/std/tests/process_spawning.rs +++ b/library/std/tests/process_spawning.rs @@ -6,7 +6,7 @@ mod common; #[test] // Process spawning not supported by Miri, Emscripten and wasi -#[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)] +#[cfg_attr(any(skip_unsupported_miri_tests, target_os = "emscripten", target_os = "wasi"), ignore)] #[cfg_attr( any(target_os = "tvos", target_os = "watchos", target_os = "l4re"), ignore = "fork is prohibited" diff --git a/library/std/tests/switch-stdout.rs b/library/std/tests/switch-stdout.rs index 91fe0200f6cae..829909bc364d0 100644 --- a/library/std/tests/switch-stdout.rs +++ b/library/std/tests/switch-stdout.rs @@ -50,7 +50,7 @@ fn switch_stdout_to(file: OwnedHandle) -> OwnedHandle { } #[test] -#[cfg_attr(miri, ignore)] // dup/SetStdHandle not supported by Miri +#[cfg_attr(all(windows, skip_unsupported_miri_tests), ignore)] // SetStdHandle not supported by Miri fn switch_stdout() { let temp = common::tmpdir(); let path = temp.join("switch-stdout-output"); diff --git a/library/std/tests/thread.rs b/library/std/tests/thread.rs index ef13ce44d3180..433b804952694 100644 --- a/library/std/tests/thread.rs +++ b/library/std/tests/thread.rs @@ -6,7 +6,7 @@ use std::time::{Duration, Instant}; #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -#[cfg_attr(miri, ignore)] // Miri does not like the thread leak +#[cfg_attr(miri, ignore)] // Test leaks memory; a copy in the Miri test suite covers this fn sleep_very_long() { let finished = Arc::new(Mutex::new(false)); let t_finished = finished.clone(); diff --git a/library/std/tests/thread_local/tests.rs b/library/std/tests/thread_local/tests.rs index c2164a0bc2cff..734437585efcb 100644 --- a/library/std/tests/thread_local/tests.rs +++ b/library/std/tests/thread_local/tests.rs @@ -403,7 +403,7 @@ fn thread_current_in_dtor() { // https://github.com/rust-lang/rust/pull/148799#issuecomment-3731806901 #[cfg(target_os = "windows")] #[test] -#[cfg_attr(miri, ignore)] // Miri does not support fibers +#[cfg_attr(skip_unsupported_miri_tests, ignore)] // Miri does not support fibers fn fiber_does_not_trigger_dtor() { use core::ffi::c_void; use std::ptr; diff --git a/library/std/tests/win_delete_self.rs b/library/std/tests/win_delete_self.rs index ce505de69a22d..1b4e95174664b 100644 --- a/library/std/tests/win_delete_self.rs +++ b/library/std/tests/win_delete_self.rs @@ -2,7 +2,7 @@ /// Attempting to delete a running binary should return an error on Windows. #[test] -#[cfg_attr(miri, ignore)] // `remove_file` does not work in Miri on Windows +#[cfg_attr(skip_unsupported_miri_tests, ignore)] // `remove_file` does not work in Miri on Windows fn win_delete_self() { let path = std::env::current_exe().unwrap(); assert!(std::fs::remove_file(path).is_err()); diff --git a/library/std/tests/windows_unix_socket.rs b/library/std/tests/windows_unix_socket.rs index dd71b1f135dce..865794361eabb 100644 --- a/library/std/tests/windows_unix_socket.rs +++ b/library/std/tests/windows_unix_socket.rs @@ -1,5 +1,5 @@ #![cfg(windows)] -#![cfg(not(miri))] // no Windows socket support in Miri +#![cfg(not(skip_unsupported_miri_tests))] // no Windows socket support in Miri #![feature(windows_unix_domain_sockets)] // Now only test windows_unix_domain_sockets feature // in the future, will test both unix and windows uds diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 886966fdd496e..07412657f8687 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -58,13 +58,13 @@ check-aux: $(Q)$(BOOTSTRAP) test --stage 2 \ build-std \ $(BOOTSTRAP_ARGS) - # Run standard library tests in Miri. + ## Run standard library tests in Miri. $(Q)MIRIFLAGS="-Zmiri-strict-provenance" \ $(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ $(BOOTSTRAP_ARGS) \ - --tests # exclude doc tests + --tests # exclude doc tests, they are run below # Some doctests use file system operations to demonstrate dealing with `Result`, # so we have to run them with isolation disabled. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ @@ -73,22 +73,15 @@ check-aux: library/alloc \ $(BOOTSTRAP_ARGS) \ --doc - # In `std` we cannot test everything, so we skip some modules. - $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ - $(BOOTSTRAP) miri --stage 2 \ - library/std \ - $(BOOTSTRAP_ARGS) \ - -- \ - --skip fs:: --skip net:: --skip process:: --skip sys:: - # Also test some very target-specific modules on other targets - # (making sure to cover an i686 target as well). - $(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \ + # In `std` we cannot test everything. Tests should be disabled under `skip_unsupported_miri_tests`. + # We cover all three tier 1 architectures and operating systems. + $(Q)MIRIFLAGS="--cfg skip_unsupported_miri_tests -Zmiri-disable-isolation -Zmiri-no-short-fd-operations" \ + BOOTSTRAP_SKIP_TARGET_SANITY=1 \ $(BOOTSTRAP) miri --stage 2 \ library/std \ - --target aarch64-apple-darwin,i686-pc-windows-msvc \ $(BOOTSTRAP_ARGS) \ - -- \ - time:: sync:: thread:: env:: + --target x86_64-unknown-linux-gnu,aarch64-apple-darwin,i686-pc-windows-msvc \ + --tests # skip all doctests, they are not using skip_unsupported_miri_tests dist: $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) distcheck: diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index efaf79af02e88..7e5f545bffbfb 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1214,6 +1214,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We need to return something non-null here to make `compat_fn!` work. ecx.write_int(1, dest)?; } + "GetModuleHandleW" if ecx.frame_in_std() => { + let [_module_name] = &ecx.check_shim_sig( + shim_sig!(extern "system" fn(*_) -> winapi::HMODULE), + (link_name, abi, args), + )?; + // Returning null works best for `format_error`. + ecx.write_int(0, dest)?; + } "SetConsoleTextAttribute" if ecx.frame_in_std() => { let [_console_output, _attribute] = &ecx.check_shim_sig( shim_sig!(extern "system" fn(winapi::HANDLE, u16) -> winapi::BOOL), diff --git a/src/tools/miri/tests/pass/shims/io.rs b/src/tools/miri/tests/pass/shims/io.rs index a96b98c022746..554ee2dd0cee1 100644 --- a/src/tools/miri/tests/pass/shims/io.rs +++ b/src/tools/miri/tests/pass/shims/io.rs @@ -12,7 +12,8 @@ fn main() { let raw_os_error = if cfg!(unix) { 22 // EINVAL (on most Unixes, anyway) } else if cfg!(windows) { - 87 // ERROR_INVALID_PARAMETER + // FACILITY_NT_BIT hits an extra codepath in std + 87 | 268435456 // ERROR_INVALID_PARAMETER | FACILITY_NT_BIT } else { panic!("unsupported OS") }; From 2b46dddfc23a811b4c9d0a42be3624f03b0b50f5 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 10 Nov 2026 21:48:59 +0100 Subject: [PATCH 09/15] make improper_ctypes accept x87_f80 It is represented as an ADT, so needs custom logic to be accepted. The point of this type is that it's compatible with its C counterpart, so the lint definitely should accept it. --- .../rustc_lint/src/types/improper_ctypes.rs | 4 ++- tests/ui/lint/improper-ctypes/x87_f80.rs | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/improper-ctypes/x87_f80.rs diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 32d583768e534..45615d1476f36 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -803,7 +803,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct | AdtKind::Union => { - if tcx.is_lang_item(def.did(), LangItem::PpcF128) { + if tcx.is_lang_item(def.did(), LangItem::PpcF128) + || tcx.is_lang_item(def.did(), LangItem::X87F80) + { return FfiResult::FfiSafe; } if let Some(sym::cstring_type | sym::cstr_type) = diff --git a/tests/ui/lint/improper-ctypes/x87_f80.rs b/tests/ui/lint/improper-ctypes/x87_f80.rs new file mode 100644 index 0000000000000..62df52dbb4a7a --- /dev/null +++ b/tests/ui/lint/improper-ctypes/x87_f80.rs @@ -0,0 +1,28 @@ +#![deny(improper_ctypes_definitions)] +//@ add-minicore +//@ check-pass +//@ revisions: linux64 linux32 win64 win32 +//@ [linux64] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [linux32] compile-flags: --target=i686-unknown-linux-gnu +//@ [win64] compile-flags: --target=x86_64-pc-windows-gnu +//@ [win32] compile-flags: --target=i686-pc-windows-gnu +//@ needs-llvm-components: x86 +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; + +// The x87_f80 type is implemented as an ADT, so it needs custom logic +// to be accepted by improper_ctypes. + +#[cfg(target_arch = "x86")] +use minicore::arch::x86::x87_f80; +#[cfg(target_arch = "x86_64")] +use minicore::arch::x86_64::x87_f80; +use minicore::*; + +#[unsafe(no_mangle)] +extern "C" fn identity(x: x87_f80) -> x87_f80 { + x +} From c22a287fca730283289818c0f059aa4ed667f248 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 10 Nov 2026 11:53:30 +0100 Subject: [PATCH 10/15] Wrap proc-macro `EscapeError` enum into a struct --- library/proc_macro/src/lib.rs | 93 ++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 8a0f150a5eac4..e3a815ca4948e 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -65,10 +65,61 @@ use crate::bridge::client::Methods as BridgeMethods; use crate::escape::{EscapeOptions, escape_bytes}; /// Mostly relating to malformed escape sequences, but also a few other problems. +#[derive(Debug, PartialEq, Eq)] +#[unstable(feature = "proc_macro_value", issue = "136652")] +pub struct EscapeError { + kind: EscapeErrorKind, +} + +#[unstable(feature = "proc_macro_value", issue = "136652")] +impl error::Error for EscapeError {} + #[unstable(feature = "proc_macro_value", issue = "136652")] +impl fmt::Display for EscapeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.kind, f) + } +} + +#[unstable(feature = "proc_macro_value", issue = "136652")] +#[doc(hidden)] +impl From for EscapeError { + fn from(value: rustc_literal_escaper::EscapeError) -> Self { + use rustc_literal_escaper::EscapeError as EE; + + let kind = match value { + EE::ZeroChars => EscapeErrorKind::ZeroChars, + EE::MoreThanOneChar => EscapeErrorKind::MoreThanOneChar, + EE::LoneSlash => EscapeErrorKind::LoneSlash, + EE::InvalidEscape => EscapeErrorKind::InvalidEscape, + EE::BareCarriageReturn => EscapeErrorKind::BareCarriageReturn, + EE::BareCarriageReturnInRawString => EscapeErrorKind::BareCarriageReturnInRawString, + EE::EscapeOnlyChar => EscapeErrorKind::EscapeOnlyChar, + EE::TooShortHexEscape => EscapeErrorKind::TooShortHexEscape, + EE::InvalidCharInHexEscape => EscapeErrorKind::InvalidCharInHexEscape, + EE::OutOfRangeHexEscape => EscapeErrorKind::OutOfRangeHexEscape, + EE::NoBraceInUnicodeEscape => EscapeErrorKind::NoBraceInUnicodeEscape, + EE::InvalidCharInUnicodeEscape => EscapeErrorKind::InvalidCharInUnicodeEscape, + EE::EmptyUnicodeEscape => EscapeErrorKind::EmptyUnicodeEscape, + EE::UnclosedUnicodeEscape => EscapeErrorKind::UnclosedUnicodeEscape, + EE::LeadingUnderscoreUnicodeEscape => EscapeErrorKind::LeadingUnderscoreUnicodeEscape, + EE::OverlongUnicodeEscape => EscapeErrorKind::OverlongUnicodeEscape, + EE::LoneSurrogateUnicodeEscape => EscapeErrorKind::LoneSurrogateUnicodeEscape, + EE::OutOfRangeUnicodeEscape => EscapeErrorKind::OutOfRangeUnicodeEscape, + EE::UnicodeEscapeInByte => EscapeErrorKind::UnicodeEscapeInByte, + EE::NonAsciiCharInByte => EscapeErrorKind::NonAsciiCharInByte, + EE::NulInCStr => EscapeErrorKind::NulInCStr, + EE::UnskippedWhitespaceWarning => EscapeErrorKind::UnskippedWhitespaceWarning, + EE::MultipleSkippedLinesWarning => EscapeErrorKind::MultipleSkippedLinesWarning, + }; + Self { kind } + } +} + +/// Mostly relating to malformed escape sequences, but also a few other problems. #[derive(Debug, PartialEq, Eq)] #[non_exhaustive] -pub enum EscapeError { +enum EscapeErrorKind { /// Expected 1 char, but 0 were found. ZeroChars, /// Expected 1 char, but more than 1 were found. @@ -125,45 +176,9 @@ pub enum EscapeError { MultipleSkippedLinesWarning, } -#[unstable(feature = "proc_macro_value", issue = "136652")] -#[doc(hidden)] -impl From for EscapeError { - fn from(value: rustc_literal_escaper::EscapeError) -> Self { - use rustc_literal_escaper::EscapeError as EE; - - match value { - EE::ZeroChars => Self::ZeroChars, - EE::MoreThanOneChar => Self::MoreThanOneChar, - EE::LoneSlash => Self::LoneSlash, - EE::InvalidEscape => Self::InvalidEscape, - EE::BareCarriageReturn => Self::BareCarriageReturn, - EE::BareCarriageReturnInRawString => Self::BareCarriageReturnInRawString, - EE::EscapeOnlyChar => Self::EscapeOnlyChar, - EE::TooShortHexEscape => Self::TooShortHexEscape, - EE::InvalidCharInHexEscape => Self::InvalidCharInHexEscape, - EE::OutOfRangeHexEscape => Self::OutOfRangeHexEscape, - EE::NoBraceInUnicodeEscape => Self::NoBraceInUnicodeEscape, - EE::InvalidCharInUnicodeEscape => Self::InvalidCharInUnicodeEscape, - EE::EmptyUnicodeEscape => Self::EmptyUnicodeEscape, - EE::UnclosedUnicodeEscape => Self::UnclosedUnicodeEscape, - EE::LeadingUnderscoreUnicodeEscape => Self::LeadingUnderscoreUnicodeEscape, - EE::OverlongUnicodeEscape => Self::OverlongUnicodeEscape, - EE::LoneSurrogateUnicodeEscape => Self::LoneSurrogateUnicodeEscape, - EE::OutOfRangeUnicodeEscape => Self::OutOfRangeUnicodeEscape, - EE::UnicodeEscapeInByte => Self::UnicodeEscapeInByte, - EE::NonAsciiCharInByte => Self::NonAsciiCharInByte, - EE::NulInCStr => Self::NulInCStr, - EE::UnskippedWhitespaceWarning => Self::UnskippedWhitespaceWarning, - EE::MultipleSkippedLinesWarning => Self::MultipleSkippedLinesWarning, - } - } -} - -#[unstable(feature = "proc_macro_value", issue = "136652")] -impl error::Error for EscapeError {} +impl error::Error for EscapeErrorKind {} -#[unstable(feature = "proc_macro_value", issue = "136652")] -impl fmt::Display for EscapeError { +impl fmt::Display for EscapeErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { Self::ZeroChars => "zero chars", From bd7688c3f11b1418ff9f411abf6ed6e4d5011a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Oct 2026 16:08:56 +0000 Subject: [PATCH 11/15] Fix incorrect span to point at private item that should be marked `pub` ``` error[E0364]: `f` is private, and cannot be re-exported --> $DIR/privacy-early.rs:10:13 | LL | pub macro m() { LL | use f as g; | ^^^^^^ ... LL | foo::m!(); | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:6:5 | LL | fn f() {} | ^^^^^^^^^ ``` where it was ``` error[E0364]: `f` is private, and cannot be re-exported --> $DIR/privacy-early.rs:10:13 | LL | pub macro m() { LL | use f as g; | ^^^^^^ ... LL | foo::m!(); | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:10:13 | LL | use f as g; | ^^^^^^ ... LL | foo::m!(); | --------- in this macro invocation ``` --- compiler/rustc_resolve/src/imports.rs | 2 +- tests/ui/hygiene/privacy-early.stderr | 19 ++---- .../private-from-decl-macro.fail.stderr | 9 +-- tests/ui/imports/reexports.stderr | 6 +- .../ui/privacy/crate-private-reexport.stderr | 66 +++++++++---------- ...46209-private-enum-variant-reexport.stderr | 12 ++-- .../ui/privacy/macro-private-reexport.stderr | 6 +- .../privacy/private-variant-reexport.stderr | 12 ++-- tests/ui/privacy/restricted/test.stderr | 6 +- tests/ui/resolve/decl-macro-use-no-ice.stderr | 9 +-- 10 files changed, 67 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9afbb425eeb9d..47d3f6b1804de 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1708,7 +1708,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span }); } _ => { - err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident }); + err.subdiagnostic(ConsiderMarkingAsPub { span: decl.span, ident }); } } err.emit(); diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr index 22a8db986ad3d..5faa3181f7dc8 100644 --- a/tests/ui/hygiene/privacy-early.stderr +++ b/tests/ui/hygiene/privacy-early.stderr @@ -9,13 +9,10 @@ LL | foo::m!(); | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module - --> $DIR/privacy-early.rs:10:13 + --> $DIR/privacy-early.rs:6:5 | -LL | use f as g; - | ^^^^^^ -... -LL | foo::m!(); - | --------- in this macro invocation +LL | fn f() {} + | ^^^^^^^^^ error[E0364]: `f` is private, and cannot be re-exported --> $DIR/privacy-early.rs:10:13 @@ -28,14 +25,10 @@ LL | foo::m!(); | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module - --> $DIR/privacy-early.rs:10:13 + --> $DIR/privacy-early.rs:7:5 | -LL | use f as g; - | ^^^^^^ -... -LL | foo::m!(); - | --------- in this macro invocation - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | macro f() {} + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr index 80b6fde5e8539..a6fac6b33e3d8 100644 --- a/tests/ui/imports/private-from-decl-macro.fail.stderr +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -10,13 +10,10 @@ LL | crate::m::mac_glob!(); | --------------------- in this macro invocation | note: consider marking `S` as `pub` in the imported module - --> $DIR/private-from-decl-macro.rs:18:13 + --> $DIR/private-from-decl-macro.rs:10:5 | -LL | use crate::m::*; - | ^^^^^^^^^^^ -... -LL | crate::m::mac_glob!(); - | --------------------- in this macro invocation +LL | const S: u8 = 0; + | ^^^^^^^^^^^^^^^^ error[E0423]: cannot find value `S` in this scope --> $DIR/private-from-decl-macro.rs:28:17 diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index cb3836305c1ab..e85d938be2ff5 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -5,10 +5,10 @@ LL | pub use super::foo; | ^^^^^^^^^^ | note: consider marking `foo` as `pub` in the imported module - --> $DIR/reexports.rs:8:17 + --> $DIR/reexports.rs:4:5 | -LL | pub use super::foo; - | ^^^^^^^^^^ +LL | fn foo() {} + | ^^^^^^^^^^^ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:36:22 diff --git a/tests/ui/privacy/crate-private-reexport.stderr b/tests/ui/privacy/crate-private-reexport.stderr index 9b2626efacd2d..39814835f6ff4 100644 --- a/tests/ui/privacy/crate-private-reexport.stderr +++ b/tests/ui/privacy/crate-private-reexport.stderr @@ -5,10 +5,10 @@ LL | pub use crate::f1; | ^^^^^^^^^ | note: consider marking `f1` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:8:13 + --> $DIR/crate-private-reexport.rs:1:1 | -LL | pub use crate::f1; - | ^^^^^^^^^ +LL | fn f1() {} + | ^^^^^^^^^^ error[E0365]: `S1` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:9:13 @@ -33,10 +33,10 @@ LL | pub use crate::E1::V; | ^^^^^^^^^^^^ | note: consider marking `V` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:11:13 + --> $DIR/crate-private-reexport.rs:2:11 | -LL | pub use crate::E1::V; - | ^^^^^^^^^^^^ +LL | enum E1 { V } + | ^ error[E0364]: `f2` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:23:13 @@ -45,10 +45,10 @@ LL | pub use crate::f2; | ^^^^^^^^^ | note: consider marking `f2` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:23:13 + --> $DIR/crate-private-reexport.rs:14:1 | -LL | pub use crate::f2; - | ^^^^^^^^^ +LL | pub(crate) fn f2() {} + | ^^^^^^^^^^^^^^^^^^^^^ error[E0365]: `S2` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:24:13 @@ -73,10 +73,10 @@ LL | pub use crate::E2::V; | ^^^^^^^^^^^^ | note: consider marking `V` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:26:13 + --> $DIR/crate-private-reexport.rs:16:5 | -LL | pub use crate::E2::V; - | ^^^^^^^^^^^^ +LL | V + | ^ error[E0364]: `f3` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:39:9 @@ -85,10 +85,10 @@ LL | pub use m3::f3; | ^^^^^^ | note: consider marking `f3` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:39:9 + --> $DIR/crate-private-reexport.rs:30:5 | -LL | pub use m3::f3; - | ^^^^^^ +LL | pub(crate) fn f3() {} + | ^^^^^^^^^^^^^^^^^^^^^ error[E0365]: `S3` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:40:9 @@ -113,10 +113,10 @@ LL | pub use m3::E3::V; | ^^^^^^^^^ | note: consider marking `V` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:42:9 + --> $DIR/crate-private-reexport.rs:32:9 | -LL | pub use m3::E3::V; - | ^^^^^^^^^ +LL | V + | ^ error[E0364]: `f4` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:45:9 @@ -125,10 +125,10 @@ LL | pub use crate::f4 as f5; | ^^^^^^^^^^^^^^^ | note: consider marking `f4` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:45:9 + --> $DIR/crate-private-reexport.rs:44:1 | -LL | pub use crate::f4 as f5; - | ^^^^^^^^^^^^^^^ +LL | pub(self) fn f4() {} + | ^^^^^^^^^^^^^^^^^^^^ error[E0364]: `f6` is private, and cannot be re-exported --> $DIR/crate-private-reexport.rs:53:13 @@ -137,10 +137,10 @@ LL | pub use self::m::f6; | ^^^^^^^^^^^ | note: consider marking `f6` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:53:13 + --> $DIR/crate-private-reexport.rs:49:9 | -LL | pub use self::m::f6; - | ^^^^^^^^^^^ +LL | pub(super) fn f6() {} + | ^^^^^^^^^^^^^^^^^^^^^ error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:54:13 @@ -149,10 +149,10 @@ LL | pub use self::m::f7; | ^^^^^^^^^^^ | note: consider marking `f7` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:54:13 + --> $DIR/crate-private-reexport.rs:50:9 | -LL | pub use self::m::f7; - | ^^^^^^^^^^^ +LL | pub(crate) fn f7() {} + | ^^^^^^^^^^^^^^^^^^^^^ error[E0364]: `f8` is private, and cannot be re-exported --> $DIR/crate-private-reexport.rs:55:13 @@ -161,10 +161,10 @@ LL | pub use self::m::f8; | ^^^^^^^^^^^ | note: consider marking `f8` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:55:13 + --> $DIR/crate-private-reexport.rs:51:9 | -LL | pub use self::m::f8; - | ^^^^^^^^^^^ +LL | pub(in crate::m10) fn f8() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:58:9 @@ -173,10 +173,10 @@ LL | pub use m10::m::f7; | ^^^^^^^^^^ | note: consider marking `f7` as `pub` in the imported module - --> $DIR/crate-private-reexport.rs:58:9 + --> $DIR/crate-private-reexport.rs:50:9 | -LL | pub use m10::m::f7; - | ^^^^^^^^^^ +LL | pub(crate) fn f7() {} + | ^^^^^^^^^^^^^^^^^^^^^ error[E0603]: function `f6` is private --> $DIR/crate-private-reexport.rs:57:17 diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index f1701d547a62f..0adf20c8f9fab 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -5,10 +5,10 @@ LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^^^^^^^^ | note: consider marking `JuniorGrade` as `pub` in the imported module - --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:32 + --> $DIR/issue-46209-private-enum-variant-reexport.rs:25:9 | -LL | pub use self::Lieutenant::{JuniorGrade, Full}; - | ^^^^^^^^^^^ +LL | JuniorGrade, + | ^^^^^^^^^^^ error[E0364]: `Full` is private, and cannot be re-exported --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:45 @@ -17,10 +17,10 @@ LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^ | note: consider marking `Full` as `pub` in the imported module - --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:45 + --> $DIR/issue-46209-private-enum-variant-reexport.rs:26:9 | -LL | pub use self::Lieutenant::{JuniorGrade, Full}; - | ^^^^ +LL | Full, + | ^^^^ error: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough --> $DIR/issue-46209-private-enum-variant-reexport.rs:3:13 diff --git a/tests/ui/privacy/macro-private-reexport.stderr b/tests/ui/privacy/macro-private-reexport.stderr index aa02715c20298..61af022b901e5 100644 --- a/tests/ui/privacy/macro-private-reexport.stderr +++ b/tests/ui/privacy/macro-private-reexport.stderr @@ -23,10 +23,10 @@ LL | pub use baz as _; | ^^^^^^^^ | note: consider marking `baz` as `pub` in the imported module - --> $DIR/macro-private-reexport.rs:14:13 + --> $DIR/macro-private-reexport.rs:12:5 | -LL | pub use baz as _; - | ^^^^^^^^ +LL | macro baz() {} + | ^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr index aaa42d8d30dc5..efc6d5c3ae0ff 100644 --- a/tests/ui/privacy/private-variant-reexport.stderr +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -5,10 +5,10 @@ LL | pub use ::E::V; | ^^^^^^ | note: consider marking `V` as `pub` in the imported module - --> $DIR/private-variant-reexport.rs:3:13 + --> $DIR/private-variant-reexport.rs:21:10 | -LL | pub use ::E::V; - | ^^^^^^ +LL | enum E { V } + | ^ error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:7:19 @@ -17,10 +17,10 @@ LL | pub use ::E::{V}; | ^ | note: consider marking `V` as `pub` in the imported module - --> $DIR/private-variant-reexport.rs:7:19 + --> $DIR/private-variant-reexport.rs:21:10 | -LL | pub use ::E::{V}; - | ^ +LL | enum E { V } + | ^ error[E0432]: unresolved import `E::V` --> $DIR/private-variant-reexport.rs:11:18 diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index f380da1ca344e..5aebd55825eba 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -5,10 +5,10 @@ LL | pub(super) use foo::bar::f as g; | ^^^^^^^^^^^^^^^^ | note: consider marking `f` as `pub` in the imported module - --> $DIR/test.rs:22:24 + --> $DIR/test.rs:9:9 | -LL | pub(super) use foo::bar::f as g; - | ^^^^^^^^^^^^^^^^ +LL | pub(super) fn f() {} + | ^^^^^^^^^^^^^^^^^^^^ error[E0433]: cannot find module or crate `bad` in the crate root --> $DIR/test.rs:51:12 diff --git a/tests/ui/resolve/decl-macro-use-no-ice.stderr b/tests/ui/resolve/decl-macro-use-no-ice.stderr index 1f47f757f6153..35074c292ba08 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.stderr +++ b/tests/ui/resolve/decl-macro-use-no-ice.stderr @@ -9,13 +9,10 @@ LL | foo::m!(); | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module - --> $DIR/decl-macro-use-no-ice.rs:13:13 + --> $DIR/decl-macro-use-no-ice.rs:10:5 | -LL | use f; - | ^ -... -LL | foo::m!(); - | --------- in this macro invocation +LL | macro f() {} + | ^^^^^^^^^^^^ error: aborting due to 1 previous error From 43c52bd3afaf4b2c8480b5388007a4679e5cd525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Oct 2026 17:15:20 +0000 Subject: [PATCH 12/15] Provide more context for private re-exported items Use span when suggesting making module public: ``` note: consider declaring module `foo` with `pub` --> $DIR/E0365.rs:1:1 | LL | / mod foo { LL | | pub const X: u32 = 1; LL | | } | |_^ ``` Show container when talking about enclosing module: ``` note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:6:5 | LL | mod foo { LL | fn f() {} | ^^^^^^^^^ ``` Use accurate descriptor for enclosing item: ``` note: consider declaring struct `S1` with `pub` --> $DIR/crate-private-reexport.rs:3:1 | LL | / struct S1 { LL | | #[rustfmt::skip] LL | | bar: i32, LL | | } | |_^ ``` ``` note: consider marking `Full` as `pub` in the imported variant --> $DIR/issue-46209-private-enum-variant-reexport.rs:26:9 | LL | enum Lieutenant { LL | JuniorGrade, LL | Full, | ^^^^ ``` --- compiler/rustc_resolve/src/diagnostics/mod.rs | 13 ++-- compiler/rustc_resolve/src/imports.rs | 46 +++++++++++-- tests/ui/error-codes/E0365.stderr | 8 ++- tests/ui/hygiene/privacy-early.stderr | 3 + .../private-from-decl-macro.fail.stderr | 2 + tests/ui/imports/reexports.stderr | 1 + tests/ui/modules/issue-56411.stderr | 9 ++- .../ui/privacy/crate-private-reexport.stderr | 65 ++++++++++++++++--- ...46209-private-enum-variant-reexport.stderr | 7 +- .../ui/privacy/macro-private-reexport.stderr | 2 + .../privacy/private-variant-reexport.stderr | 4 +- tests/ui/privacy/restricted/test.stderr | 1 + tests/ui/proc-macro/issue-79148.stderr | 2 +- tests/ui/resolve/decl-macro-use-no-ice.stderr | 1 + tests/ui/use/pub-use-self-super-crate.stderr | 45 +++++++++++-- 15 files changed, 178 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index e33255eec46d8..4a54269a30137 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -831,22 +831,26 @@ pub(crate) struct CannotBeReexportedCratePublic { #[derive(Diagnostic)] #[diag("`{$ident}` is private, and cannot be re-exported", code = E0365)] -#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedPrivateNS { #[primary_span] #[label("re-export of private `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, + #[note("consider declaring {$descr} `{$ident}` with `pub`")] + pub(crate) parent: Span, + pub(crate) descr: &'static str, } #[derive(Diagnostic)] #[diag("`{$ident}` is only public within the crate, and cannot be re-exported outside", code = E0365)] -#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedCratePublicNS { #[primary_span] #[label("re-export of crate public `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, + #[note("consider declaring {$descr} `{$ident}` with `pub`")] + pub(crate) parent: Span, + pub(crate) descr: &'static str, } #[derive(Diagnostic)] @@ -881,11 +885,12 @@ pub(crate) struct ConsiderMarkingAsPubCrate { } #[derive(Subdiagnostic)] -#[note("consider marking `{$ident}` as `pub` in the imported module")] +#[note("consider marking `{$ident}` as `pub` in the imported {$descr}")] pub(crate) struct ConsiderMarkingAsPub { #[primary_span] - pub(crate) span: Span, + pub(crate) span: MultiSpan, pub(crate) ident: Ident, + pub(crate) descr: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 47d3f6b1804de..0205ad616cb08 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -6,10 +6,10 @@ use std::mem; use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; -use rustc_errors::{Applicability, BufferedEarlyLint, Diagnostic}; +use rustc_errors::{Applicability, BufferedEarlyLint, Diagnostic, MultiSpan}; use rustc_expand::base::SyntaxExtensionKind; use rustc_hir::def::{self, DefKind}; -use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalDefIdMap}; use rustc_lint_defs::LintId; use rustc_lint_defs::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, @@ -20,7 +20,7 @@ use rustc_middle::ty::Visibility; use rustc_session::diagnostics::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; -use rustc_span::{Ident, OrdSpan, Span, Symbol, kw, span_bug, sym}; +use rustc_span::{DUMMY_SP, Ident, OrdSpan, Span, Symbol, kw, span_bug, sym}; use tracing::debug; use crate::Namespace::{self, *}; @@ -1685,10 +1685,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { diagnostic: diagnostic.into(), }); } else if ns == TypeNS { + let def_id = decl.res().def_id(); + let parent = if !def_id.is_crate_root() { self.def_span(def_id) } else { DUMMY_SP }; + let descr = self.tcx().def_descr(def_id); + if crate_private_reexport { - self.dcx().emit_err(CannotBeReexportedCratePublicNS { span: import.span, ident }); + self.dcx().emit_err(CannotBeReexportedCratePublicNS { + span: import.span, + ident, + parent, + descr, + }); } else { - self.dcx().emit_err(CannotBeReexportedPrivateNS { span: import.span, ident }); + self.dcx().emit_err(CannotBeReexportedPrivateNS { + span: import.span, + ident, + parent, + descr, + }); } } else { let mut err = if crate_private_reexport { @@ -1708,7 +1722,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span }); } _ => { - err.subdiagnostic(ConsiderMarkingAsPub { span: decl.span, ident }); + let mut span: MultiSpan = decl.span.into(); + let descr = if decl.is_import() { + "re-export" + } else if let Some(def_id) = decl.res().opt_def_id() { + let parent = self.tcx().parent(def_id); + + if let DefKind::Variant = self.tcx().def_kind(parent) { + // We had the DefId for the variant's constructor, but we want to point at the enum. + span.push_span_context( + self.def_span(self.tcx().parent(parent)).shrink_to_lo(), + ); + } else if CRATE_DEF_ID.to_def_id() != parent { + span.push_span_context(self.def_span(parent).shrink_to_lo()); + } + self.tcx().def_descr(parent) + } else { + // unreachable, but provide fallback just in case + debug_assert!(false, "we have a DefId in {decl:?} with no parent?"); + "module" + }; + err.subdiagnostic(ConsiderMarkingAsPub { span, ident, descr }); } } err.emit(); diff --git a/tests/ui/error-codes/E0365.stderr b/tests/ui/error-codes/E0365.stderr index d6eb9d6c38339..4199459e12d1a 100644 --- a/tests/ui/error-codes/E0365.stderr +++ b/tests/ui/error-codes/E0365.stderr @@ -4,7 +4,13 @@ error[E0365]: `foo` is only public within the crate, and cannot be re-exported o LL | pub use foo as foo2; | ^^^^^^^^^^^ re-export of crate public `foo` | - = note: consider declaring type or module `foo` with `pub` +note: consider declaring module `foo` with `pub` + --> $DIR/E0365.rs:1:1 + | +LL | / mod foo { +LL | | pub const X: u32 = 1; +LL | | } + | |_^ error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr index 5faa3181f7dc8..2c1ac643b9a33 100644 --- a/tests/ui/hygiene/privacy-early.stderr +++ b/tests/ui/hygiene/privacy-early.stderr @@ -11,6 +11,7 @@ LL | foo::m!(); note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:6:5 | +LL | mod foo { LL | fn f() {} | ^^^^^^^^^ @@ -27,6 +28,8 @@ LL | foo::m!(); note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:7:5 | +LL | mod foo { +LL | fn f() {} LL | macro f() {} | ^^^^^^^^^^^^ diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr index a6fac6b33e3d8..9468c3535f7f1 100644 --- a/tests/ui/imports/private-from-decl-macro.fail.stderr +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -12,6 +12,8 @@ LL | crate::m::mac_glob!(); note: consider marking `S` as `pub` in the imported module --> $DIR/private-from-decl-macro.rs:10:5 | +LL | mod m { +... LL | const S: u8 = 0; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index e85d938be2ff5..18e7739622219 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -7,6 +7,7 @@ LL | pub use super::foo; note: consider marking `foo` as `pub` in the imported module --> $DIR/reexports.rs:4:5 | +LL | mod a { LL | fn foo() {} | ^^^^^^^^^^^ diff --git a/tests/ui/modules/issue-56411.stderr b/tests/ui/modules/issue-56411.stderr index 6e8912146883d..06f603bc55921 100644 --- a/tests/ui/modules/issue-56411.stderr +++ b/tests/ui/modules/issue-56411.stderr @@ -27,7 +27,14 @@ LL | pub use self::$name; LL | import!(("issue-56411-aux.rs", issue_56411_aux)); | ------------------------------------------------ in this macro invocation | - = note: consider declaring type or module `issue_56411_aux` with `pub` +note: consider declaring module `issue_56411_aux` with `pub` + --> $DIR/issue-56411.rs:5:13 + | +LL | mod $name; + | ^^^^^^^^^^ +... +LL | import!(("issue-56411-aux.rs", issue_56411_aux)); + | ------------------------------------------------ in this macro invocation error: aborting due to 2 previous errors diff --git a/tests/ui/privacy/crate-private-reexport.stderr b/tests/ui/privacy/crate-private-reexport.stderr index 39814835f6ff4..5962db9783ea1 100644 --- a/tests/ui/privacy/crate-private-reexport.stderr +++ b/tests/ui/privacy/crate-private-reexport.stderr @@ -16,7 +16,14 @@ error[E0365]: `S1` is only public within the crate, and cannot be re-exported ou LL | pub use crate::S1; | ^^^^^^^^^ re-export of crate public `S1` | - = note: consider declaring type or module `S1` with `pub` +note: consider declaring struct `S1` with `pub` + --> $DIR/crate-private-reexport.rs:3:1 + | +LL | / struct S1 { +LL | | #[rustfmt::skip] +LL | | bar: i32, +LL | | } + | |_^ error[E0365]: `E1` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:10:13 @@ -24,7 +31,11 @@ error[E0365]: `E1` is only public within the crate, and cannot be re-exported ou LL | pub use crate::E1; | ^^^^^^^^^ re-export of crate public `E1` | - = note: consider declaring type or module `E1` with `pub` +note: consider declaring enum `E1` with `pub` + --> $DIR/crate-private-reexport.rs:2:1 + | +LL | enum E1 { V } + | ^^^^^^^^^^^^^ error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:11:13 @@ -32,7 +43,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use crate::E1::V; | ^^^^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported module +note: consider marking `V` as `pub` in the imported variant --> $DIR/crate-private-reexport.rs:2:11 | LL | enum E1 { V } @@ -56,7 +67,14 @@ error[E0365]: `S2` is only public within the crate, and cannot be re-exported ou LL | pub use crate::S2; | ^^^^^^^^^ re-export of crate public `S2` | - = note: consider declaring type or module `S2` with `pub` +note: consider declaring struct `S2` with `pub` + --> $DIR/crate-private-reexport.rs:18:1 + | +LL | / pub(crate) struct S2 { +LL | | #[rustfmt::skip] +LL | | bar: i32, +LL | | } + | |_^ error[E0365]: `E2` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:25:13 @@ -64,7 +82,13 @@ error[E0365]: `E2` is only public within the crate, and cannot be re-exported ou LL | pub use crate::E2; | ^^^^^^^^^ re-export of crate public `E2` | - = note: consider declaring type or module `E2` with `pub` +note: consider declaring enum `E2` with `pub` + --> $DIR/crate-private-reexport.rs:15:1 + | +LL | / pub(crate) enum E2 { +LL | | V +LL | | } + | |_^ error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:26:13 @@ -72,9 +96,10 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use crate::E2::V; | ^^^^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported module +note: consider marking `V` as `pub` in the imported variant --> $DIR/crate-private-reexport.rs:16:5 | +LL | pub(crate) enum E2 { LL | V | ^ @@ -87,6 +112,7 @@ LL | pub use m3::f3; note: consider marking `f3` as `pub` in the imported module --> $DIR/crate-private-reexport.rs:30:5 | +LL | mod m3 { LL | pub(crate) fn f3() {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +122,14 @@ error[E0365]: `S3` is only public within the crate, and cannot be re-exported ou LL | pub use m3::S3; | ^^^^^^ re-export of crate public `S3` | - = note: consider declaring type or module `S3` with `pub` +note: consider declaring struct `S3` with `pub` + --> $DIR/crate-private-reexport.rs:34:5 + | +LL | / pub(crate) struct S3 { +LL | | #[rustfmt::skip] +LL | | bar: i32, +LL | | } + | |_____^ error[E0365]: `E3` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:41:9 @@ -104,7 +137,13 @@ error[E0365]: `E3` is only public within the crate, and cannot be re-exported ou LL | pub use m3::E3; | ^^^^^^ re-export of crate public `E3` | - = note: consider declaring type or module `E3` with `pub` +note: consider declaring enum `E3` with `pub` + --> $DIR/crate-private-reexport.rs:31:5 + | +LL | / pub(crate) enum E3 { +LL | | V +LL | | } + | |_____^ error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/crate-private-reexport.rs:42:9 @@ -112,9 +151,10 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use m3::E3::V; | ^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported module +note: consider marking `V` as `pub` in the imported variant --> $DIR/crate-private-reexport.rs:32:9 | +LL | pub(crate) enum E3 { LL | V | ^ @@ -139,6 +179,7 @@ LL | pub use self::m::f6; note: consider marking `f6` as `pub` in the imported module --> $DIR/crate-private-reexport.rs:49:9 | +LL | pub mod m { LL | pub(super) fn f6() {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -151,6 +192,8 @@ LL | pub use self::m::f7; note: consider marking `f7` as `pub` in the imported module --> $DIR/crate-private-reexport.rs:50:9 | +LL | pub mod m { +LL | pub(super) fn f6() {} LL | pub(crate) fn f7() {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -163,6 +206,8 @@ LL | pub use self::m::f8; note: consider marking `f8` as `pub` in the imported module --> $DIR/crate-private-reexport.rs:51:9 | +LL | pub mod m { +... LL | pub(in crate::m10) fn f8() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -175,6 +220,8 @@ LL | pub use m10::m::f7; note: consider marking `f7` as `pub` in the imported module --> $DIR/crate-private-reexport.rs:50:9 | +LL | pub mod m { +LL | pub(super) fn f6() {} LL | pub(crate) fn f7() {} | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index 0adf20c8f9fab..74430f04817ca 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -4,9 +4,10 @@ error[E0364]: `JuniorGrade` is private, and cannot be re-exported LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^^^^^^^^ | -note: consider marking `JuniorGrade` as `pub` in the imported module +note: consider marking `JuniorGrade` as `pub` in the imported variant --> $DIR/issue-46209-private-enum-variant-reexport.rs:25:9 | +LL | enum Lieutenant { LL | JuniorGrade, | ^^^^^^^^^^^ @@ -16,9 +17,11 @@ error[E0364]: `Full` is private, and cannot be re-exported LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^ | -note: consider marking `Full` as `pub` in the imported module +note: consider marking `Full` as `pub` in the imported variant --> $DIR/issue-46209-private-enum-variant-reexport.rs:26:9 | +LL | enum Lieutenant { +LL | JuniorGrade, LL | Full, | ^^^^ diff --git a/tests/ui/privacy/macro-private-reexport.stderr b/tests/ui/privacy/macro-private-reexport.stderr index 61af022b901e5..33c68ce013d62 100644 --- a/tests/ui/privacy/macro-private-reexport.stderr +++ b/tests/ui/privacy/macro-private-reexport.stderr @@ -25,6 +25,8 @@ LL | pub use baz as _; note: consider marking `baz` as `pub` in the imported module --> $DIR/macro-private-reexport.rs:12:5 | +LL | mod foo { +... LL | macro baz() {} | ^^^^^^^^^^^^^^ diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr index efc6d5c3ae0ff..4d76bbad6c3c5 100644 --- a/tests/ui/privacy/private-variant-reexport.stderr +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -4,7 +4,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use ::E::V; | ^^^^^^ | -note: consider marking `V` as `pub` in the imported module +note: consider marking `V` as `pub` in the imported variant --> $DIR/private-variant-reexport.rs:21:10 | LL | enum E { V } @@ -16,7 +16,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use ::E::{V}; | ^ | -note: consider marking `V` as `pub` in the imported module +note: consider marking `V` as `pub` in the imported variant --> $DIR/private-variant-reexport.rs:21:10 | LL | enum E { V } diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index 5aebd55825eba..529bc9cf96766 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -7,6 +7,7 @@ LL | pub(super) use foo::bar::f as g; note: consider marking `f` as `pub` in the imported module --> $DIR/test.rs:9:9 | +LL | pub mod bar { LL | pub(super) fn f() {} | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/proc-macro/issue-79148.stderr b/tests/ui/proc-macro/issue-79148.stderr index 8adc4c6e0dbe4..bcb7f7b2fe4b1 100644 --- a/tests/ui/proc-macro/issue-79148.stderr +++ b/tests/ui/proc-macro/issue-79148.stderr @@ -4,7 +4,7 @@ error[E0364]: `Variant` is only public within the crate, and cannot be re-export LL | cause_ice!(); | ^^^^^^^^^^^^ | -note: consider marking `Variant` as `pub` in the imported module +note: consider marking `Variant` as `pub` in the imported variant --> $DIR/issue-79148.rs:8:1 | LL | cause_ice!(); diff --git a/tests/ui/resolve/decl-macro-use-no-ice.stderr b/tests/ui/resolve/decl-macro-use-no-ice.stderr index 35074c292ba08..073537d1cabbd 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.stderr +++ b/tests/ui/resolve/decl-macro-use-no-ice.stderr @@ -11,6 +11,7 @@ LL | foo::m!(); note: consider marking `f` as `pub` in the imported module --> $DIR/decl-macro-use-no-ice.rs:10:5 | +LL | mod foo { LL | macro f() {} | ^^^^^^^^^^^^ diff --git a/tests/ui/use/pub-use-self-super-crate.stderr b/tests/ui/use/pub-use-self-super-crate.stderr index 0f9c87b93a098..9d6df994a4d79 100644 --- a/tests/ui/use/pub-use-self-super-crate.stderr +++ b/tests/ui/use/pub-use-self-super-crate.stderr @@ -4,7 +4,14 @@ error[E0365]: `self` is only public within the crate, and cannot be re-exported LL | pub use self as this; | ^^^^^^^^^^^^ re-export of crate public `self` | - = note: consider declaring type or module `self` with `pub` +note: consider declaring module `self` with `pub` + --> $DIR/pub-use-self-super-crate.rs:1:1 + | +LL | / mod foo { +LL | | pub use self as this; +... | +LL | | } + | |_^ error[E0365]: `super` is only public within the crate, and cannot be re-exported outside --> $DIR/pub-use-self-super-crate.rs:6:17 @@ -12,7 +19,14 @@ error[E0365]: `super` is only public within the crate, and cannot be re-exported LL | pub use super as parent; | ^^^^^^^^^^^^^^^ re-export of crate public `super` | - = note: consider declaring type or module `super` with `pub` +note: consider declaring module `super` with `pub` + --> $DIR/pub-use-self-super-crate.rs:1:1 + | +LL | / mod foo { +LL | | pub use self as this; +... | +LL | | } + | |_^ error[E0365]: `super` is only public within the crate, and cannot be re-exported outside --> $DIR/pub-use-self-super-crate.rs:8:17 @@ -20,7 +34,14 @@ error[E0365]: `super` is only public within the crate, and cannot be re-exported LL | pub use self::super as parent2; | ^^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `super` | - = note: consider declaring type or module `super` with `pub` +note: consider declaring module `super` with `pub` + --> $DIR/pub-use-self-super-crate.rs:1:1 + | +LL | / mod foo { +LL | | pub use self as this; +... | +LL | | } + | |_^ error[E0365]: `self` is only public within the crate, and cannot be re-exported outside --> $DIR/pub-use-self-super-crate.rs:10:25 @@ -28,7 +49,14 @@ error[E0365]: `self` is only public within the crate, and cannot be re-exported LL | pub use super::{self as parent3}; | ^^^^^^^^^^^^^^^ re-export of crate public `self` | - = note: consider declaring type or module `self` with `pub` +note: consider declaring module `self` with `pub` + --> $DIR/pub-use-self-super-crate.rs:1:1 + | +LL | / mod foo { +LL | | pub use self as this; +... | +LL | | } + | |_^ error[E0365]: `super` is only public within the crate, and cannot be re-exported outside --> $DIR/pub-use-self-super-crate.rs:12:24 @@ -36,7 +64,14 @@ error[E0365]: `super` is only public within the crate, and cannot be re-exported LL | pub use self::{super as parent4}; | ^^^^^^^^^^^^^^^^ re-export of crate public `super` | - = note: consider declaring type or module `super` with `pub` +note: consider declaring module `super` with `pub` + --> $DIR/pub-use-self-super-crate.rs:1:1 + | +LL | / mod foo { +LL | | pub use self as this; +... | +LL | | } + | |_^ error: aborting due to 5 previous errors From bef8da0b44c5cf6c0d7d5539600c371d1f5451e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 9 Nov 2026 20:21:57 +0000 Subject: [PATCH 13/15] Tweak wording when encountering private variants --- compiler/rustc_resolve/src/imports.rs | 5 ++++- tests/ui/privacy/crate-private-reexport.stderr | 6 +++--- .../issue-46209-private-enum-variant-reexport.stderr | 4 ++-- tests/ui/privacy/private-variant-reexport.stderr | 4 ++-- tests/ui/proc-macro/issue-79148.stderr | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0205ad616cb08..f7e86925800a3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1733,10 +1733,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span.push_span_context( self.def_span(self.tcx().parent(parent)).shrink_to_lo(), ); + self.tcx().def_descr(self.tcx().parent(parent)) } else if CRATE_DEF_ID.to_def_id() != parent { span.push_span_context(self.def_span(parent).shrink_to_lo()); + self.tcx().def_descr(parent) + } else { + self.tcx().def_descr(parent) } - self.tcx().def_descr(parent) } else { // unreachable, but provide fallback just in case debug_assert!(false, "we have a DefId in {decl:?} with no parent?"); diff --git a/tests/ui/privacy/crate-private-reexport.stderr b/tests/ui/privacy/crate-private-reexport.stderr index 5962db9783ea1..c092120972589 100644 --- a/tests/ui/privacy/crate-private-reexport.stderr +++ b/tests/ui/privacy/crate-private-reexport.stderr @@ -43,7 +43,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use crate::E1::V; | ^^^^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported variant +note: consider marking `V` as `pub` in the imported enum --> $DIR/crate-private-reexport.rs:2:11 | LL | enum E1 { V } @@ -96,7 +96,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use crate::E2::V; | ^^^^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported variant +note: consider marking `V` as `pub` in the imported enum --> $DIR/crate-private-reexport.rs:16:5 | LL | pub(crate) enum E2 { @@ -151,7 +151,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use m3::E3::V; | ^^^^^^^^^ | -note: consider marking `V` as `pub` in the imported variant +note: consider marking `V` as `pub` in the imported enum --> $DIR/crate-private-reexport.rs:32:9 | LL | pub(crate) enum E3 { diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index 74430f04817ca..ea748ae5f0f60 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -4,7 +4,7 @@ error[E0364]: `JuniorGrade` is private, and cannot be re-exported LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^^^^^^^^ | -note: consider marking `JuniorGrade` as `pub` in the imported variant +note: consider marking `JuniorGrade` as `pub` in the imported enum --> $DIR/issue-46209-private-enum-variant-reexport.rs:25:9 | LL | enum Lieutenant { @@ -17,7 +17,7 @@ error[E0364]: `Full` is private, and cannot be re-exported LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^ | -note: consider marking `Full` as `pub` in the imported variant +note: consider marking `Full` as `pub` in the imported enum --> $DIR/issue-46209-private-enum-variant-reexport.rs:26:9 | LL | enum Lieutenant { diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr index 4d76bbad6c3c5..6dd94028a9167 100644 --- a/tests/ui/privacy/private-variant-reexport.stderr +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -4,7 +4,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use ::E::V; | ^^^^^^ | -note: consider marking `V` as `pub` in the imported variant +note: consider marking `V` as `pub` in the imported enum --> $DIR/private-variant-reexport.rs:21:10 | LL | enum E { V } @@ -16,7 +16,7 @@ error[E0364]: `V` is only public within the crate, and cannot be re-exported out LL | pub use ::E::{V}; | ^ | -note: consider marking `V` as `pub` in the imported variant +note: consider marking `V` as `pub` in the imported enum --> $DIR/private-variant-reexport.rs:21:10 | LL | enum E { V } diff --git a/tests/ui/proc-macro/issue-79148.stderr b/tests/ui/proc-macro/issue-79148.stderr index bcb7f7b2fe4b1..008a1d16df992 100644 --- a/tests/ui/proc-macro/issue-79148.stderr +++ b/tests/ui/proc-macro/issue-79148.stderr @@ -4,7 +4,7 @@ error[E0364]: `Variant` is only public within the crate, and cannot be re-export LL | cause_ice!(); | ^^^^^^^^^^^^ | -note: consider marking `Variant` as `pub` in the imported variant +note: consider marking `Variant` as `pub` in the imported enum --> $DIR/issue-79148.rs:8:1 | LL | cause_ice!(); From 745d7ccd2b6be307ad5b53a49b721e36119975e9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 9 Nov 2026 13:51:43 -0800 Subject: [PATCH 14/15] Normalize "beta release channel" in `const-supertrait-unstable` test like commit cbdd3f36585d9747c9614b10e59696632e0e64fe did for stable. --- ...supertrait-unstable.nightly-enabled.stderr | 18 +++++------ .../const-supertrait-unstable.nightly.stderr | 22 ++++++------- .../const-traits/const-supertrait-unstable.rs | 1 + ...-supertrait-unstable.stable-enabled.stderr | 30 ++++++++--------- .../const-supertrait-unstable.stable.stderr | 32 +++++++++---------- 5 files changed, 52 insertions(+), 51 deletions(-) diff --git a/tests/ui/traits/const-traits/const-supertrait-unstable.nightly-enabled.stderr b/tests/ui/traits/const-traits/const-supertrait-unstable.nightly-enabled.stderr index 43ac8df50d8f1..ae38e9799981f 100644 --- a/tests/ui/traits/const-traits/const-supertrait-unstable.nightly-enabled.stderr +++ b/tests/ui/traits/const-traits/const-supertrait-unstable.nightly-enabled.stderr @@ -1,17 +1,17 @@ error: `[const]` is not allowed here - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -22,7 +22,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -34,7 +34,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -46,7 +46,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -57,7 +57,7 @@ LL | const trait Bar: [const] Foo {} | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -69,13 +69,13 @@ LL | const trait Bar: [const] Foo {} | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/const-supertrait-unstable.rs:36:7 + --> $DIR/const-supertrait-unstable.rs:37:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ this trait is not const diff --git a/tests/ui/traits/const-traits/const-supertrait-unstable.nightly.stderr b/tests/ui/traits/const-traits/const-supertrait-unstable.nightly.stderr index ed1fa6bf261a9..ba0c399c0d27b 100644 --- a/tests/ui/traits/const-traits/const-supertrait-unstable.nightly.stderr +++ b/tests/ui/traits/const-traits/const-supertrait-unstable.nightly.stderr @@ -1,17 +1,17 @@ error: `[const]` is not allowed here - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: const trait impls are experimental - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ @@ -21,7 +21,7 @@ LL | trait Bar: [const] Foo {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ @@ -31,7 +31,7 @@ LL | const fn foo(x: &T) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -42,7 +42,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -54,7 +54,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` @@ -66,7 +66,7 @@ LL | const trait Foo { | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -77,7 +77,7 @@ LL | const trait Bar: [const] Foo {} | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -89,13 +89,13 @@ LL | const trait Bar: [const] Foo {} | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/const-supertrait-unstable.rs:36:7 + --> $DIR/const-supertrait-unstable.rs:37:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ this trait is not const diff --git a/tests/ui/traits/const-traits/const-supertrait-unstable.rs b/tests/ui/traits/const-traits/const-supertrait-unstable.rs index 04e49b4109f32..5c6b6c731216f 100644 --- a/tests/ui/traits/const-traits/const-supertrait-unstable.rs +++ b/tests/ui/traits/const-traits/const-supertrait-unstable.rs @@ -4,6 +4,7 @@ //@ needs-target-std //@ normalize-stderr: "dev release channel" -> "nightly release channel" +//@ normalize-stderr: "beta release channel" -> "nightly release channel" //@ normalize-stderr: "stable release channel" -> "nightly release channel" //@ compile-flags: --check-cfg=cfg(feature_enabled) diff --git a/tests/ui/traits/const-traits/const-supertrait-unstable.stable-enabled.stderr b/tests/ui/traits/const-traits/const-supertrait-unstable.stable-enabled.stderr index dbcc8d46d3fc7..196f3dc2724ba 100644 --- a/tests/ui/traits/const-traits/const-supertrait-unstable.stable-enabled.stderr +++ b/tests/ui/traits/const-traits/const-supertrait-unstable.stable-enabled.stderr @@ -1,92 +1,92 @@ error: `[const]` is not allowed here - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0554]: `#![feature]` may not be used on the nightly release channel - --> $DIR/const-supertrait-unstable.rs:18:30 + --> $DIR/const-supertrait-unstable.rs:19:30 | LL | #![cfg_attr(feature_enabled, feature(const_trait_impl))] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | note: `Bar` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | note: `Bar` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/const-supertrait-unstable.rs:36:7 + --> $DIR/const-supertrait-unstable.rs:37:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ this trait is not const diff --git a/tests/ui/traits/const-traits/const-supertrait-unstable.stable.stderr b/tests/ui/traits/const-traits/const-supertrait-unstable.stable.stderr index ee1c731e604a6..50ceda54258c1 100644 --- a/tests/ui/traits/const-traits/const-supertrait-unstable.stable.stderr +++ b/tests/ui/traits/const-traits/const-supertrait-unstable.stable.stderr @@ -1,17 +1,17 @@ error: `[const]` is not allowed here - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: const trait impls are experimental - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ @@ -19,7 +19,7 @@ LL | trait Bar: [const] Foo {} = note: see issue #143874 for more information error[E0658]: const trait impls are experimental - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ @@ -27,76 +27,76 @@ LL | const fn foo(x: &T) { = note: see issue #143874 for more information error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:25:12 + --> $DIR/const-supertrait-unstable.rs:26:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | note: `Foo` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | note: `Bar` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/const-supertrait-unstable.rs:32:17 + --> $DIR/const-supertrait-unstable.rs:33:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | note: `Bar` can't be used with `[const]` because it isn't `const` - --> $DIR/const-supertrait-unstable.rs:25:1 + --> $DIR/const-supertrait-unstable.rs:26:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/const-supertrait-unstable.rs:36:7 + --> $DIR/const-supertrait-unstable.rs:37:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/const-supertrait-unstable.rs:21:1 + --> $DIR/const-supertrait-unstable.rs:22:1 | LL | trait Foo { | ^^^^^^^^^ this trait is not const From 886a3f1256dd3f58ae8e648838279868989bd547 Mon Sep 17 00:00:00 2001 From: Alex Celeste Date: Wed, 11 Nov 2026 02:18:35 +0000 Subject: [PATCH 15/15] In irrefutable patterns, the FieldPat is skipped, which means the name: field is not printed * In irrefutable patterns, the FieldPat is skipped, which means the name: field is not printed; since FieldPat can be listed out of order and the list can be incomplete, it is not generally possible to associate a given pattern within a Leaf or Variant with the actual field. the slightly janky indentation is consistent with the way the other PatKinds do it (with no comma) * avoid referring to std in THIR tests * review feedback (test too long) * review feedback (naming, explanation, test too long) * additional review feedback (test still too long) --- compiler/rustc_mir_build/src/thir/print.rs | 12 +- .../thir-print/thir-tree-field-pat-names.rs | 27 + .../thir-tree-field-pat-names.stdout | 460 ++++++++++++++++++ .../ui/thir-print/thir-tree-match-for.stdout | 56 ++- tests/ui/thir-print/thir-tree-match.stdout | 50 +- 5 files changed, 558 insertions(+), 47 deletions(-) create mode 100644 tests/ui/thir-print/thir-tree-field-pat-names.rs create mode 100644 tests/ui/thir-print/thir-tree-field-pat-names.stdout diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 7cfd313218d33..d7186829d5b22 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -718,6 +718,14 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "}", depth_lvl); } + fn print_field_pat(&mut self, field_pat: &FieldPat<'tcx>, depth_lvl: usize) { + print_indented!(self, "FieldPat {", depth_lvl); + print_indented!(self, format!("field: {}", field_pat.field.as_u32()), depth_lvl + 1); + print_indented!(self, "pattern:", depth_lvl + 1); + self.print_pat(&field_pat.pattern, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) { print_indented!(self, "kind: PatKind {", depth_lvl); @@ -760,7 +768,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { if subpatterns.len() > 0 { print_indented!(self, "subpatterns: [", depth_lvl + 2); for field_pat in subpatterns.iter() { - self.print_pat(&field_pat.pattern, depth_lvl + 3); + self.print_field_pat(field_pat, depth_lvl + 3); } print_indented!(self, "]", depth_lvl + 2); } else { @@ -773,7 +781,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "Leaf { ", depth_lvl + 1); print_indented!(self, "subpatterns: [", depth_lvl + 2); for field_pat in subpatterns.iter() { - self.print_pat(&field_pat.pattern, depth_lvl + 3); + self.print_field_pat(field_pat, depth_lvl + 3); } print_indented!(self, "]", depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); diff --git a/tests/ui/thir-print/thir-tree-field-pat-names.rs b/tests/ui/thir-print/thir-tree-field-pat-names.rs new file mode 100644 index 0000000000000..8f64a11658af9 --- /dev/null +++ b/tests/ui/thir-print/thir-tree-field-pat-names.rs @@ -0,0 +1,27 @@ +//@ check-pass +//@ compile-flags: -Zunpretty=thir-tree +//@ normalize-stdout: "\[[a-z0-9]{4}\]" -> "" +//@ normalize-stdout: "DefId\(\d+:\d+" -> "DefId(N:M" + + +// Previously, `Leaf` and `Variant` patterns, when appearing within an irrefutable +// pattern only, did not show the field names, leaving the structure ambiguous. + + +struct Tri { x: u32, y: u32, z: u32 } + +fn tuple_leaf (t: (u32, u32, u32)) { + let (a, ..) = t; + + // refutable (different print path) + if let (a, 12, ..) = t { } +} + +fn struct_leaf (s: Tri) { + let Tri { z: d, y: e, .. } = s; + + // refutable (different print path) + if let Tri { y: 12, x, .. } = s {} +} + +fn main() {} diff --git a/tests/ui/thir-print/thir-tree-field-pat-names.stdout b/tests/ui/thir-print/thir-tree-field-pat-names.stdout new file mode 100644 index 0000000000000..2917dc92aaaa9 --- /dev/null +++ b/tests/ui/thir-print/thir-tree-field-pat-names.stdout @@ -0,0 +1,460 @@ +DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf): +params: [ + Param { + ty: (u32, u32, u32) + ty_span: Some($DIR/thir-tree-field-pat-names.rs:13:19: 13:34 (#0)) + self_kind: None + hir_id: Some(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).1)) + param: Some( + Pat { + ty: (u32, u32, u32) + span: $DIR/thir-tree-field-pat-names.rs:13:16: 13:17 (#0) + kind: PatKind { + Binding { + name: "t" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).2)) + ty: (u32, u32, u32) + is_primary: true + is_shorthand: false + subpattern: None + } + } + } + ) + } +] +body: + Expr { + ty: () + temp_scope_id: 20 + span: $DIR/thir-tree-field-pat-names.rs:13:36: 18:2 (#0) + kind: + Scope { + region_scope: Node(20) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).20) + value: + Expr { + ty: () + temp_scope_id: 20 + span: $DIR/thir-tree-field-pat-names.rs:13:36: 18:2 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-field-pat-names.rs:13:36: 18:2 (#0) + region_scope: Node(3) + safety_mode: Safe + stmts: [ + Stmt { + kind: Let { + remainder_scope: Remainder { block: 3, first_statement_index: 0} + init_scope: Node(4) + pattern: + Pat { + ty: (u32, u32, u32) + span: $DIR/thir-tree-field-pat-names.rs:14:7: 14:14 (#0) + kind: PatKind { + Leaf { + subpatterns: [ + FieldPat { + field: 0 + pattern: + Pat { + ty: u32 + span: $DIR/thir-tree-field-pat-names.rs:14:8: 14:9 (#0) + kind: PatKind { + Binding { + name: "a" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).9)) + ty: u32 + is_primary: true + is_shorthand: false + subpattern: None + } + } + } + } + ] + } + } + } + , + initializer: Some( + Expr { + ty: (u32, u32, u32) + temp_scope_id: 5 + span: $DIR/thir-tree-field-pat-names.rs:14:17: 14:18 (#0) + kind: + Scope { + region_scope: Node(5) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).5) + value: + Expr { + ty: (u32, u32, u32) + temp_scope_id: 5 + span: $DIR/thir-tree-field-pat-names.rs:14:17: 14:18 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).2)) + } + } + } + } + ) + else_block: None + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).7) + span: $DIR/thir-tree-field-pat-names.rs:14:3: 14:18 (#0) + } + } + ] + expr: + Expr { + ty: () + temp_scope_id: 10 + span: $DIR/thir-tree-field-pat-names.rs:17:3: 17:29 (#0) + kind: + Scope { + region_scope: Node(10) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).10) + value: + Expr { + ty: () + temp_scope_id: 10 + span: $DIR/thir-tree-field-pat-names.rs:17:3: 17:29 (#0) + kind: + If { + if_then_scope: IfThen(19) + cond: + Expr { + ty: bool + temp_scope_id: 11 + span: $DIR/thir-tree-field-pat-names.rs:17:6: 17:25 (#0) + kind: + Scope { + region_scope: Node(11) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).11) + value: + Expr { + ty: bool + temp_scope_id: 11 + span: $DIR/thir-tree-field-pat-names.rs:17:6: 17:25 (#0) + kind: + Let { + expr: + Expr { + ty: (u32, u32, u32) + temp_scope_id: 16 + span: $DIR/thir-tree-field-pat-names.rs:17:24: 17:25 (#0) + kind: + Scope { + region_scope: Node(16) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).16) + value: + Expr { + ty: (u32, u32, u32) + temp_scope_id: 16 + span: $DIR/thir-tree-field-pat-names.rs:17:24: 17:25 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).2)) + } + } + } + } + pat: Pat { ty: (u32, u32, u32), span: $DIR/thir-tree-field-pat-names.rs:17:10: 17:21 (#0), extra: None, kind: Leaf { subpatterns: [FieldPat { field: 0, pattern: Pat { ty: u32, span: $DIR/thir-tree-field-pat-names.rs:17:11: 17:12 (#0), extra: None, kind: Binding { name: "a", mode: BindingMode(No, Not), var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).13)), ty: u32, subpattern: None, is_primary: true, is_shorthand: false } } }, FieldPat { field: 1, pattern: Pat { ty: u32, span: $DIR/thir-tree-field-pat-names.rs:17:14: 17:16 (#0), extra: None, kind: Constant { value: Value { ty: u32, valtree: Leaf(0x0000000c) } } } }] } } + } + } + } + } + then: + Expr { + ty: () + temp_scope_id: 19 + span: $DIR/thir-tree-field-pat-names.rs:17:26: 17:29 (#0) + kind: + Scope { + region_scope: Node(19) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::tuple_leaf).19) + value: + Expr { + ty: () + temp_scope_id: 19 + span: $DIR/thir-tree-field-pat-names.rs:17:26: 17:29 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-field-pat-names.rs:17:26: 17:29 (#0) + region_scope: Node(18) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + } + } + } + } + } + } + } + } + + +DefId(N:M ~ thir_tree_field_pat_names::struct_leaf): +params: [ + Param { + ty: Tri + ty_span: Some($DIR/thir-tree-field-pat-names.rs:20:20: 20:23 (#0)) + self_kind: None + hir_id: Some(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).1)) + param: Some( + Pat { + ty: Tri + span: $DIR/thir-tree-field-pat-names.rs:20:17: 20:18 (#0) + kind: PatKind { + Binding { + name: "s" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).2)) + ty: Tri + is_primary: true + is_shorthand: false + subpattern: None + } + } + } + ) + } +] +body: + Expr { + ty: () + temp_scope_id: 27 + span: $DIR/thir-tree-field-pat-names.rs:20:25: 25:2 (#0) + kind: + Scope { + region_scope: Node(27) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).27) + value: + Expr { + ty: () + temp_scope_id: 27 + span: $DIR/thir-tree-field-pat-names.rs:20:25: 25:2 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-field-pat-names.rs:20:25: 25:2 (#0) + region_scope: Node(3) + safety_mode: Safe + stmts: [ + Stmt { + kind: Let { + remainder_scope: Remainder { block: 3, first_statement_index: 0} + init_scope: Node(4) + pattern: + Pat { + ty: Tri + span: $DIR/thir-tree-field-pat-names.rs:21:7: 21:29 (#0) + kind: PatKind { + Leaf { + subpatterns: [ + FieldPat { + field: 2 + pattern: + Pat { + ty: u32 + span: $DIR/thir-tree-field-pat-names.rs:21:16: 21:17 (#0) + kind: PatKind { + Binding { + name: "d" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).11)) + ty: u32 + is_primary: true + is_shorthand: false + subpattern: None + } + } + } + } + FieldPat { + field: 1 + pattern: + Pat { + ty: u32 + span: $DIR/thir-tree-field-pat-names.rs:21:22: 21:23 (#0) + kind: PatKind { + Binding { + name: "e" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).13)) + ty: u32 + is_primary: true + is_shorthand: false + subpattern: None + } + } + } + } + ] + } + } + } + , + initializer: Some( + Expr { + ty: Tri + temp_scope_id: 5 + span: $DIR/thir-tree-field-pat-names.rs:21:32: 21:33 (#0) + kind: + Scope { + region_scope: Node(5) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).5) + value: + Expr { + ty: Tri + temp_scope_id: 5 + span: $DIR/thir-tree-field-pat-names.rs:21:32: 21:33 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).2)) + } + } + } + } + ) + else_block: None + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).7) + span: $DIR/thir-tree-field-pat-names.rs:21:3: 21:33 (#0) + } + } + ] + expr: + Expr { + ty: () + temp_scope_id: 14 + span: $DIR/thir-tree-field-pat-names.rs:24:3: 24:37 (#0) + kind: + Scope { + region_scope: Node(14) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).14) + value: + Expr { + ty: () + temp_scope_id: 14 + span: $DIR/thir-tree-field-pat-names.rs:24:3: 24:37 (#0) + kind: + If { + if_then_scope: IfThen(26) + cond: + Expr { + ty: bool + temp_scope_id: 15 + span: $DIR/thir-tree-field-pat-names.rs:24:6: 24:34 (#0) + kind: + Scope { + region_scope: Node(15) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).15) + value: + Expr { + ty: bool + temp_scope_id: 15 + span: $DIR/thir-tree-field-pat-names.rs:24:6: 24:34 (#0) + kind: + Let { + expr: + Expr { + ty: Tri + temp_scope_id: 23 + span: $DIR/thir-tree-field-pat-names.rs:24:33: 24:34 (#0) + kind: + Scope { + region_scope: Node(23) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).23) + value: + Expr { + ty: Tri + temp_scope_id: 23 + span: $DIR/thir-tree-field-pat-names.rs:24:33: 24:34 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).2)) + } + } + } + } + pat: Pat { ty: Tri, span: $DIR/thir-tree-field-pat-names.rs:24:10: 24:30 (#0), extra: None, kind: Leaf { subpatterns: [FieldPat { field: 1, pattern: Pat { ty: u32, span: $DIR/thir-tree-field-pat-names.rs:24:19: 24:21 (#0), extra: None, kind: Constant { value: Value { ty: u32, valtree: Leaf(0x0000000c) } } } }, FieldPat { field: 0, pattern: Pat { ty: u32, span: $DIR/thir-tree-field-pat-names.rs:24:23: 24:24 (#0), extra: None, kind: Binding { name: "x", mode: BindingMode(No, Not), var: LocalVarId(HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).22)), ty: u32, subpattern: None, is_primary: true, is_shorthand: true } } }] } } + } + } + } + } + then: + Expr { + ty: () + temp_scope_id: 26 + span: $DIR/thir-tree-field-pat-names.rs:24:35: 24:37 (#0) + kind: + Scope { + region_scope: Node(26) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::struct_leaf).26) + value: + Expr { + ty: () + temp_scope_id: 26 + span: $DIR/thir-tree-field-pat-names.rs:24:35: 24:37 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-field-pat-names.rs:24:35: 24:37 (#0) + region_scope: Node(25) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + } + } + } + } + } + } + } + } + + +DefId(N:M ~ thir_tree_field_pat_names::main): +params: [ +] +body: + Expr { + ty: () + temp_scope_id: 2 + span: $DIR/thir-tree-field-pat-names.rs:27:11: 27:13 (#0) + kind: + Scope { + region_scope: Node(2) + hir_id: HirId(DefId(N:M ~ thir_tree_field_pat_names::main).2) + value: + Expr { + ty: () + temp_scope_id: 2 + span: $DIR/thir-tree-field-pat-names.rs:27:11: 27:13 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-field-pat-names.rs:27:11: 27:13 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + + diff --git a/tests/ui/thir-print/thir-tree-match-for.stdout b/tests/ui/thir-print/thir-tree-match-for.stdout index b07b0c182a161..72dd2c578e446 100644 --- a/tests/ui/thir-print/thir-tree-match-for.stdout +++ b/tests/ui/thir-print/thir-tree-match-for.stdout @@ -720,20 +720,24 @@ body: args: [u32] variant_index: 1 subpatterns: [ - Pat { - ty: u32 - span: $DIR/thir-tree-match-for.rs:16:7: 16:8 (#0) - kind: PatKind { - Binding { - name: "i" - mode: BindingMode(No, Not) - var: LocalVarId(HirId(DefId(N:M ~ thir_tree_match_for::match_from_for).14)) + FieldPat { + field: 0 + pattern: + Pat { ty: u32 - is_primary: true - is_shorthand: false - subpattern: None + span: $DIR/thir-tree-match-for.rs:16:7: 16:8 (#0) + kind: PatKind { + Binding { + name: "i" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_match_for::match_from_for).14)) + ty: u32 + is_primary: true + is_shorthand: false + subpattern: None + } + } } - } } ] } @@ -1277,20 +1281,24 @@ body: args: [u32] variant_index: 1 subpatterns: [ - Pat { - ty: u32 - span: $DIR/thir-tree-match-for.rs:27:24: 27:25 (#0) - kind: PatKind { - Binding { - name: "i" - mode: BindingMode(No, Not) - var: LocalVarId(HirId(DefId(N:M ~ thir_tree_match_for::match_loop_nonfor).40)) + FieldPat { + field: 0 + pattern: + Pat { ty: u32 - is_primary: true - is_shorthand: false - subpattern: None + span: $DIR/thir-tree-match-for.rs:27:24: 27:25 (#0) + kind: PatKind { + Binding { + name: "i" + mode: BindingMode(No, Not) + var: LocalVarId(HirId(DefId(N:M ~ thir_tree_match_for::match_loop_nonfor).40)) + ty: u32 + is_primary: true + is_shorthand: false + subpattern: None + } + } } - } } ] } diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 70a936d663aba..189de85797ca8 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -100,23 +100,27 @@ body: args: [] variant_index: 0 subpatterns: [ - Pat { - ty: Bar - span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0) - kind: PatKind { - Variant { - adt_def: - AdtDef { - did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) - variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], tainted: None, flags: }] - flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: , scalable: None, field_shuffle_seed: 7908585036048874241 } + FieldPat { + field: 0 + pattern: + Pat { + ty: Bar + span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) + variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], tainted: None, flags: }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: , scalable: None, field_shuffle_seed: 7908585036048874241 } + } + args: [] + variant_index: 0 + subpatterns: [] } - args: [] - variant_index: 0 - subpatterns: [] + } } - } } ] } @@ -164,12 +168,16 @@ body: args: [] variant_index: 0 subpatterns: [ - Pat { - ty: Bar - span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0) - kind: PatKind { - Wild - } + FieldPat { + field: 0 + pattern: + Pat { + ty: Bar + span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0) + kind: PatKind { + Wild + } + } } ] }