Skip to content

Rollup of 6 pull requests #127924

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
@@ -556,6 +556,9 @@ lint_non_fmt_panic_unused =
}
.add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally

lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inherent`
.suggestion = try using a glob import instead

lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`

lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
46 changes: 45 additions & 1 deletion compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@

use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
TykindKind, UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
@@ -263,6 +264,49 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
String::new()
}

declare_tool_lint! {
/// The `non_glob_import_of_type_ir_inherent_item` lint detects
/// non-glob imports of module `rustc_type_ir::inherent`.
pub rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
Allow,
"non-glob import of `rustc_type_ir::inherent`",
report_in_external_macro: true
}

declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT]);

impl<'tcx> LateLintPass<'tcx> for TypeIr {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };

let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
let (lo, hi, snippet) = match path.segments {
[.., penultimate, segment]
if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>
{
(segment.ident.span, item.ident.span, "*")
}
[.., segment]
if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent)
&& let rustc_hir::UseKind::Single = kind =>
{
let (lo, snippet) =
match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() {
Ok("self") => (path.span, "*"),
_ => (segment.ident.span.shrink_to_hi(), "::*"),
};
(lo, if segment.ident == item.ident { lo } else { item.ident.span }, snippet)
}
_ => return,
};
cx.emit_span_lint(
NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
path.span,
NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet },
);
}
}

