Auto merge of #133803 - matthiaskrgr:rollup-8ag5ncy, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #132612 (Gate async fn trait bound modifier on `async_trait_bounds`)
 - #133545 (Lint against Symbol::intern on a string literal)
 - #133558 (Structurally resolve in `probe_adt`)
 - #133696 (stabilize const_collections_with_hasher and build_hasher_default_const_new)
 - #133753 (Reduce false positives on some common cases from if-let-rescope lint)
 - #133762 (stabilize const_{size,align}_of_val)
 - #133777 (document -Zrandomize-layout in the unstable book)
 - #133779 (Use correct `hir_id` for array const arg infers)
 - #133796 (Update the definition of `borrowing_sub`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-03 18:16:53 +00:00
commit c44b3d50fe
106 changed files with 438 additions and 224 deletions

View File

@ -2011,7 +2011,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Underscore => {
if self.tcx.features().generic_arg_infer() {
let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
self.arena
.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind })
} else {
feature_err(
&self.tcx.sess,

View File

@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token};
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
use rustc_session::Session;
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_span::Span;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use rustc_span::symbol::{Symbol, sym};
use rustc_target::spec::abi;
use thin_vec::ThinVec;
@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
gate_all!(
async_trait_bounds,
"`async` trait bounds are unstable",
"use the desugared name of the async trait, such as `AsyncFn`"
);
gate_all!(async_for_loop, "`for await` loops are experimental");
gate_all!(
closure_lifetime_binder,
@ -690,6 +695,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
.find(|feat| feat.gate_name == sym::generic_const_exprs)
.map(|feat| feat.attr_sp)
{
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
sess.dcx().emit_err(errors::IncompatibleFeatures {
spans: vec![gce_span],
f1: Symbol::intern("-Znext-solver=globally"),

View File

@ -33,8 +33,8 @@ use rustc_middle::ty::{
TyCtxt, TypeVisitableExt,
};
use rustc_middle::{bug, span_bug};
use rustc_span::ErrorGuaranteed;
use rustc_span::symbol::{kw, sym};
use rustc_span::{ErrorGuaranteed, Symbol};
use tracing::{debug, instrument};
use crate::BorrowckInferCtxt;
@ -524,7 +524,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let reg_vid = self
.infcx
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
.next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic))
.as_var();
let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
@ -540,10 +540,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
}
let fr_fn_body = self
.infcx
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
.as_var();
let fr_fn_body =
self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var();
let num_universals = self.infcx.num_region_vars();

View File

@ -74,7 +74,7 @@ fn create_jit_module(
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"));
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
crate::allocator::codegen(tcx, &mut jit_module);
@ -276,12 +276,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
let mut cx = crate::CodegenCx::new(
tcx,
jit_module.isa(),
false,
Symbol::intern("dummy_cgu_name"),
);
let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
assert!(cx.global_asm.is_empty());

View File

@ -189,18 +189,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
if sess.target.arch == "x86_64" && sess.target.os != "none" {
// x86_64 mandates SSE2 support
vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")]
vec![sym::fsxr, sym::sse, sym::sse2]
} else if sess.target.arch == "aarch64" {
match &*sess.target.os {
"none" => vec![],
// On macOS the aes, sha2 and sha3 features are enabled by default and ring
// fails to compile on macOS when they are not present.
"macos" => vec![
sym::neon,
Symbol::intern("aes"),
Symbol::intern("sha2"),
Symbol::intern("sha3"),
],
"macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
// AArch64 mandates Neon support
_ => vec![sym::neon],
}

View File

@ -394,6 +394,8 @@ declare_features! (
(unstable, async_fn_track_caller, "1.73.0", Some(110011)),
/// Allows `for await` loops.
(unstable, async_for_loop, "1.77.0", Some(118898)),
/// Allows `async` trait bound modifier.
(unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg(<true/false>)]`.

View File

@ -419,7 +419,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
if let Node::ConstBlock(_) = node {
own_params.push(ty::GenericParamDef {
index: next_index(),
name: Symbol::intern("<const_ty>"),
name: rustc_span::sym::const_ty_placeholder,
def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },

View File

@ -307,7 +307,11 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _)
if !ty.has_escaping_bound_vars() =>
{
self.normalize(span, ty).ty_adt_def()
if self.next_trait_solver() {
self.try_structurally_resolve_type(span, ty).ty_adt_def()
} else {
self.normalize(span, ty).ty_adt_def()
}
}
_ => None,
}

View File

@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_name.name == Symbol::intern("write_fmt");
}) && item_name.name == sym::write_fmt;
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
self.suggest_missing_writer(rcvr_ty, rcvr_expr)
} else {

View File

@ -775,6 +775,9 @@ lint_suspicious_double_ref_clone =
lint_suspicious_double_ref_deref =
using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
.help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs`
lint_trailing_semi_macro = trailing semicolon in macro used in expression position
.note1 = macro invocations at the end of a block are treated as expressions
.note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`

View File

@ -103,8 +103,11 @@ fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
}
fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else {
return false;
let mut parents = tcx.hir().parent_iter(hir_id);
let stmt = match parents.next() {
Some((_, hir::Node::Stmt(stmt))) => stmt,
Some((_, hir::Node::Block(_) | hir::Node::Arm(_))) => return true,
_ => return false,
};
let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false };
expr.hir_id == hir_id

View File

@ -17,8 +17,9 @@ use tracing::debug;
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -650,3 +651,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
_ => false,
}
}
declare_tool_lint! {
/// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal
pub rustc::SYMBOL_INTERN_STRING_LITERAL,
// rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols;
// bootstrap will deny this manually
Allow,
"Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead",
report_in_external_macro: true
}
declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let ExprKind::Call(path, [arg]) = expr.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
&& let ExprKind::Lit(kind) = arg.kind
&& let rustc_ast::LitKind::Str(_, _) = kind.node
{
cx.emit_span_lint(
SYMBOL_INTERN_STRING_LITERAL,
kind.span,
SymbolInternStringLiteralDiag,
);
}
}
}

View File

@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) {
store.register_late_mod_pass(|_| Box::new(PassByValue));
store.register_lints(&SpanUseEqCtxt::lint_vec());
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
store.register_lints(&SymbolInternStringLiteral::lint_vec());
store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral));
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
// these lints will trigger all of the time - change this once migration to diagnostic structs

View File

@ -907,6 +907,11 @@ pub(crate) struct QueryUntracked {
#[diag(lint_span_use_eq_ctxt)]
pub(crate) struct SpanUseEqCtxtDiag;
#[derive(LintDiagnostic)]
#[diag(lint_symbol_intern_string_literal)]
#[help]
pub(crate) struct SymbolInternStringLiteralDiag;
#[derive(LintDiagnostic)]
#[diag(lint_tykind_kind)]
pub(crate) struct TykindKind {

View File

@ -1563,7 +1563,7 @@ impl UnusedImportBraces {
}
rename.unwrap_or(orig_ident).name
}
ast::UseTreeKind::Glob => Symbol::intern("*"),
ast::UseTreeKind::Glob => sym::asterisk,
ast::UseTreeKind::Nested { .. } => return,
};

View File

@ -861,8 +861,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// First up we check for global allocators. Look at the crate graph here
// and see what's a global allocator, including if we ourselves are a
// global allocator.
let mut global_allocator =
self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
let this_crate = Symbol::intern("this crate");
let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate);
for (_, data) in self.cstore.iter_crate_data() {
if data.has_global_allocator() {
match global_allocator {
@ -876,8 +878,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
}
}
let mut alloc_error_handler =
self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate"));
let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate);
for (_, data) in self.cstore.iter_crate_data() {
if data.has_alloc_error_handler() {
match alloc_error_handler {

View File

@ -872,6 +872,7 @@ impl MetadataBlob {
let def_kind = root.tables.def_kind.get(blob, item).unwrap();
let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
let def_name = if item == CRATE_DEF_INDEX {
rustc_span::symbol::kw::Crate
} else {

View File

@ -1389,10 +1389,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// `ConstArgKind::Path`. We never actually access this `DefId`
// anywhere so we don't need to encode it for other crates.
if def_kind == DefKind::AnonConst
&& matches!(
tcx.hir_node_by_def_id(local_id),
hir::Node::ConstArg(hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. })
)
&& match tcx.hir_node_by_def_id(local_id) {
hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind {
// Skip encoding defs for these as they should not have had a `DefId` created
hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true,
hir::ConstArgKind::Anon(..) => false,
},
_ => false,
}
{
continue;
}

View File

@ -9,7 +9,7 @@ use rustc_ast::{
};
use rustc_errors::{Applicability, PResult};
use rustc_span::symbol::{Ident, kw, sym};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_span::{ErrorGuaranteed, Span};
use thin_vec::{ThinVec, thin_vec};
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
@ -940,7 +940,7 @@ impl<'a> Parser<'a> {
let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
&& self.eat_keyword(kw::Async)
{
self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
BoundAsyncness::Async(self.prev_token.span)
} else if self.may_recover()
&& self.token.uninterpolated_span().is_rust_2015()
@ -951,7 +951,7 @@ impl<'a> Parser<'a> {
span: self.prev_token.span,
help: HelpUseLatestEdition::new(),
});
self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
BoundAsyncness::Async(self.prev_token.span)
} else {
BoundAsyncness::Normal
@ -1136,7 +1136,7 @@ impl<'a> Parser<'a> {
Some(ast::Path {
span: fn_token_span.to(self.prev_token.span),
segments: thin_vec![ast::PathSegment {
ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
ident: Ident::new(sym::Fn, fn_token_span),
id: DUMMY_NODE_ID,
args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
span: args_lo.to(self.prev_token.span),

View File

@ -3113,6 +3113,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
let existing_name = match &in_scope_lifetimes[..] {
[] => Symbol::intern("'a"),
[(existing, _)] => existing.name,

View File

@ -2257,7 +2257,7 @@ fn module_to_string(module: Module<'_>) -> Option<String> {
collect_mod(names, parent);
}
} else {
names.push(Symbol::intern("<opaque>"));
names.push(sym::opaque_module_name_placeholder);
collect_mod(names, module.parent.unwrap());
}
}

View File

@ -87,7 +87,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol {
}
}
Symbol::intern("rust_out")
sym::rust_out
}
pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {

View File

@ -298,6 +298,7 @@ symbols! {
Return,
Right,
Rust,
RustaceansAreAwesome,
RustcDecodable,
RustcEncodable,
RwLock,
@ -316,6 +317,7 @@ symbols! {
StructuralPartialEq,
SubdiagMessage,
Subdiagnostic,
SymbolIntern,
Sync,
SyncUnsafeCell,
T,
@ -377,6 +379,7 @@ symbols! {
adt_const_params,
advanced_slice_patterns,
adx_target_feature,
aes,
aggregate_raw_ptr,
alias,
align,
@ -440,6 +443,7 @@ symbols! {
associated_types,
assume,
assume_init,
asterisk: "*",
async_await,
async_call,
async_call_mut,
@ -468,6 +472,7 @@ symbols! {
async_for_loop,
async_iterator,
async_iterator_poll_next,
async_trait_bounds,
atomic,
atomic_mod,
atomics,
@ -520,6 +525,7 @@ symbols! {
btreeset_iter,
builtin_syntax,
c,
c_dash_variadic,
c_str,
c_str_literals,
c_unwind,
@ -650,6 +656,7 @@ symbols! {
const_trait_bound_opt_out,
const_trait_impl,
const_try,
const_ty_placeholder: "<const_ty>",
constant,
constructor,
convert_identity,
@ -779,6 +786,7 @@ symbols! {
drop_types_in_const,
dropck_eyepatch,
dropck_parametricity,
dummy_cgu_name,
dylib,
dyn_compatible_for_dispatch,
dyn_metadata,
@ -922,6 +930,7 @@ symbols! {
fmuladdf32,
fmuladdf64,
fn_align,
fn_body,
fn_delegation,
fn_must_use,
fn_mut,
@ -962,6 +971,7 @@ symbols! {
fs_create_dir,
fsub_algebraic,
fsub_fast,
fsxr,
full,
fundamental,
fused_iterator,
@ -1385,6 +1395,7 @@ symbols! {
on,
on_unimplemented,
opaque,
opaque_module_name_placeholder: "<opaque>",
open_options_new,
ops,
opt_out_copy,
@ -1654,6 +1665,7 @@ symbols! {
rust_eh_catch_typeinfo,
rust_eh_personality,
rust_logo,
rust_out,
rustc,
rustc_abi,
rustc_allocator,
@ -1776,6 +1788,8 @@ symbols! {
self_in_typedefs,
self_struct_ctor,
semitransparent,
sha2,
sha3,
sha512_sm_x86,
shadow_call_stack,
shallow,
@ -1890,6 +1904,7 @@ symbols! {
sreg,
sreg_low16,
sse,
sse2,
sse4a_target_feature,
stable,
staged_api,
@ -2177,6 +2192,7 @@ symbols! {
wrapping_sub,
wreg,
write_bytes,
write_fmt,
write_macro,
write_str,
write_via_move,
@ -2406,6 +2422,7 @@ impl Symbol {
}
/// Maps a string to its interned representation.
#[rustc_diagnostic_item = "SymbolIntern"]
pub fn intern(string: &str) -> Self {
with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
}

View File

@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
closure_def_id,
found_kind,
expected_kind,
"async ",
"Async",
);
self.note_obligation_cause(&mut err, &obligation);
self.point_at_returns_when_relevant(&mut err, &obligation);

View File

@ -18,7 +18,6 @@ use rustc_middle::ty::{
TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
};
use rustc_span::Span;
use rustc_span::symbol::Symbol;
use smallvec::SmallVec;
use tracing::{debug, instrument};
@ -679,7 +678,7 @@ fn receiver_is_dispatchable<'tcx>(
// FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can
// replace this with `dyn Trait`
let unsized_self_ty: Ty<'tcx> =
Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome"));
Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
// `Receiver[Self => U]`
let unsized_receiver_ty =

View File

@ -179,6 +179,7 @@ impl Layout {
/// or other unsized type like a slice).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[rustc_const_stable_indirect]
#[must_use]
#[inline]
pub const fn for_value<T: ?Sized>(t: &T) -> Self {
@ -215,7 +216,6 @@ impl Layout {
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[rustc_const_unstable(feature = "layout_for_ptr", issue = "69835")]
#[must_use]
pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
// SAFETY: we pass along the prerequisites of these functions to the caller

View File

@ -752,10 +752,10 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<fn() -> H>);
impl<H> BuildHasherDefault<H> {
/// Creates a new BuildHasherDefault for Hasher `H`.
#[unstable(
#[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(
feature = "build_hasher_default_const_new",
issue = "123197",
reason = "recently added"
since = "CURRENT_RUSTC_VERSION"
)]
pub const fn new() -> Self {
BuildHasherDefault(marker::PhantomData)

View File

@ -4099,6 +4099,7 @@ pub const fn variant_count<T>() -> usize {
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_intrinsic_const_stable_indirect]
pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
unreachable!()
}
@ -4114,6 +4115,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_intrinsic_const_stable_indirect]
pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
unreachable!()
}

View File

@ -333,7 +333,7 @@ pub const fn size_of<T>() -> usize {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")]
pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
// SAFETY: `val` is a reference, so it's a valid raw pointer
@ -390,7 +390,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
#[inline]
#[must_use]
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")]
pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
// SAFETY: the caller must provide a valid raw pointer
unsafe { intrinsics::size_of_val(val) }
@ -485,7 +484,7 @@ pub const fn align_of<T>() -> usize {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")]
#[allow(deprecated)]
pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
// SAFETY: val is a reference, so it's a valid raw pointer
@ -534,7 +533,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
#[inline]
#[must_use]
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")]
pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
// SAFETY: the caller must provide a valid raw pointer
unsafe { intrinsics::min_align_of_val(val) }

View File

@ -2445,7 +2445,7 @@ macro_rules! uint_impl {
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
let (a, b) = self.overflowing_sub(rhs);
let (c, d) = a.overflowing_sub(borrow as $SelfT);
(c, b || d)
(c, b | d)
}
/// Calculates `self` - `rhs` with a signed `rhs`

View File

@ -13,7 +13,6 @@
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(clone_to_uninit)]
#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]
#![feature(const_eval_select)]
#![feature(const_nonnull_new)]

View File

@ -204,6 +204,25 @@ use crate::ops::Index;
/// println!("{viking:?} has {health} hp");
/// }
/// ```
///
/// # Usage in `const` and `static`
///
/// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed,
/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the
/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this
/// way is not resistant against HashDoS!**
///
/// ```rust
/// use std::collections::HashMap;
/// use std::hash::{BuildHasherDefault, DefaultHasher};
/// use std::sync::Mutex;
///
/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> =
/// HashMap::with_hasher(BuildHasherDefault::new());
/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> =
/// Mutex::new(HashMap::with_hasher(BuildHasherDefault::new()));
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")]
#[stable(feature = "rust1", since = "1.0.0")]
@ -277,7 +296,10 @@ impl<K, V, S> HashMap<K, V, S> {
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
#[rustc_const_stable(
feature = "const_collections_with_hasher",
since = "CURRENT_RUSTC_VERSION"
)]
pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_hasher(hash_builder) }
}

View File

@ -101,6 +101,25 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub};
/// [`HashMap`]: crate::collections::HashMap
/// [`RefCell`]: crate::cell::RefCell
/// [`Cell`]: crate::cell::Cell
///
/// # Usage in `const` and `static`
///
/// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed,
/// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the
/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
/// involve a random seed, as demonstrated in the following example. **A `HashSet` constructed this
/// way is not resistant against HashDoS!**
///
/// ```rust
/// use std::collections::HashSet;
/// use std::hash::{BuildHasherDefault, DefaultHasher};
/// use std::sync::Mutex;
///
/// const EMPTY_SET: HashSet<String, BuildHasherDefault<DefaultHasher>> =
/// HashSet::with_hasher(BuildHasherDefault::new());
/// static SET: Mutex<HashSet<String, BuildHasherDefault<DefaultHasher>>> =
/// Mutex::new(HashSet::with_hasher(BuildHasherDefault::new()));
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct HashSet<T, S = RandomState> {
@ -369,7 +388,10 @@ impl<T, S> HashSet<T, S> {
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
#[rustc_const_stable(
feature = "const_collections_with_hasher",
since = "CURRENT_RUSTC_VERSION"
)]
pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
HashSet { base: base::HashSet::with_hasher(hasher) }
}

