Skip to content

Rollup of 7 pull requests #138714

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 16 commits into from
Mar 20, 2025
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
61f7000
Add helper methods checking for "#[non_exhaustive] that's active"
meithecatte Mar 3, 2025
044deec
mir_build: consider privacy when checking for irrefutable patterns
meithecatte Mar 4, 2025
8269132
Add inherent versions of MaybeUninit::fill methods for slices
clarfonthey Aug 18, 2024
523b9d9
Implement default methods for io::Empty and io::Sink
thaliaarchi Feb 14, 2025
e1388bf
core/slice: Mark some `split_off` variants unstably const
okaneco Mar 15, 2025
f478853
If a label is placed on the block of a loop instead of the header, su…
zachs18 Mar 17, 2025
6c865c1
Allow builtin macros to be used more than once.
m-ou-se Mar 17, 2025
055d31c
Demonstrate next-solver missing diagnostic
oli-obk Mar 17, 2025
14cd467
Fix next solver handling of shallow trait impl check
oli-obk Mar 17, 2025
d46cc71
Rollup merge of #135394 - clarfonthey:uninit-slices-part-2, r=tgross35
matthiaskrgr Mar 19, 2025
ce76292
Rollup merge of #137051 - thaliaarchi:io-optional-impls/empty, r=m-ou-se
matthiaskrgr Mar 19, 2025
2ab69b8
Rollup merge of #138001 - meithecatte:privately-uninhabited, r=Nadrieril
matthiaskrgr Mar 19, 2025
2df731d
Rollup merge of #138540 - okaneco:const_split_off_first_last, r=m-ou-se
matthiaskrgr Mar 19, 2025
c3f74bc
Rollup merge of #138589 - zachs18:block-label-not-supported-here-loop…
matthiaskrgr Mar 19, 2025
9ab2a0e
Rollup merge of #138594 - oli-obk:no-select, r=lcnr
matthiaskrgr Mar 19, 2025
966021d
Rollup merge of #138613 - m-ou-se:no-more-e0773, r=jdonszelmann,petro…
matthiaskrgr Mar 19, 2025
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
14 changes: 8 additions & 6 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -23,6 +23,8 @@

extern crate proc_macro;

use std::sync::Arc;

use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
use rustc_span::sym;
@@ -67,13 +69,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
macro register_bang($($name:ident: $f:expr,)*) {
$(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)*
$(register(sym::$name, SyntaxExtensionKind::LegacyBang(Arc::new($f as MacroExpanderFn)));)*
}
macro register_attr($($name:ident: $f:expr,)*) {
$(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)*
$(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Arc::new($f)));)*
}
macro register_derive($($name:ident: $f:expr,)*) {
$(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)*
$(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Arc::new(BuiltinDerive($f))));)*
}

register_bang! {
@@ -139,9 +141,9 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
}

let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })));
let requires = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandRequires));
register(sym::quote, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })));
let requires = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandRequires));
register(sym::contracts_requires, requires);
let ensures = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandEnsures));
let ensures = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandEnsures));
register(sym::contracts_ensures, ensures);
}
42 changes: 3 additions & 39 deletions compiler/rustc_error_codes/src/error_codes/E0773.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,4 @@
A builtin-macro was defined more than once.
#### this error code is no longer emitted by the compiler.

Erroneous code example:

```compile_fail,E0773
#![feature(decl_macro)]
#![feature(rustc_attrs)]
#![allow(internal_features)]

#[rustc_builtin_macro]
pub macro test($item:item) {
/* compiler built-in */
}

mod inner {
#[rustc_builtin_macro]
pub macro test($item:item) {
/* compiler built-in */
}
}
```

To fix the issue, remove the duplicate declaration:

```
#![feature(decl_macro)]
#![feature(rustc_attrs)]
#![allow(internal_features)]

#[rustc_builtin_macro]
pub macro test($item:item) {
/* compiler built-in */
}
```