declare_tool_lint! {
/// The `lint_pass_impl_without_macro` detects manual implementations of a lint
/// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -572,6 +572,8 @@ fn register_internals(store: &mut LintStore) {
store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
store.register_lints(&TyTyKind::get_lints());
store.register_late_mod_pass(|_| Box::new(TyTyKind));
store.register_lints(&TypeIr::get_lints());
store.register_late_mod_pass(|_| Box::new(TypeIr));
store.register_lints(&Diagnostics::get_lints());
store.register_late_mod_pass(|_| Box::new(Diagnostics));
store.register_lints(&BadOptAccess::get_lints());
@@ -595,6 +597,7 @@ fn register_internals(store: &mut LintStore) {
LintId::of(PASS_BY_VALUE),
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
LintId::of(USAGE_OF_QUALIFIED_TY),
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
LintId::of(EXISTING_DOC_KEYWORD),
LintId::of(BAD_OPT_ACCESS),
LintId::of(SPAN_USE_EQ_CTXT),
8 changes: 8 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -926,6 +926,14 @@ pub struct TyQualified {
pub suggestion: Span,
}

#[derive(LintDiagnostic)]
#[diag(lint_non_glob_import_type_ir_inherent)]
pub struct NonGlobImportTypeIrInherent {
#[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
pub suggestion: Option<Span>,
pub snippet: &'static str,
}

#[derive(LintDiagnostic)]
#[diag(lint_lintpass_by_hand)]
#[help]
8 changes: 4 additions & 4 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1203,16 +1203,16 @@ declare_lint! {
/// This was historically allowed, but is not the intended behavior
/// according to the visibility rules. This is a [future-incompatible]
/// lint to transition this to a hard error in the future. See [issue
/// #34537] for more details.
/// #127909] for more details.
///
/// [issue #34537]: https://github.com/rust-lang/rust/issues/34537
/// [issue #127909]: https://github.com/rust-lang/rust/issues/127909
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
Deny,
"detect public re-exports of private extern crates",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #127909 <https://github.com/rust-lang/rust/issues/127909>",
};
}

1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1926,6 +1926,7 @@ symbols! {
type_ascription,
type_changing_struct_update,
type_id,
type_ir_inherent,
type_length_limit,
type_macros,
type_name,
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/effects.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::inherent::{AdtDef, IntoKind, Ty};
use crate::inherent::*;
use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
use crate::Interner;

1 change: 1 addition & 0 deletions compiler/rustc_type_ir/src/lib.rs
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ pub mod elaborate;
pub mod error;
pub mod fast_reject;
pub mod fold;
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")]
pub mod inherent;
pub mod ir_print;
pub mod lang_items;
24 changes: 17 additions & 7 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
@@ -770,6 +770,13 @@ impl<T> Option<T> {
}
}

#[inline]
const fn len(&self) -> usize {
// Using the intrinsic avoids emitting a branch to get the 0 or 1.
let discriminant: isize = crate::intrinsics::discriminant_value(self);
discriminant as usize
}

/// Returns a slice of the contained value, if any. If this is `None`, an
/// empty slice is returned. This can be useful to have a single type of
/// iterator over an `Option` or slice.
@@ -812,7 +819,7 @@ impl<T> Option<T> {
unsafe {
slice::from_raw_parts(
(self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
self.is_some() as usize,
self.len(),
)
}
}
@@ -869,7 +876,7 @@ impl<T> Option<T> {
unsafe {
slice::from_raw_parts_mut(
(self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
self.is_some() as usize,
self.len(),
)
}
}
@@ -2242,10 +2249,8 @@ impl<A> Iterator for Item<A> {

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.opt {
Some(_) => (1, Some(1)),
None => (0, Some(0)),
}
let len = self.len();
(len, Some(len))
}
}

@@ -2256,7 +2261,12 @@ impl<A> DoubleEndedIterator for Item<A> {
}
}

impl<A> ExactSizeIterator for Item<A> {}
impl<A> ExactSizeIterator for Item<A> {
#[inline]
fn len(&self) -> usize {
self.opt.len()
}
}
impl<A> FusedIterator for Item<A> {}
unsafe impl<A> TrustedLen for Item<A> {}

138 changes: 115 additions & 23 deletions library/std/src/sync/reentrant_lock.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;

use cfg_if::cfg_if;

use crate::cell::UnsafeCell;
use crate::fmt;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use crate::sys::sync as sys;
use crate::thread::{current_id, ThreadId};

/// A re-entrant mutual exclusion lock
///
@@ -53,8 +55,8 @@ use crate::sys::sync as sys;
//
// The 'owner' field tracks which thread has locked the mutex.
//
// We use current_thread_unique_ptr() as the thread identifier,
// which is just the address of a thread local variable.
// We use thread::current_id() as the thread identifier, which is just the
// current thread's ThreadId, so it's unique across the process lifetime.
//
// If `owner` is set to the identifier of the current thread,
// we assume the mutex is already locked and instead of locking it again,
@@ -72,14 +74,109 @@ use crate::sys::sync as sys;
// since we're not dealing with multiple threads. If it's not equal,
// synchronization is left to the mutex, making relaxed memory ordering for
// the `owner` field fine in all cases.
//
// On systems without 64 bit atomics we also store the address of a TLS variable
// along the 64-bit TID. We then first check that address against the address
// of that variable on the current thread, and only if they compare equal do we
// compare the actual TIDs. Because we only ever read the TID on the same thread
// that it was written on (or a thread sharing the TLS block with that writer thread),
// we don't need to further synchronize the TID accesses, so they can be regular 64-bit
// non-atomic accesses.
#[unstable(feature = "reentrant_lock", issue = "121440")]
pub struct ReentrantLock<T: ?Sized> {
mutex: sys::Mutex,
owner: AtomicUsize,
owner: Tid,
lock_count: UnsafeCell<u32>,
data: T,
}

cfg_if!(
if #[cfg(target_has_atomic = "64")] {
use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};

struct Tid(AtomicU64);

impl Tid {
const fn new() -> Self {
Self(AtomicU64::new(0))
}

#[inline]
fn contains(&self, owner: ThreadId) -> bool {
owner.as_u64().get() == self.0.load(Relaxed)
}

#[inline]
// This is just unsafe to match the API of the Tid type below.
unsafe fn set(&self, tid: Option<ThreadId>) {
let value = tid.map_or(0, |tid| tid.as_u64().get());
self.0.store(value, Relaxed);
}
}
} else {
/// Returns the address of a TLS variable. This is guaranteed to
/// be unique across all currently alive threads.
fn tls_addr() -> usize {
thread_local! { static X: u8 = const { 0u8 } };

X.with(|p| <*const u8>::addr(p))
}

use crate::sync::atomic::{
AtomicUsize,
Ordering,
};

struct Tid {
// When a thread calls `set()`, this value gets updated to
// the address of a thread local on that thread. This is
// used as a first check in `contains()`; if the `tls_addr`
// doesn't match the TLS address of the current thread, then
// the ThreadId also can't match. Only if the TLS addresses do
// match do we read out the actual TID.
// Note also that we can use relaxed atomic operations here, because
// we only ever read from the tid if `tls_addr` matches the current
// TLS address. In that case, either the the tid has been set by
// the current thread, or by a thread that has terminated before
// the current thread was created. In either case, no further
// synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
tls_addr: AtomicUsize,
tid: UnsafeCell<u64>,
}

unsafe impl Send for Tid {}
unsafe impl Sync for Tid {}

impl Tid {
const fn new() -> Self {
Self { tls_addr: AtomicUsize::new(0), tid: UnsafeCell::new(0) }
}

#[inline]
// NOTE: This assumes that `owner` is the ID of the current
// thread, and may spuriously return `false` if that's not the case.
fn contains(&self, owner: ThreadId) -> bool {
// SAFETY: See the comments in the struct definition.
self.tls_addr.load(Ordering::Relaxed) == tls_addr()
&& unsafe { *self.tid.get() } == owner.as_u64().get()
}

#[inline]
// This may only be called by one thread at a time, and can lead to
// race conditions otherwise.
unsafe fn set(&self, tid: Option<ThreadId>) {
// It's important that we set `self.tls_addr` to 0 if the tid is
// cleared. Otherwise, there might be race conditions between
// `set()` and `get()`.
let tls_addr = if tid.is_some() { tls_addr() } else { 0 };
let value = tid.map_or(0, |tid| tid.as_u64().get());
self.tls_addr.store(tls_addr, Ordering::Relaxed);
unsafe { *self.tid.get() = value };
}
}
}
);