View File

@ -320,7 +320,6 @@
// Library features (core):
// tidy-alphabetical-start
#![feature(array_chunks)]
#![feature(build_hasher_default_const_new)]
#![feature(c_str_module)]
#![feature(char_internals)]
#![feature(clone_to_uninit)]

View File

@ -2756,6 +2756,10 @@ impl Step for Crate {
// `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
// instead. But crucially we only do that for the library, not the test builds.
cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
// std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
// does not set this directly, but relies on the rustc wrapper to set it, and we are not using
// the wrapper -- hence we have to set it ourselves.
cargo.rustflag("-Zforce-unstable-if-unmarked");
cargo
} else {
// Also prepare a sysroot for the target.

View File

@ -1033,6 +1033,15 @@ impl Builder<'_> {
if mode == Mode::Rustc {
rustflags.arg("-Wrustc::internal");
// cfg(bootstrap) - remove this check when lint is in bootstrap compiler
if stage != 0 {
// Lint is allow by default so downstream tools don't get a lit
// they can do nothing about
// We shouldn't be preinterning symbols used by tests
if cmd_kind != Kind::Test {
rustflags.arg("-Drustc::symbol_intern_string_literal");
}
}
// FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
// of the individual lints are satisfied.
rustflags.arg("-Wkeyword_idents_2024");

View File

@ -0,0 +1,23 @@
# `randomize-layout`
The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764).
------------------------
The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal
optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified
default representation. This also affects type sizes and padding.
Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized.
It can be used to find unsafe code that accidentally relies on unspecified behavior.
Randomization is not guaranteed to use a different permutation for each compilation session.
`-Zlayout-seed=<u64>` can be used to supply additional entropy.
Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently
result in the same layout due to limitations of the current implementation. Randomization may become
more aggressive over time as our coverage of the available degrees of freedoms improves.
Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds
on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts.
Randomization may also become less aggressive in the future if additional guarantees get added to the default layout.

View File

@ -1,6 +1,6 @@
// Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync
#![feature(async_closure, noop_waker)]
#![feature(async_closure, noop_waker, async_trait_bounds)]
use std::future::Future;
use std::pin::pin;

View File

@ -1,4 +1,4 @@
#![feature(async_closure, noop_waker, async_fn_traits)]
#![feature(async_closure, noop_waker, async_trait_bounds)]
use std::future::Future;
use std::pin::pin;

View File

@ -6,8 +6,8 @@
#![no_std]
#![feature(bigint_helper_methods)]
// This checks that the `carrying_add` implementation successfully chains, to catch
// issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
// This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain,
// to catch issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
// This forces the ABI to avoid the windows-vs-linux ABI differences.
@ -31,3 +31,24 @@ pub unsafe extern "sysv64" fn bigint_chain_carrying_add(
}
carry
}
// CHECK-LABEL: bigint_chain_borrowing_sub:
#[no_mangle]
pub unsafe extern "sysv64" fn bigint_chain_borrowing_sub(
dest: *mut u64,
src1: *const u64,
src2: *const u64,
n: usize,
mut carry: bool,
) -> bool {
// CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8]
// CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
// CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]]
// CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16]
// CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16]
// CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]]
for i in 0..n {
(*dest.add(i), carry) = u64::borrowing_sub(*src1.add(i), *src2.add(i), carry);
}
carry
}

