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
106 changed files with 438 additions and 224 deletions
+2 -1
View File
@@ -2011,7 +2011,8 @@ fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::Const
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,
@@ -4,9 +4,9 @@
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 @@ macro_rules! gate_all {
"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"),
@@ -33,8 +33,8 @@
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 @@ fn build(self) -> UniversalRegions<'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 @@ fn build(self) -> UniversalRegions<'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();
@@ -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());
+2 -7
View File
@@ -189,18 +189,13 @@ fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_sp
// 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],
}
+2
View File
@@ -394,6 +394,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
(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>)]`.
@@ -419,7 +419,7 @@ enum Defaults {
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 },
+5 -1
View File
@@ -307,7 +307,11 @@ fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'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,
}
@@ -664,7 +664,7 @@ fn report_no_match_method_error(
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 {
+3
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}`
+5 -2
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
+33 -2
View File
@@ -17,8 +17,9 @@
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,
);
}
}
}
+2
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
+5
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 {
+1 -1
View File
@@ -1563,7 +1563,7 @@ fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &
}
rename.unwrap_or(orig_ident).name
}
ast::UseTreeKind::Glob => Symbol::intern("*"),
ast::UseTreeKind::Glob => sym::asterisk,
ast::UseTreeKind::Nested { .. } => return,
};
+5 -4
View File
@@ -861,8 +861,10 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
// 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 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
}
}
}
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 {
@@ -872,6 +872,7 @@ fn print_item(
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 {
+8 -4
View File
@@ -1389,10 +1389,14 @@ fn encode_def_ids(&mut self) {
// `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;
}
+4 -4
View File
@@ -9,7 +9,7 @@
};
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 @@ fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
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 @@ fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
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 @@ fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
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),
@@ -3113,6 +3113,7 @@ fn add_missing_lifetime_specifiers_label(
}
}
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
let existing_name = match &in_scope_lifetimes[..] {
[] => Symbol::intern("'a"),
[(existing, _)] => existing.name,
+1 -1
View File
@@ -2257,7 +2257,7 @@ fn collect_mod(names: &mut Vec<Symbol>, module: Module<'_>) {
collect_mod(names, parent);
}
} else {
names.push(Symbol::intern("<opaque>"));
names.push(sym::opaque_module_name_placeholder);
collect_mod(names, module.parent.unwrap());
}
}
+1 -1
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>) {
+17
View File
@@ -298,6 +298,7 @@
Return,
Right,
Rust,
RustaceansAreAwesome,
RustcDecodable,
RustcEncodable,
RwLock,
@@ -316,6 +317,7 @@
StructuralPartialEq,
SubdiagMessage,
Subdiagnostic,
SymbolIntern,
Sync,
SyncUnsafeCell,
T,
@@ -377,6 +379,7 @@
adt_const_params,
advanced_slice_patterns,
adx_target_feature,
aes,
aggregate_raw_ptr,
alias,
align,
@@ -440,6 +443,7 @@
associated_types,
assume,
assume_init,
asterisk: "*",
async_await,
async_call,
async_call_mut,
@@ -468,6 +472,7 @@
async_for_loop,
async_iterator,
async_iterator_poll_next,
async_trait_bounds,
atomic,
atomic_mod,
atomics,
@@ -520,6 +525,7 @@
btreeset_iter,
builtin_syntax,
c,
c_dash_variadic,
c_str,
c_str_literals,
c_unwind,
@@ -650,6 +656,7 @@
const_trait_bound_opt_out,
const_trait_impl,
const_try,
const_ty_placeholder: "<const_ty>",
constant,
constructor,
convert_identity,
@@ -779,6 +786,7 @@
drop_types_in_const,
dropck_eyepatch,
dropck_parametricity,
dummy_cgu_name,
dylib,
dyn_compatible_for_dispatch,
dyn_metadata,
@@ -922,6 +930,7 @@
fmuladdf32,
fmuladdf64,
fn_align,
fn_body,
fn_delegation,
fn_must_use,
fn_mut,
@@ -962,6 +971,7 @@
fs_create_dir,
fsub_algebraic,
fsub_fast,
fsxr,
full,
fundamental,
fused_iterator,
@@ -1385,6 +1395,7 @@
on,
on_unimplemented,
opaque,
opaque_module_name_placeholder: "<opaque>",
open_options_new,
ops,
opt_out_copy,
@@ -1654,6 +1665,7 @@
rust_eh_catch_typeinfo,
rust_eh_personality,
rust_logo,
rust_out,
rustc,
rustc_abi,
rustc_allocator,
@@ -1776,6 +1788,8 @@
self_in_typedefs,
self_struct_ctor,
semitransparent,
sha2,
sha3,
sha512_sm_x86,
shadow_call_stack,
shallow,
@@ -1890,6 +1904,7 @@
sreg,
sreg_low16,
sse,
sse2,
sse4a_target_feature,
stable,
staged_api,
@@ -2177,6 +2192,7 @@
wrapping_sub,
wreg,
write_bytes,
write_fmt,
write_macro,
write_str,
write_via_move,
@@ -2406,6 +2422,7 @@ pub fn new_from_decoded(n: u32) -> Self {
}
/// 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))
}
@@ -794,7 +794,7 @@ fn emit_specialized_closure_kind_error(
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);
@@ -18,7 +18,6 @@
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 =
+1 -1
View File
@@ -179,6 +179,7 @@ pub const fn new<T>() -> Self {
/// 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 @@ pub const fn for_value<T: ?Sized>(t: &T) -> Self {
/// [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
+3 -3
View File
@@ -752,10 +752,10 @@ fn hash_one<T: Hash>(&self, x: T) -> u64
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)
+2
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 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 min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
unreachable!()
}
+2 -4
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) }
+1 -1
View File
@@ -2445,7 +2445,7 @@ pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
// 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`
-1
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)]
+23 -1
View File
@@ -204,6 +204,25 @@
/// 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) }
}
+23 -1
View File
@@ -101,6 +101,25 @@
/// [`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 @@ pub fn clear(&mut self) {
/// ```
#[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) }
}
-1
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)]
@@ -2756,6 +2756,10 @@ fn run(self, builder: &Builder<'_>) {
// `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.
+9
View File
@@ -1033,6 +1033,15 @@ fn cargo(
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");
@@ -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.
@@ -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;
@@ -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;
@@ -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 @@
}
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
}
+1 -1
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}");
+4 -4
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
+1 -1
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| |
+1 -1
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;
}
+2 -2
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;
}
-15
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;
}
}
@@ -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;
@@ -8,7 +8,7 @@
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;
}
@@ -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. */ }
}
@@ -11,7 +11,7 @@
async fn empty() {}
pub async fn call_once<F: async FnOnce()>(f: F) {
pub async fn call_once<F: AsyncFnOnce()>(f: F) {
f().await;
}
@@ -16,7 +16,7 @@ fn callback(&mut self) {
}
}
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}
+1 -1
View File
@@ -13,7 +13,7 @@
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;
}
}
@@ -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
}
@@ -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;
}
@@ -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
}
@@ -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;
}
+1 -1
View File
@@ -16,7 +16,7 @@ fn drop(&mut self) {
}
}
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");
@@ -10,7 +10,7 @@
#[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
@@ -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
@@ -13,7 +13,7 @@
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
@@ -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
@@ -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 {
@@ -12,7 +12,7 @@
struct NoCopy;
async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}
@@ -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
@@ -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
}
@@ -13,11 +13,11 @@
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;
}
@@ -22,7 +22,7 @@ pub fn spawn(&'scope self, future: impl Future<Output = ()> + Send + 'scope) {
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!()
}
@@ -19,7 +19,7 @@ fn is_static<T: 'static>(_: &T) {}
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));
});
}
@@ -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 || {
@@ -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;
}
@@ -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)
}
@@ -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;
}
@@ -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 {
+4 -4
View File
@@ -10,15 +10,15 @@
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;
});
@@ -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);
@@ -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;
}
@@ -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}");
});
}
@@ -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 || {
| -------------- ^^^^^^^^
+1 -1
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() {}
+2 -2
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
@@ -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`
@@ -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
@@ -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;
+3 -3
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() {}
@@ -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() {}
@@ -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
+1 -1
View File
@@ -1,6 +1,6 @@
//@ edition:2018
#![feature(async_closure)]
#![feature(async_trait_bounds)]
struct S;
+3 -1
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 });
+1 -1
View File
@@ -1,7 +1,7 @@
//@ edition: 2021
//@ check-pass
#![feature(async_closure)]
#![feature(async_closure, async_trait_bounds)]
async fn foo() {}
@@ -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() {}
@@ -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
+1 -1
View File
@@ -1,6 +1,6 @@
//@ edition:2018
#![feature(async_closure)]
#![feature(async_trait_bounds)]
trait Foo {}
@@ -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; _];
}
@@ -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};
@@ -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
@@ -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};
+18 -6
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() {}
}
+17 -5
View File
@@ -14,7 +14,7 @@ fn drop(&mut self) {
}
}
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() {}
}
+7 -27
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
@@ -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