#[unstable(feature = "reentrant_lock", issue = "121440")]
unsafe impl<T: Send + ?Sized> Send for ReentrantLock<T> {}
#[unstable(feature = "reentrant_lock", issue = "121440")]
@@ -134,7 +231,7 @@ impl<T> ReentrantLock<T> {
pub const fn new(t: T) -> ReentrantLock<T> {
ReentrantLock {
mutex: sys::Mutex::new(),
owner: AtomicUsize::new(0),
owner: Tid::new(),
lock_count: UnsafeCell::new(0),
data: t,
}
@@ -184,14 +281,16 @@ impl<T: ?Sized> ReentrantLock<T> {
/// assert_eq!(lock.lock().get(), 10);
/// ```
pub fn lock(&self) -> ReentrantLockGuard<'_, T> {
let this_thread = current_thread_unique_ptr();
// Safety: We only touch lock_count when we own the lock.
let this_thread = current_id();
// Safety: We only touch lock_count when we own the inner mutex.
// Additionally, we only call `self.owner.set()` while holding
// the inner mutex, so no two threads can call it concurrently.
unsafe {
if self.owner.load(Relaxed) == this_thread {
if self.owner.contains(this_thread) {
self.increment_lock_count().expect("lock count overflow in reentrant mutex");
} else {
self.mutex.lock();
self.owner.store(this_thread, Relaxed);
self.owner.set(Some(this_thread));
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
}
@@ -226,14 +325,16 @@ impl<T: ?Sized> ReentrantLock<T> {
///
/// This function does not block.
pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
let this_thread = current_thread_unique_ptr();
// Safety: We only touch lock_count when we own the lock.
let this_thread = current_id();
// Safety: We only touch lock_count when we own the inner mutex.
// Additionally, we only call `self.owner.set()` while holding
// the inner mutex, so no two threads can call it concurrently.
unsafe {
if self.owner.load(Relaxed) == this_thread {
if self.owner.contains(this_thread) {
self.increment_lock_count()?;
Some(ReentrantLockGuard { lock: self })
} else if self.mutex.try_lock() {
self.owner.store(this_thread, Relaxed);
self.owner.set(Some(this_thread));
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
Some(ReentrantLockGuard { lock: self })
@@ -308,18 +409,9 @@ impl<T: ?Sized> Drop for ReentrantLockGuard<'_, T> {
unsafe {
*self.lock.lock_count.get() -= 1;
if *self.lock.lock_count.get() == 0 {
self.lock.owner.store(0, Relaxed);
self.lock.owner.set(None);
self.lock.mutex.unlock();
}
}
}
}

/// Get an address that is unique per running thread.
///
/// This can be used as a non-null usize-sized ID.
pub(crate) fn current_thread_unique_ptr() -> usize {
// Use a non-drop type to make sure it's still available during thread destruction.
thread_local! { static X: u8 = const { 0 } }
X.with(|x| <*const _>::addr(x))
}
32 changes: 29 additions & 3 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
@@ -159,7 +159,7 @@
mod tests;

use crate::any::Any;
use crate::cell::{OnceCell, UnsafeCell};
use crate::cell::{Cell, OnceCell, UnsafeCell};
use crate::env;
use crate::ffi::{CStr, CString};
use crate::fmt;
@@ -699,17 +699,22 @@ where
}

thread_local! {
// Invariant: `CURRENT` and `CURRENT_ID` will always be initialized together.
// If `CURRENT` is initialized, then `CURRENT_ID` will hold the same value
// as `CURRENT.id()`.
static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
static CURRENT_ID: Cell<Option<ThreadId>> = const { Cell::new(None) };
}

/// Sets the thread handle for the current thread.
///
/// Aborts if the handle has been set already to reduce code size.
pub(crate) fn set_current(thread: Thread) {
let tid = thread.id();
// Using `unwrap` here can add ~3kB to the binary size. We have complete
// control over where this is called, so just abort if there is a bug.
CURRENT.with(|current| match current.set(thread) {
Ok(()) => {}
Ok(()) => CURRENT_ID.set(Some(tid)),
Err(_) => rtabort!("thread::set_current should only be called once per thread"),
});
}
@@ -719,7 +724,28 @@ pub(crate) fn set_current(thread: Thread) {
/// In contrast to the public `current` function, this will not panic if called
/// from inside a TLS destructor.
pub(crate) fn try_current() -> Option<Thread> {
CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok()
CURRENT
.try_with(|current| {
current
.get_or_init(|| {
let thread = Thread::new_unnamed();
CURRENT_ID.set(Some(thread.id()));
thread
})
.clone()
})
.ok()
}

/// Gets the id of the thread that invokes it.
#[inline]
pub(crate) fn current_id() -> ThreadId {
CURRENT_ID.get().unwrap_or_else(|| {
// If `CURRENT_ID` isn't initialized yet, then `CURRENT` must also not be initialized.
// `current()` will initialize both `CURRENT` and `CURRENT_ID` so subsequent calls to
// `current_id()` will succeed immediately.
current().id()
})
}

/// Gets a handle to the thread that invokes it.
1 change: 1 addition & 0 deletions src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -535,6 +535,7 @@ impl Build {
// even though that has no relation to the upstream for the submodule.
let current_branch = helpers::git(Some(&self.src))
.capture_stdout()
.allow_failure()
.run_always()
.args(["symbolic-ref", "--short", "HEAD"])
.run(self)
15 changes: 9 additions & 6 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
@@ -410,13 +410,16 @@ See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag.

By default, `rustc` prefers to statically link dependencies. This option will
indicate that dynamic linking should be used if possible if both a static and
dynamic versions of a library are available. There is an internal algorithm
for determining whether or not it is possible to statically or dynamically
link with a dependency. For example, `cdylib` crate types may only use static
linkage. This flag takes one of the following values:
dynamic versions of a library are available.

* `y`, `yes`, `on`, `true` or no value: use dynamic linking.
* `n`, `no`, `off` or `false`: use static linking (the default).
There is [an internal algorithm](https://github.com/rust-lang/rust/blob/master/compiler/rustc_metadata/src/dependency_format.rs)
for determining whether or not it is possible to statically or dynamically link
with a dependency.

This flag takes one of the following values:

* `y`, `yes`, `on`, `true` or no value: prefer dynamic linking.
* `n`, `no`, `off` or `false`: prefer static linking (the default).

## profile-generate

35 changes: 34 additions & 1 deletion tests/codegen/option-as-slice.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,14 @@ pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
// CHECK-NOT: br
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[LEN:.+]] = load i64,{{.+}} !range ![[META_U64:.+]], !noundef
// CHECK-NOT: select
// CHECK-NOT: br
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
// CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
// CHECK-NEXT: ret { ptr, i64 } %[[T1]]
o.as_slice()
}

@@ -25,10 +33,35 @@ pub fn nonzero_u64_opt_as_slice(o: &Option<NonZero<u64>>) -> &[NonZero<u64>] {
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[NZ:.+]] = icmp ne i64 %{{.+}}, 0
// CHECK-NEXT: zext i1 %[[NZ]] to i64
// CHECK-NEXT: %[[LEN:.+]] = zext i1 %[[NZ]] to i64
// CHECK-NOT: select
// CHECK-NOT: br
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %o, 0
// CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
// CHECK-NEXT: ret { ptr, i64 } %[[T1]]
o.as_slice()
}

// CHECK-LABEL: @u8_opt_as_slice
#[no_mangle]
pub fn u8_opt_as_slice(o: &Option<u8>) -> &[u8] {
// CHECK-NOT: select
// CHECK-NOT: br
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[TAG:.+]] = load i8,{{.+}} !range ![[META_U8:.+]], !noundef
// CHECK: %[[LEN:.+]] = zext{{.*}} i8 %[[TAG]] to i64
// CHECK-NOT: select
// CHECK-NOT: br
// CHECK-NOT: switch
// CHECK-NOT: icmp
// CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
// CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
// CHECK-NEXT: ret { ptr, i64 } %[[T1]]
o.as_slice()
}

// CHECK: ![[META_U64]] = !{i64 0, i64 2}
// CHECK: ![[META_U8]] = !{i8 0, i8 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//@ compile-flags: -Z unstable-options
//@ ignore-stage1 (can be removed after beta bump, #[cfg(bootstrap)])
#![feature(rustc_private)]
#![deny(rustc::non_glob_import_of_type_ir_inherent)]

extern crate rustc_type_ir;

mod ok {
use rustc_type_ir::inherent::*; // OK
use rustc_type_ir::inherent::{}; // OK
use rustc_type_ir::inherent::{*}; // OK

fn usage<T: rustc_type_ir::inherent::SliceLike>() {} // OK
}

mod direct {
use rustc_type_ir::inherent::Predicate; //~ ERROR non-glob import of `rustc_type_ir::inherent`
use rustc_type_ir::inherent::{AdtDef, Ty};
//~^ ERROR non-glob import of `rustc_type_ir::inherent`
//~| ERROR non-glob import of `rustc_type_ir::inherent`
use rustc_type_ir::inherent::ParamEnv as _; //~ ERROR non-glob import of `rustc_type_ir::inherent`
}

mod indirect0 {
use rustc_type_ir::inherent; //~ ERROR non-glob import of `rustc_type_ir::inherent`
use rustc_type_ir::inherent as inh; //~ ERROR non-glob import of `rustc_type_ir::inherent`
use rustc_type_ir::{inherent as _}; //~ ERROR non-glob import of `rustc_type_ir::inherent`

fn usage0<T: inherent::SliceLike>() {}
fn usage1<T: inh::SliceLike>() {}
}

mod indirect1 {
use rustc_type_ir::inherent::{self}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
use rustc_type_ir::inherent::{self as innate}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:17:9
|
LL | use rustc_type_ir::inherent::Predicate;
| ^^^^^^^^^^^^^^^^^^^^^^^^^---------
| |
| help: try using a glob import instead: `*`
|
note: the lint level is defined here
--> $DIR/non_glob_import_of_type_ir_inherent.rs:4:9
|
LL | #![deny(rustc::non_glob_import_of_type_ir_inherent)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:18:35
|
LL | use rustc_type_ir::inherent::{AdtDef, Ty};
| ^^^^^^ help: try using a glob import instead: `*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:18:43
|
LL | use rustc_type_ir::inherent::{AdtDef, Ty};
| ^^ help: try using a glob import instead: `*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:21:9
|
LL | use rustc_type_ir::inherent::ParamEnv as _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^-------------
| |
| help: try using a glob import instead: `*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
|
LL | use rustc_type_ir::inherent;
| ^^^^^^^^^^^^^^^^^^^^^^^- help: try using a glob import instead: `::*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:26:9
|
LL | use rustc_type_ir::inherent as inh;
| ^^^^^^^^^^^^^^^^^^^^^^^------- help: try using a glob import instead: `::*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:27:25
|
LL | use rustc_type_ir::{inherent as _};
| ^^^^^^^^----- help: try using a glob import instead: `::*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
|
LL | use rustc_type_ir::inherent::{self};
| ^^^^ help: try using a glob import instead: `*`

error: non-glob import of `rustc_type_ir::inherent`
--> $DIR/non_glob_import_of_type_ir_inherent.rs:35:35
|
LL | use rustc_type_ir::inherent::{self as innate};
| ^^^^----------
| |
| help: try using a glob import instead: `*`

error: aborting due to 9 previous errors

17 changes: 16 additions & 1 deletion tests/ui/pub/pub-reexport-priv-extern-crate.stderr
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ LL | pub use core as reexported_core;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
= note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
= note: `#[deny(pub_use_of_private_extern_crate)]` on by default
help: consider making the `extern crate` item publicly accessible
|
@@ -40,3 +40,18 @@ error: aborting due to 3 previous errors

Some errors have detailed explanations: E0365, E0603.
For more information about an error, try `rustc --explain E0365`.
Future incompatibility report: Future breakage diagnostic:
error[E0365]: extern crate `core` is private and cannot be re-exported
--> $DIR/pub-reexport-priv-extern-crate.rs:2:9
|
LL | pub use core as reexported_core;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
= note: `#[deny(pub_use_of_private_extern_crate)]` on by default
help: consider making the `extern crate` item publicly accessible
|
LL | pub extern crate core;
| +++