View File

@ -9,7 +9,7 @@
#![feature(async_closure)]
fn async_closure_test(upvar: &str) -> impl async Fn() + '_ {
fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ {
async move || {
let hello = String::from("hello");
println!("{hello}, {upvar}");

View File

@ -1,19 +1,19 @@
Function name: async_closure::call_once::<async_closure::main::{closure#0}>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c]
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44)
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43)
Highest counter ID seen: c0
Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02]
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14)
- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14)
- Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
Highest counter ID seen: c1

View File

@ -4,7 +4,7 @@
LL| |//@ aux-build: executor.rs
LL| |extern crate executor;
LL| |
LL| 1|async fn call_once(f: impl async FnOnce()) {
LL| 1|async fn call_once(f: impl AsyncFnOnce()) {
LL| 1| f().await;
LL| 1|}
LL| |

View File

@ -4,7 +4,7 @@
//@ aux-build: executor.rs
extern crate executor;
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -1,7 +1,7 @@
//@ known-bug: #124020
//@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib
#![feature(async_closure, noop_waker, async_fn_traits)]
#![feature(async_closure, noop_waker, async_trait_bounds)]
use std::future::Future;
use std::pin::pin;
@ -19,7 +19,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
}
}
async fn call_once(f: impl async FnOnce(DropMe)) {
async fn call_once(f: impl AsyncFnOnce(DropMe)) {
f(DropMe("world")).await;
}

View File

@ -1,15 +0,0 @@
//@ known-bug: #132320
//@ compile-flags: -Znext-solver=globally
trait Foo {
type Item;
fn foo(&mut self);
}
impl Foo for () {
type Item = Option<()>;
fn foo(&mut self) {
let _ = Self::Item::None;
}
}

View File

@ -10,7 +10,7 @@ fn main() {
block_on::block_on(async {
let x = async || {};
async fn needs_async_fn_mut(mut x: impl async FnMut()) {
async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) {
x().await;
}
needs_async_fn_mut(x).await;

View File

@ -8,7 +8,7 @@ extern crate block_on;
fn main() {
block_on::block_on(async {
async fn needs_async_fn_once(x: impl async FnOnce()) {
async fn needs_async_fn_once(x: impl AsyncFnOnce()) {
x().await;
}

View File

@ -2,6 +2,6 @@
#![feature(async_closure)]
pub fn closure() -> impl async Fn() {
pub fn closure() -> impl AsyncFn() {
async || { /* Don't really need to do anything here. */ }
}

View File

@ -11,7 +11,7 @@ extern crate block_on;
async fn empty() {}
pub async fn call_once<F: async FnOnce()>(f: F) {
pub async fn call_once<F: AsyncFnOnce()>(f: F) {
f().await;
}

View File

@ -16,7 +16,7 @@ impl Trait for (i32,) {
}
}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -13,7 +13,7 @@ struct S;
struct B<'b>(PhantomData<&'b mut &'b mut ()>);
impl S {
async fn q<F: async Fn(B<'_>)>(self, f: F) {
async fn q<F: AsyncFn(B<'_>)>(self, f: F) {
f(B(PhantomData)).await;
}
}

View File

@ -13,11 +13,11 @@ fn main() {
block_on::block_on(async_main());
}
async fn call<T>(f: &impl async Fn() -> T) -> T {
async fn call<T>(f: &impl AsyncFn() -> T) -> T {
f().await
}
async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}
@ -80,7 +80,7 @@ async fn async_main() {
call_once(c).await;
}
fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
fn force_fnonce<T>(f: impl AsyncFnOnce() -> T) -> impl AsyncFnOnce() -> T {
f
}

View File

@ -7,7 +7,7 @@
extern crate block_on;
async fn for_each(f: impl async FnOnce(&str) + Clone) {
async fn for_each(f: impl AsyncFnOnce(&str) + Clone) {
f.clone()("world").await;
f.clone()("world2").await;
}

View File

@ -6,7 +6,7 @@
#![feature(async_closure)]
fn constrain<T: async FnOnce()>(t: T) -> T {
fn constrain<T: AsyncFnOnce()>(t: T) -> T {
t
}
@ -14,7 +14,7 @@ fn call_once<T>(f: impl FnOnce() -> T) -> T {
f()
}
async fn async_call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn async_call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}

View File

@ -7,7 +7,7 @@
extern crate block_on;
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -16,7 +16,7 @@ impl Drop for DropMe {
}
}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
println!("before call");
let fut = Box::pin(f());
println!("after call");

View File

@ -10,7 +10,7 @@ use std::future::Future;
#[target_feature(enable = "sse2")]
fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() }
fn test(f: impl async Fn()) {}
fn test(f: impl AsyncFn()) {}
fn main() {
test(target_feature); //~ ERROR the trait bound

View File

@ -9,8 +9,8 @@ LL | test(target_feature);
note: required by a bound in `test`
--> $DIR/fn-exception-target-features.rs:13:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`
error: aborting due to 1 previous error

View File

@ -13,7 +13,7 @@ unsafe extern "C" {
pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
}
fn test(f: impl async Fn()) {}
fn test(f: impl AsyncFn()) {}
fn main() {
test(unsafety); //~ ERROR the trait bound

View File

@ -9,8 +9,8 @@ LL | test(unsafety);
note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
--> $DIR/fn-exception.rs:20:10
@ -23,8 +23,8 @@ LL | test(abi);
note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`
error: aborting due to 2 previous errors

View File

@ -6,7 +6,7 @@
extern crate block_on;
fn force_fnonce<T: async FnOnce()>(t: T) -> T { t }
fn force_fnonce<T: AsyncFnOnce()>(t: T) -> T { t }
fn main() {
block_on::block_on(async {

View File

@ -12,7 +12,7 @@ extern crate foreign;
struct NoCopy;
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -1,7 +1,7 @@
//@ build-pass
//@ edition: 2021
// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!)
// Demonstrates that an async closure may implement `FnMut` (not just `AsyncFnMut`!)
// if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env,
// since it's fine to reborrow it with its original lifetime. See the doc comment on
// `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we

View File

@ -24,7 +24,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
}
}
async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}

View File

@ -13,11 +13,11 @@ use std::future::Future;
use std::pin::pin;
use std::task::*;
async fn call_mut(f: &mut impl async FnMut()) {
async fn call_mut(f: &mut impl AsyncFnMut()) {
f().await;
}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()>
where
for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>),
for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>),
{
todo!()
}

View File

@ -19,7 +19,7 @@ fn main() {
is_static(&c);
// Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures.
fn call_once<F: async FnOnce()>(f: F) -> F::CallOnceFuture { f() }
fn call_once<F: AsyncFnOnce()>(f: F) -> F::CallOnceFuture { f() }
is_static(&call_once(c));
});
}

View File

@ -9,7 +9,7 @@
extern crate block_on;
async fn call_once(f: impl async FnOnce()) { f().await; }
async fn call_once(f: impl AsyncFnOnce()) { f().await; }
pub async fn async_closure(x: &mut i32) {
let c = async move || {

View File

@ -5,7 +5,7 @@
fn outlives<'a>(_: impl Sized + 'a) {}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -6,7 +6,7 @@
extern crate block_on;
fn wrapper(f: impl Fn(String)) -> impl async Fn(String) {
fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) {
async move |s| f(s)
}

View File

@ -7,7 +7,7 @@
extern crate block_on;
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -5,7 +5,7 @@
//@ revisions: call call_once force_once
// call - Call the closure regularly.
// call_once - Call the closure w/ `async FnOnce`, so exercising the by_move shim.
// call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim.
// force_once - Force the closure mode to `FnOnce`, so exercising what was fixed
// in <https://github.com/rust-lang/rust/pull/123350>.
@ -20,7 +20,7 @@ macro_rules! call {
}
#[cfg(call_once)]
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await
}
@ -35,7 +35,7 @@ macro_rules! guidance {
}
#[cfg(force_once)]
fn infer_fnonce(c: impl async FnOnce()) -> impl async FnOnce() { c }
fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c }
#[cfg(force_once)]
macro_rules! guidance {

View File

@ -10,15 +10,15 @@ struct NoCopy;
fn main() {
block_on::block_on(async {
async fn call_once(x: impl async Fn()) { x().await }
async fn call_once(x: impl AsyncFn()) { x().await }
// check that `&{async-closure}` implements `async Fn`.
// check that `&{async-closure}` implements `AsyncFn`.
call_once(&async || {}).await;
// check that `&{closure}` implements `async Fn`.
// check that `&{closure}` implements `AsyncFn`.
call_once(&|| async {}).await;
// check that `&fndef` implements `async Fn`.
// check that `&fndef` implements `AsyncFn`.
async fn foo() {}
call_once(&foo).await;
});

View File

@ -3,7 +3,7 @@
#![feature(async_closure)]
async fn foo(x: impl async Fn(&str) -> &str) {}
async fn foo(x: impl AsyncFn(&str) -> &str) {}
fn main() {
foo(async |x| x);

View File

@ -8,7 +8,7 @@
fn outlives<'a>(_: impl Sized + 'a) {}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

View File

@ -2,7 +2,7 @@
#![feature(async_closure)]
fn needs_async_fn(_: impl async Fn()) {}
fn needs_async_fn(_: impl AsyncFn()) {}
fn a() {
let mut x = 1;
@ -15,7 +15,7 @@ fn a() {
fn b() {
let x = String::new();
needs_async_fn(move || async move {
//~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
//~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
println!("{x}");
});
}

View File

@ -1,29 +1,29 @@
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
--> $DIR/wrong-fn-kind.rs:17:20
|
LL | needs_async_fn(move || async move {
| -------------- -^^^^^^
| | |
| _____|______________this closure implements `async FnOnce`, not `async Fn`
| _____|______________this closure implements `AsyncFnOnce`, not `AsyncFn`
| | |
| | required by a bound introduced by this call
LL | |
LL | | println!("{x}");
| | - closure is `async FnOnce` because it moves the variable `x` out of its environment
| | - closure is `AsyncFnOnce` because it moves the variable `x` out of its environment
LL | | });
| |_____- the requirement to implement `async Fn` derives from here
| |_____- the requirement to implement `AsyncFn` derives from here
|
note: required by a bound in `needs_async_fn`
--> $DIR/wrong-fn-kind.rs:5:27
|
LL | fn needs_async_fn(_: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `needs_async_fn`
LL | fn needs_async_fn(_: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `needs_async_fn`
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/wrong-fn-kind.rs:9:20
|
LL | fn needs_async_fn(_: impl async Fn()) {}
| --------------- change this to accept `FnMut` instead of `Fn`
LL | fn needs_async_fn(_: impl AsyncFn()) {}
| -------------- change this to accept `FnMut` instead of `Fn`
...
LL | needs_async_fn(async || {
| -------------- ^^^^^^^^

View File

@ -2,7 +2,7 @@
#![feature(async_closure)]
fn foo(x: &dyn async Fn()) {}
fn foo(x: &dyn AsyncFn()) {}
//~^ ERROR the trait `AsyncFnMut` cannot be made into an object
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0038]: the trait `AsyncFnMut` cannot be made into an object
--> $DIR/dyn-pos.rs:5:16
|
LL | fn foo(x: &dyn async Fn()) {}
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
LL | fn foo(x: &dyn AsyncFn()) {}
| ^^^^^^^^^ `AsyncFnMut` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL

View File

@ -1,8 +1,8 @@
fn foo(x: impl async Fn()) -> impl async Fn() { x }
//~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later
//~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
//~| ERROR async closures are unstable
//~| ERROR async closures are unstable
//~| ERROR `async` trait bounds are unstable
//~| ERROR `async` trait bounds are unstable
//~| ERROR use of unstable library feature `async_closure`
//~| ERROR use of unstable library feature `async_closure`

View File

@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
= help: pass `--edition 2024` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0658]: async closures are unstable
error[E0658]: `async` trait bounds are unstable
--> $DIR/edition-2015.rs:1:16
|
LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {`
= help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: async closures are unstable
error[E0658]: `async` trait bounds are unstable
--> $DIR/edition-2015.rs:1:36
|
LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {`
= help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: use of unstable library feature `async_closure`
--> $DIR/edition-2015.rs:1:42

View File

@ -15,7 +15,7 @@ async fn f(arg: &i32) {}
async fn func<F>(f: F)
where
F: for<'a> async Fn(&'a i32),
F: for<'a> AsyncFn(&'a i32),
{
let x: i32 = 0;
f(&x).await;

View File

@ -3,13 +3,13 @@
#![feature(async_closure, type_alias_impl_trait)]
type Tait = impl async Fn();
type Tait = impl AsyncFn();
fn tait() -> Tait {
|| async {}
}
fn foo(x: impl async Fn()) -> impl async Fn() { x }
fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x }
fn param<T: async Fn()>() {}
fn param<T: AsyncFn()>() {}
fn main() {}

View File

@ -13,9 +13,9 @@ macro_rules! demo {
}
demo! { impl async Trait }
//~^ ERROR async closures are unstable
//~^ ERROR `async` trait bounds are unstable
demo! { dyn async Trait }
//~^ ERROR async closures are unstable
//~^ ERROR `async` trait bounds are unstable
fn main() {}

View File

@ -20,27 +20,27 @@ LL | demo! { dyn async Trait }
|
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: async closures are unstable
error[E0658]: `async` trait bounds are unstable
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14
|
LL | demo! { impl async Trait }
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {`
= help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: async closures are unstable
error[E0658]: `async` trait bounds are unstable
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13
|
LL | demo! { dyn async Trait }
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {`
= help: use the desugared name of the async trait, such as `AsyncFn`
error: aborting due to 4 previous errors

View File

@ -1,6 +1,6 @@
//@ edition:2018
#![feature(async_closure)]
#![feature(async_trait_bounds)]
struct S;

View File

@ -6,7 +6,9 @@
#![feature(async_closure, unboxed_closures, async_fn_traits)]
fn project<F: async Fn<()>>(_: F) -> Option<F::Output> { None }
use std::ops::AsyncFn;
fn project<F: AsyncFn<()>>(_: F) -> Option<F::Output> { None }
fn main() {
let x: Option<i32> = project(|| async { 1i32 });

View File

@ -1,7 +1,7 @@
//@ edition: 2021
//@ check-pass
#![feature(async_closure)]
#![feature(async_closure, async_trait_bounds)]
async fn foo() {}

View File

@ -6,7 +6,7 @@ macro_rules! x {
x! {
async fn foo() -> impl async Fn() { }
//~^ ERROR async closures are unstable
//~^ ERROR `async` trait bounds are unstable
}
fn main() {}

View File

@ -1,13 +1,13 @@
error[E0658]: async closures are unstable
error[E0658]: `async` trait bounds are unstable
--> $DIR/trait-bounds-in-macro.rs:8:28
|
LL | async fn foo() -> impl async Fn() { }
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {`
= help: use the desugared name of the async trait, such as `AsyncFn`
error: aborting due to 1 previous error

View File

@ -1,6 +1,6 @@
//@ edition:2018
#![feature(async_closure)]
#![feature(async_trait_bounds)]
trait Foo {}

View File

@ -0,0 +1,12 @@
//@ check-pass
#![feature(generic_arg_infer)]
#![crate_type = "lib"]
// Test that encoding the hallucinated `DefId` for the `_` const argument doesn't
// ICE (see #133468). This requires this to be a library crate.
pub fn foo() {
let s: [u8; 10];
s = [0; _];
}

View File

@ -1,6 +1,5 @@
#![feature(extern_types)]
#![feature(core_intrinsics)]
#![feature(const_size_of_val, const_align_of_val)]
use std::intrinsics::{min_align_of_val, size_of_val};

View File

@ -1,11 +1,11 @@
error[E0080]: evaluation of constant value failed
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31
|
LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
error[E0080]: evaluation of constant value failed
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:32
|
LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout

View File

@ -1,7 +1,6 @@
//@ run-pass
#![feature(const_size_of_val, const_align_of_val)]
#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)]
#![feature(layout_for_ptr)]
use std::{mem, ptr};

View File

@ -14,7 +14,7 @@ impl Drop for Droppy {
}
}
impl Droppy {
fn get(&self) -> Option<u8> {
const fn get(&self) -> Option<u8> {
None
}
}
@ -62,11 +62,10 @@ fn main() {
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
}
if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
if let () = { if let Some(_value) = Droppy.get() {} } {
// This should not lint.
// This `if let` sits is a tail expression of a block.
// In Edition 2024, the temporaries are dropped before exiting the surrounding block.
}
#[rustfmt::skip]
@ -94,4 +93,17 @@ fn main() {
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
}
// We want to keep the `if let`s below as direct descendents of match arms,
// so the formatting is suppressed.
#[rustfmt::skip]
match droppy().get() {
_ => if let Some(_value) = droppy().get() {},
// Should not lint
// There is implicitly a block surrounding the `if let`.
// Given that it is a tail expression, the temporaries are dropped duly before
// the execution is exiting the `match`.
}
if let Some(_value) = droppy().get() {}
}

View File

@ -14,7 +14,7 @@ impl Drop for Droppy {
}
}
impl Droppy {
fn get(&self) -> Option<u8> {
const fn get(&self) -> Option<u8> {
None
}
}
@ -63,10 +63,9 @@ fn main() {
}
if let () = { if let Some(_value) = Droppy.get() {} } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
// This should not lint.
// This `if let` sits is a tail expression of a block.
// In Edition 2024, the temporaries are dropped before exiting the surrounding block.
}
#[rustfmt::skip]
@ -94,4 +93,17 @@ fn main() {
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
}
// We want to keep the `if let`s below as direct descendents of match arms,
// so the formatting is suppressed.
#[rustfmt::skip]
match droppy().get() {
_ => if let Some(_value) = droppy().get() {},
// Should not lint
// There is implicitly a block surrounding the `if let`.
// Given that it is a tail expression, the temporaries are dropped duly before
// the execution is exiting the `match`.
}
if let Some(_value) = droppy().get() {}
}

View File

@ -112,27 +112,7 @@ LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ =
| ~~~~~ +++++++++++++++++ ~~~~ +
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:65:22
|
LL | if let () = { if let Some(_value) = Droppy.get() {} } {
| ^^^^^^^^^^^^^^^^^^^------^^^^^^
| |
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:65:55
|
LL | if let () = { if let Some(_value) = Droppy.get() {} } {
| ^
help: a `match` with a single arm can preserve the drop order up to Edition 2021
|
LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
| ~~~~~ +++++++++++++++++ ++++++++
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:73:12
--> $DIR/lint-if-let-rescope.rs:72:12
|
LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@ -142,7 +122,7 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:73:53
--> $DIR/lint-if-let-rescope.rs:72:53
|
LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
| ^
@ -152,7 +132,7 @@ LL | if (match droppy().get() { Some(_value) => { true } _ => { false }}) {
| ~~~~~ +++++++++++++++++ ~~~~ +
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:79:21
--> $DIR/lint-if-let-rescope.rs:78:21
|
LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@ -162,7 +142,7 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:79:62
--> $DIR/lint-if-let-rescope.rs:78:62
|
LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
| ^
@ -172,7 +152,7 @@ LL | } else if (((match droppy().get() { Some(_value) => { true } _ => { fal
| ~~~~~ +++++++++++++++++ ~~~~ +
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:91:15
--> $DIR/lint-if-let-rescope.rs:90:15
|
LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@ -182,7 +162,7 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:91:57
--> $DIR/lint-if-let-rescope.rs:90:57
|
LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
| ^
@ -191,5 +171,5 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021
LL | while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
| ~~~~~ +++++++++++++++++ ~~~~ +
error: aborting due to 8 previous errors
error: aborting due to 7 previous errors

View File

@ -0,0 +1,7 @@
//@ edition: 2021
fn test(_: impl async Fn()) {}
//~^ ERROR `async` trait bounds are unstable
//~| ERROR use of unstable library feature `async_closure`
fn main() {}

Some files were not shown because too many files have changed in this diff Show More