In very rare edge cases, this may happen when loading `core` or `std` twice,
once with `check` metadata and once with `build` metadata.
For more information, see [#75176].

[#75176]: https://github.com/rust-lang/rust/pull/75176#issuecomment-683234468
This was triggered when multiple macro definitions used the same
`#[rustc_builtin_macro(..)]`. This is no longer an error.
21 changes: 11 additions & 10 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
@@ -681,33 +681,34 @@ impl MacResult for DummyResult {
}

/// A syntax extension kind.
#[derive(Clone)]
pub enum SyntaxExtensionKind {
/// A token-based function-like macro.
Bang(
/// An expander with signature TokenStream -> TokenStream.
Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
Arc<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
),

/// An AST-based function-like macro.
LegacyBang(
/// An expander with signature TokenStream -> AST.
Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
Arc<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
),

/// A token-based attribute macro.
Attr(
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
/// The first TokenStream is the attribute itself, the second is the annotated item.
/// The produced TokenStream replaces the input TokenStream.
Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
Arc<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
),

/// An AST-based attribute macro.
LegacyAttr(
/// An expander with signature (AST, AST) -> AST.
/// The first AST fragment is the attribute itself, the second is the annotated item.
/// The produced AST fragment replaces the input AST fragment.
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
),

/// A trivial attribute "macro" that does nothing,
@@ -724,18 +725,18 @@ pub enum SyntaxExtensionKind {
/// is handled identically to `LegacyDerive`. It should be migrated to
/// a token-based representation like `Bang` and `Attr`, instead of
/// using `MultiItemModifier`.
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
),

/// An AST-based derive macro.
LegacyDerive(
/// An expander with signature AST -> AST.
/// The produced AST fragment is appended to the input AST fragment.
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
),

/// A glob delegation.
GlobDelegation(Box<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
}

/// A struct representing a macro definition in "lowered" form ready for expansion.
@@ -937,7 +938,7 @@ impl SyntaxExtension {
cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"),
))
}
SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition)
SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Arc::new(expander)), edition)
}

/// A dummy derive macro `#[derive(Foo)]`.
@@ -950,7 +951,7 @@ impl SyntaxExtension {
) -> Vec<Annotatable> {
Vec::new()
}
SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition)
SyntaxExtension::default(SyntaxExtensionKind::Derive(Arc::new(expander)), edition)
}

pub fn non_macro_attr(edition: Edition) -> SyntaxExtension {
@@ -980,7 +981,7 @@ impl SyntaxExtension {
}

let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition)
SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition)
}

pub fn expn_data(
5 changes: 3 additions & 2 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::sync::Arc;
use std::{mem, slice};

use ast::token::IdentIsRaw;
@@ -388,7 +389,7 @@ pub fn compile_declarative_macro(
node_id != DUMMY_NODE_ID,
)
};
let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new());
let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), Vec::new());

let lhs_nm = Ident::new(sym::lhs, span);
let rhs_nm = Ident::new(sym::rhs, span);
@@ -582,7 +583,7 @@ pub fn compile_declarative_macro(
})
.collect();

let expander = Box::new(MacroRulesMacroExpander {
let expander = Arc::new(MacroRulesMacroExpander {
name: ident,
span,
node_id,
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
@@ -43,7 +43,6 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef, elaborate};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::{DUMMY_SP, Span, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::{debug, instrument};
@@ -805,7 +804,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
_ => return Err(CastError::NonScalar),
};
if let ty::Adt(adt_def, _) = *self.expr_ty.kind()
&& adt_def.did().krate != LOCAL_CRATE
&& !adt_def.did().is_local()
&& adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive)
{
return Err(CastError::ForeignNonExhaustiveAdt);
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1977,7 +1977,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Prohibit struct expressions when non-exhaustive flag is set.
let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
if !adt.did().is_local() && variant.is_field_list_non_exhaustive() {
if variant.field_list_has_applicable_non_exhaustive() {
self.dcx()
.emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });
}
11 changes: 2 additions & 9 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ use rustc_middle::hir::place::ProjectionKind;
pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{
self, AdtKind, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{ErrorGuaranteed, Span};
@@ -1899,14 +1899,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// to assume that more cases will be added to the variant in the future. This mean
// that we should handle non-exhaustive SingleVariant the same way we would handle
// a MultiVariant.
// If the variant is not local it must be defined in another crate.
let is_non_exhaustive = match def.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
def.non_enum_variant().is_field_list_non_exhaustive()
}
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
};
def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
def.variants().len() > 1 || def.variant_list_has_applicable_non_exhaustive()
} else {
false
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
@@ -1724,7 +1724,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

// Require `..` if struct has non_exhaustive attribute.
let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
let non_exhaustive = variant.field_list_has_applicable_non_exhaustive();
if non_exhaustive && !has_rest_pat {
self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
}
12 changes: 4 additions & 8 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
@@ -1193,9 +1193,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
};
}

