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
Show file tree
Hide file tree
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
Expand Up @@ -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;
Expand Down Expand Up @@ -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! {
Expand Down Expand Up @@ -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
Expand Up @@ -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,
Expand All @@ -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.
Expand Down Expand Up @@ -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)]`.
Expand All @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down
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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() });
}
Expand Down
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
Expand Up @@ -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};
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 3 additions & 11 deletions compiler/rustc_lint/src/types/improper_ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
}

Expand All @@ -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
Expand Up @@ -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())
}
};

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Loading
Loading