let is_non_exhaustive =
def.non_enum_variant().is_field_list_non_exhaustive();
if is_non_exhaustive && !def.did().is_local() {
if def.non_enum_variant().field_list_has_applicable_non_exhaustive() {
return FfiUnsafe {
ty,
reason: if def.is_struct() {
@@ -1248,14 +1246,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
};
}

use improper_ctypes::{
check_non_exhaustive_variant, non_local_and_non_exhaustive,
};
use improper_ctypes::check_non_exhaustive_variant;

let non_local_def = non_local_and_non_exhaustive(def);
let non_exhaustive = def.variant_list_has_applicable_non_exhaustive();
// Check the contained variants.
let ret = def.variants().iter().try_for_each(|variant| {
check_non_exhaustive_variant(non_local_def, variant)
check_non_exhaustive_variant(non_exhaustive, variant)
.map_break(|reason| FfiUnsafe { ty, reason, help: None })?;

match self.check_variant_for_ffi(acc, ty, def, variant, args) {
14 changes: 3 additions & 11 deletions compiler/rustc_lint/src/types/improper_ctypes.rs
Original file line number Diff line number Diff line change
@@ -15,13 +15,13 @@ use crate::fluent_generated as fluent;
/// so we don't need the lint to account for it.
/// e.g. going from enum Foo { A, B, C } to enum Foo { A, B, C, D(u32) }.
pub(crate) fn check_non_exhaustive_variant(
non_local_def: bool,
non_exhaustive_variant_list: bool,
variant: &ty::VariantDef,
) -> ControlFlow<DiagMessage, ()> {
// non_exhaustive suggests it is possible that someone might break ABI
// see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344
// so warn on complex enums being used outside their crate
if non_local_def {
if non_exhaustive_variant_list {
// which is why we only warn about really_tagged_union reprs from https://rust.tf/rfc2195
// with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }`
// but exempt enums with unit ctors like C's (e.g. from rust-bindgen)
@@ -30,8 +30,7 @@ pub(crate) fn check_non_exhaustive_variant(
}
}

let non_exhaustive_variant_fields = variant.is_field_list_non_exhaustive();
if non_exhaustive_variant_fields && !variant.def_id.is_local() {
if variant.field_list_has_applicable_non_exhaustive() {
return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant);
}

@@ -42,10 +41,3 @@ fn variant_has_complex_ctor(variant: &ty::VariantDef) -> bool {
// CtorKind::Const means a "unit" ctor
!matches!(variant.ctor_kind(), Some(CtorKind::Const))
}

// non_exhaustive suggests it is possible that someone might break ABI
// see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344
// so warn on complex enums being used outside their crate
pub(crate) fn non_local_and_non_exhaustive(def: ty::AdtDef<'_>) -> bool {
def.is_variant_list_non_exhaustive() && !def.did().is_local()
}
6 changes: 3 additions & 3 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
@@ -1053,15 +1053,15 @@ impl<'a> CrateMetadataRef<'a> {
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(
trait_name,
SyntaxExtensionKind::Derive(Box::new(DeriveProcMacro { client })),
SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })),
helper_attrs,
)
}
ProcMacro::Attr { name, client } => {
(name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new())
(name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new())
}
ProcMacro::Bang { name, client } => {
(name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new())
(name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new())
}
};

11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
@@ -327,11 +327,22 @@ impl<'tcx> AdtDef<'tcx> {
}

/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
///
/// Note that this function will return `true` even if the ADT has been
/// defined in the crate currently being compiled. If that's not what you
/// want, see [`Self::variant_list_has_applicable_non_exhaustive`].
#[inline]
pub fn is_variant_list_non_exhaustive(self) -> bool {
self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}

/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`
/// and has been defined in another crate.
#[inline]
pub fn variant_list_has_applicable_non_exhaustive(self) -> bool {
self.is_variant_list_non_exhaustive() && !self.did().is_local()
}

/// Returns the kind of the ADT.
#[inline]
pub fn adt_kind(self) -> AdtKind {
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
@@ -107,7 +107,7 @@ impl<'tcx> Ty<'tcx> {
// For now, unions are always considered inhabited
Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
// Non-exhaustive ADTs from other crates are always considered inhabited
Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
Adt(adt, _) if adt.variant_list_has_applicable_non_exhaustive() => {
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -1208,12 +1208,23 @@ impl VariantDef {
}
}

/// Is this field list non-exhaustive?
/// Returns `true` if the field list of this variant is `#[non_exhaustive]`.
///
/// Note that this function will return `true` even if the type has been
/// defined in the crate currently being compiled. If that's not what you
/// want, see [`Self::field_list_has_applicable_non_exhaustive`].
#[inline]
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}

/// Returns `true` if the field list of this variant is `#[non_exhaustive]`
/// and the type has been defined in another crate.
#[inline]
pub fn field_list_has_applicable_non_exhaustive(&self) -> bool {
self.is_field_list_non_exhaustive() && !self.def_id.is_local()
}

/// Computes the `Ident` of this variant by looking up the `Span`
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
Loading