Auto merge of #127076 - matthiaskrgr:rollup-l01gm36, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #124741 (patchable-function-entry: Add unstable compiler flag and attribute) - #126470 (make cargo submodule optional) - #126956 (core: avoid `extern type`s in formatting infrastructure) - #126970 (Simplify `str::clone_into`) - #127022 (Support fetching `Attribute` of items.) - #127058 (Tighten `fn_decl_span` for async blocks) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
99f77a2eda
80 changed files with 980 additions and 308 deletions
|
@ -4675,6 +4675,8 @@ name = "rustc_smir"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_abi",
|
"rustc_abi",
|
||||||
|
"rustc_ast",
|
||||||
|
"rustc_ast_pretty",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
|
|
|
@ -1454,7 +1454,10 @@ pub enum ExprKind {
|
||||||
Block(P<Block>, Option<Label>),
|
Block(P<Block>, Option<Label>),
|
||||||
/// An `async` block (`async move { ... }`),
|
/// An `async` block (`async move { ... }`),
|
||||||
/// or a `gen` block (`gen move { ... }`)
|
/// or a `gen` block (`gen move { ... }`)
|
||||||
Gen(CaptureBy, P<Block>, GenBlockKind),
|
///
|
||||||
|
/// The span is the "decl", which is the header before the body `{ }`
|
||||||
|
/// including the `asyng`/`gen` keywords and possibly `move`.
|
||||||
|
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
|
||||||
/// An await expression (`my_future.await`). Span is of await keyword.
|
/// An await expression (`my_future.await`). Span is of await keyword.
|
||||||
Await(P<Expr>, Span),
|
Await(P<Expr>, Span),
|
||||||
|
|
||||||
|
|
|
@ -1528,8 +1528,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||||
visit_opt(label, |label| vis.visit_label(label));
|
visit_opt(label, |label| vis.visit_label(label));
|
||||||
vis.visit_block(blk);
|
vis.visit_block(blk);
|
||||||
}
|
}
|
||||||
ExprKind::Gen(_capture_by, body, _kind) => {
|
ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
|
||||||
vis.visit_block(body);
|
vis.visit_block(body);
|
||||||
|
vis.visit_span(decl_span);
|
||||||
}
|
}
|
||||||
ExprKind::Await(expr, await_kw_span) => {
|
ExprKind::Await(expr, await_kw_span) => {
|
||||||
vis.visit_expr(expr);
|
vis.visit_expr(expr);
|
||||||
|
|
|
@ -1122,7 +1122,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||||
visit_opt!(visitor, visit_label, opt_label);
|
visit_opt!(visitor, visit_label, opt_label);
|
||||||
try_visit!(visitor.visit_block(block));
|
try_visit!(visitor.visit_block(block));
|
||||||
}
|
}
|
||||||
ExprKind::Gen(_capt, body, _kind) => try_visit!(visitor.visit_block(body)),
|
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
|
||||||
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
||||||
ExprKind::Assign(lhs, rhs, _span) => {
|
ExprKind::Assign(lhs, rhs, _span) => {
|
||||||
try_visit!(visitor.visit_expr(lhs));
|
try_visit!(visitor.visit_expr(lhs));
|
||||||
|
|
|
@ -227,7 +227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
*fn_arg_span,
|
*fn_arg_span,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
ExprKind::Gen(capture_clause, block, genblock_kind) => {
|
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
|
||||||
let desugaring_kind = match genblock_kind {
|
let desugaring_kind = match genblock_kind {
|
||||||
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
|
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
|
||||||
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
|
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
|
||||||
|
@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
*capture_clause,
|
*capture_clause,
|
||||||
e.id,
|
e.id,
|
||||||
None,
|
None,
|
||||||
|
*decl_span,
|
||||||
e.span,
|
e.span,
|
||||||
desugaring_kind,
|
desugaring_kind,
|
||||||
hir::CoroutineSource::Block,
|
hir::CoroutineSource::Block,
|
||||||
|
@ -616,6 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
closure_node_id: NodeId,
|
closure_node_id: NodeId,
|
||||||
return_ty: Option<hir::FnRetTy<'hir>>,
|
return_ty: Option<hir::FnRetTy<'hir>>,
|
||||||
|
fn_decl_span: Span,
|
||||||
span: Span,
|
span: Span,
|
||||||
desugaring_kind: hir::CoroutineDesugaring,
|
desugaring_kind: hir::CoroutineDesugaring,
|
||||||
coroutine_source: hir::CoroutineSource,
|
coroutine_source: hir::CoroutineSource,
|
||||||
|
@ -692,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
bound_generic_params: &[],
|
bound_generic_params: &[],
|
||||||
fn_decl,
|
fn_decl,
|
||||||
body,
|
body,
|
||||||
fn_decl_span: self.lower_span(span),
|
fn_decl_span: self.lower_span(fn_decl_span),
|
||||||
fn_arg_span: None,
|
fn_arg_span: None,
|
||||||
kind: hir::ClosureKind::Coroutine(coroutine_kind),
|
kind: hir::ClosureKind::Coroutine(coroutine_kind),
|
||||||
constness: hir::Constness::NotConst,
|
constness: hir::Constness::NotConst,
|
||||||
|
@ -1083,6 +1085,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||||
&inner_decl,
|
&inner_decl,
|
||||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||||
|
fn_decl_span,
|
||||||
body.span,
|
body.span,
|
||||||
coroutine_kind,
|
coroutine_kind,
|
||||||
hir::CoroutineSource::Closure,
|
hir::CoroutineSource::Closure,
|
||||||
|
|
|
@ -211,6 +211,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// declaration (decl), not the return types.
|
// declaration (decl), not the return types.
|
||||||
let coroutine_kind = header.coroutine_kind;
|
let coroutine_kind = header.coroutine_kind;
|
||||||
let body_id = this.lower_maybe_coroutine_body(
|
let body_id = this.lower_maybe_coroutine_body(
|
||||||
|
*fn_sig_span,
|
||||||
span,
|
span,
|
||||||
hir_id,
|
hir_id,
|
||||||
decl,
|
decl,
|
||||||
|
@ -799,6 +800,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
||||||
let body_id = self.lower_maybe_coroutine_body(
|
let body_id = self.lower_maybe_coroutine_body(
|
||||||
|
sig.span,
|
||||||
i.span,
|
i.span,
|
||||||
hir_id,
|
hir_id,
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
|
@ -915,6 +917,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
),
|
),
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
||||||
let body_id = self.lower_maybe_coroutine_body(
|
let body_id = self.lower_maybe_coroutine_body(
|
||||||
|
sig.span,
|
||||||
i.span,
|
i.span,
|
||||||
hir_id,
|
hir_id,
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
|
@ -1111,6 +1114,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
/// `gen {}` block as appropriate.
|
/// `gen {}` block as appropriate.
|
||||||
fn lower_maybe_coroutine_body(
|
fn lower_maybe_coroutine_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
fn_decl_span: Span,
|
||||||
span: Span,
|
span: Span,
|
||||||
fn_id: hir::HirId,
|
fn_id: hir::HirId,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
|
@ -1124,6 +1128,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||||
decl,
|
decl,
|
||||||
|this| this.lower_block_expr(body),
|
|this| this.lower_block_expr(body),
|
||||||
|
fn_decl_span,
|
||||||
body.span,
|
body.span,
|
||||||
coroutine_kind,
|
coroutine_kind,
|
||||||
hir::CoroutineSource::Fn,
|
hir::CoroutineSource::Fn,
|
||||||
|
@ -1145,6 +1150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
&mut self,
|
&mut self,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
|
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
|
||||||
|
fn_decl_span: Span,
|
||||||
body_span: Span,
|
body_span: Span,
|
||||||
coroutine_kind: CoroutineKind,
|
coroutine_kind: CoroutineKind,
|
||||||
coroutine_source: hir::CoroutineSource,
|
coroutine_source: hir::CoroutineSource,
|
||||||
|
@ -1315,13 +1321,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
};
|
};
|
||||||
let closure_id = coroutine_kind.closure_id();
|
let closure_id = coroutine_kind.closure_id();
|
||||||
|
|
||||||
let span = if let FnRetTy::Default(span) = decl.output
|
|
||||||
&& matches!(coroutine_source, rustc_hir::CoroutineSource::Closure)
|
|
||||||
{
|
|
||||||
body_span.with_lo(span.lo())
|
|
||||||
} else {
|
|
||||||
body_span
|
|
||||||
};
|
|
||||||
let coroutine_expr = self.make_desugared_coroutine_expr(
|
let coroutine_expr = self.make_desugared_coroutine_expr(
|
||||||
// The default capture mode here is by-ref. Later on during upvar analysis,
|
// The default capture mode here is by-ref. Later on during upvar analysis,
|
||||||
// we will force the captured arguments to by-move, but for async closures,
|
// we will force the captured arguments to by-move, but for async closures,
|
||||||
|
@ -1330,7 +1329,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
CaptureBy::Ref,
|
CaptureBy::Ref,
|
||||||
closure_id,
|
closure_id,
|
||||||
None,
|
None,
|
||||||
span,
|
fn_decl_span,
|
||||||
|
body_span,
|
||||||
desugaring_kind,
|
desugaring_kind,
|
||||||
coroutine_source,
|
coroutine_source,
|
||||||
mkbody,
|
mkbody,
|
||||||
|
|
|
@ -540,7 +540,7 @@ impl<'a> State<'a> {
|
||||||
self.ibox(0);
|
self.ibox(0);
|
||||||
self.print_block_with_attrs(blk, attrs);
|
self.print_block_with_attrs(blk, attrs);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Gen(capture_clause, blk, kind) => {
|
ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
|
||||||
self.word_nbsp(kind.modifier());
|
self.word_nbsp(kind.modifier());
|
||||||
self.print_capture_clause(*capture_clause);
|
self.print_capture_clause(*capture_clause);
|
||||||
// cbox/ibox in analogy to the `ExprKind::Block` arm above
|
// cbox/ibox in analogy to the `ExprKind::Block` arm above
|
||||||
|
|
|
@ -298,7 +298,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||||
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
|
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
|
||||||
ExprKind::Assign(_, _, _)
|
ExprKind::Assign(_, _, _)
|
||||||
| ExprKind::AssignOp(_, _, _)
|
| ExprKind::AssignOp(_, _, _)
|
||||||
| ExprKind::Gen(_, _, _)
|
| ExprKind::Gen(_, _, _, _)
|
||||||
| ExprKind::Await(_, _)
|
| ExprKind::Await(_, _)
|
||||||
| ExprKind::Block(_, _)
|
| ExprKind::Block(_, _)
|
||||||
| ExprKind::Break(_, _)
|
| ExprKind::Break(_, _)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::config::{FunctionReturn, OptLevel};
|
use rustc_session::config::{FunctionReturn, OptLevel};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
@ -53,6 +53,34 @@ fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn patchable_function_entry_attrs<'ll>(
|
||||||
|
cx: &CodegenCx<'ll, '_>,
|
||||||
|
attr: Option<PatchableFunctionEntry>,
|
||||||
|
) -> SmallVec<[&'ll Attribute; 2]> {
|
||||||
|
let mut attrs = SmallVec::new();
|
||||||
|
let patchable_spec = attr.unwrap_or_else(|| {
|
||||||
|
PatchableFunctionEntry::from_config(cx.tcx.sess.opts.unstable_opts.patchable_function_entry)
|
||||||
|
});
|
||||||
|
let entry = patchable_spec.entry();
|
||||||
|
let prefix = patchable_spec.prefix();
|
||||||
|
if entry > 0 {
|
||||||
|
attrs.push(llvm::CreateAttrStringValue(
|
||||||
|
cx.llcx,
|
||||||
|
"patchable-function-entry",
|
||||||
|
&format!("{}", entry),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if prefix > 0 {
|
||||||
|
attrs.push(llvm::CreateAttrStringValue(
|
||||||
|
cx.llcx,
|
||||||
|
"patchable-function-prefix",
|
||||||
|
&format!("{}", prefix),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
attrs
|
||||||
|
}
|
||||||
|
|
||||||
/// Get LLVM sanitize attributes.
|
/// Get LLVM sanitize attributes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sanitize_attrs<'ll>(
|
pub fn sanitize_attrs<'ll>(
|
||||||
|
@ -421,6 +449,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
||||||
llvm::set_alignment(llfn, align);
|
llvm::set_alignment(llfn, align);
|
||||||
}
|
}
|
||||||
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
|
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
|
||||||
|
to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
|
||||||
|
|
||||||
// Always annotate functions with the target-cpu they are compiled for.
|
// Always annotate functions with the target-cpu they are compiled for.
|
||||||
// Without this, ThinLTO won't inline Rust functions into Clang generated
|
// Without this, ThinLTO won't inline Rust functions into Clang generated
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
||||||
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||||
use rustc_errors::{codes::*, struct_span_code_err};
|
use rustc_errors::{codes::*, struct_span_code_err, DiagMessage, SubdiagMessage};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
|
use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{
|
||||||
|
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
|
||||||
|
};
|
||||||
use rustc_middle::mir::mono::Linkage;
|
use rustc_middle::mir::mono::Linkage;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self as ty, TyCtxt};
|
use rustc_middle::ty::{self as ty, TyCtxt};
|
||||||
|
@ -447,6 +449,80 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
sym::patchable_function_entry => {
|
||||||
|
codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| {
|
||||||
|
let mut prefix = None;
|
||||||
|
let mut entry = None;
|
||||||
|
for item in l {
|
||||||
|
let Some(meta_item) = item.meta_item() else {
|
||||||
|
tcx.dcx().span_err(item.span(), "expected name value pair");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(name_value_lit) = meta_item.name_value_literal() else {
|
||||||
|
tcx.dcx().span_err(item.span(), "expected name value pair");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn emit_error_with_label(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
span: Span,
|
||||||
|
error: impl Into<DiagMessage>,
|
||||||
|
label: impl Into<SubdiagMessage>,
|
||||||
|
) {
|
||||||
|
let mut err: rustc_errors::Diag<'_, _> =
|
||||||
|
tcx.dcx().struct_span_err(span, error);
|
||||||
|
err.span_label(span, label);
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
let attrib_to_write = match meta_item.name_or_empty() {
|
||||||
|
sym::prefix_nops => &mut prefix,
|
||||||
|
sym::entry_nops => &mut entry,
|
||||||
|
_ => {
|
||||||
|
emit_error_with_label(
|
||||||
|
tcx,
|
||||||
|
item.span(),
|
||||||
|
"unexpected parameter name",
|
||||||
|
format!("expected {} or {}", sym::prefix_nops, sym::entry_nops),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else {
|
||||||
|
emit_error_with_label(
|
||||||
|
tcx,
|
||||||
|
name_value_lit.span,
|
||||||
|
"invalid literal value",
|
||||||
|
"value must be an integer between `0` and `255`",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(val) = val.get().try_into() else {
|
||||||
|
emit_error_with_label(
|
||||||
|
tcx,
|
||||||
|
name_value_lit.span,
|
||||||
|
"integer value out of range",
|
||||||
|
"value must be between `0` and `255`",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
*attrib_to_write = Some(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (None, None) = (prefix, entry) {
|
||||||
|
tcx.dcx().span_err(attr.span, "must specify at least one parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(PatchableFunctionEntry::from_prefix_and_entry(
|
||||||
|
prefix.unwrap_or(0),
|
||||||
|
entry.unwrap_or(0),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,6 +585,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
|
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// RFC 3543
|
||||||
|
// `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
|
||||||
|
gated!(
|
||||||
|
patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
|
||||||
|
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes: Stability, deprecation, and unsafe:
|
// Internal attributes: Stability, deprecation, and unsafe:
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
|
@ -563,6 +563,8 @@ declare_features! (
|
||||||
(unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
|
(unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
|
||||||
/// Allows using `#[optimize(X)]`.
|
/// Allows using `#[optimize(X)]`.
|
||||||
(unstable, optimize_attribute, "1.34.0", Some(54882)),
|
(unstable, optimize_attribute, "1.34.0", Some(54882)),
|
||||||
|
/// Allows specifying nop padding on functions for dynamic patching.
|
||||||
|
(unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(123115)),
|
||||||
/// Allows postfix match `expr.match { ... }`
|
/// Allows postfix match `expr.match { ... }`
|
||||||
(unstable, postfix_match, "1.79.0", Some(121618)),
|
(unstable, postfix_match, "1.79.0", Some(121618)),
|
||||||
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
|
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
|
||||||
|
|
|
@ -8,8 +8,8 @@ use rustc_session::config::{
|
||||||
ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
|
ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
|
||||||
Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
|
Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
|
||||||
LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
|
LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
|
||||||
PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
|
PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
|
||||||
SymbolManglingVersion, WasiExecModel,
|
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
|
||||||
};
|
};
|
||||||
use rustc_session::lint::Level;
|
use rustc_session::lint::Level;
|
||||||
use rustc_session::search_paths::SearchPath;
|
use rustc_session::search_paths::SearchPath;
|
||||||
|
@ -813,6 +813,11 @@ fn test_unstable_options_tracking_hash() {
|
||||||
tracked!(packed_bundled_libs, true);
|
tracked!(packed_bundled_libs, true);
|
||||||
tracked!(panic_abort_tests, true);
|
tracked!(panic_abort_tests, true);
|
||||||
tracked!(panic_in_drop, PanicStrategy::Abort);
|
tracked!(panic_in_drop, PanicStrategy::Abort);
|
||||||
|
tracked!(
|
||||||
|
patchable_function_entry,
|
||||||
|
PatchableFunctionEntry::from_total_and_prefix_nops(10, 5)
|
||||||
|
.expect("total must be greater than or equal to prefix")
|
||||||
|
);
|
||||||
tracked!(plt, Some(true));
|
tracked!(plt, Some(true));
|
||||||
tracked!(polonius, Polonius::Legacy);
|
tracked!(polonius, Polonius::Legacy);
|
||||||
tracked!(precise_enum_drop_elaboration, false);
|
tracked!(precise_enum_drop_elaboration, false);
|
||||||
|
|
|
@ -45,6 +45,32 @@ pub struct CodegenFnAttrs {
|
||||||
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
|
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
|
||||||
/// aligned to.
|
/// aligned to.
|
||||||
pub alignment: Option<Align>,
|
pub alignment: Option<Align>,
|
||||||
|
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
|
||||||
|
/// the function entry.
|
||||||
|
pub patchable_function_entry: Option<PatchableFunctionEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||||
|
pub struct PatchableFunctionEntry {
|
||||||
|
/// Nops to prepend to the function
|
||||||
|
prefix: u8,
|
||||||
|
/// Nops after entry, but before body
|
||||||
|
entry: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatchableFunctionEntry {
|
||||||
|
pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self {
|
||||||
|
Self { prefix: config.prefix(), entry: config.entry() }
|
||||||
|
}
|
||||||
|
pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self {
|
||||||
|
Self { prefix, entry }
|
||||||
|
}
|
||||||
|
pub fn prefix(&self) -> u8 {
|
||||||
|
self.prefix
|
||||||
|
}
|
||||||
|
pub fn entry(&self) -> u8 {
|
||||||
|
self.entry
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
||||||
|
@ -121,6 +147,7 @@ impl CodegenFnAttrs {
|
||||||
no_sanitize: SanitizerSet::empty(),
|
no_sanitize: SanitizerSet::empty(),
|
||||||
instruction_set: None,
|
instruction_set: None,
|
||||||
alignment: None,
|
alignment: None,
|
||||||
|
patchable_function_entry: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3432,8 +3432,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let capture_clause = self.parse_capture_clause()?;
|
let capture_clause = self.parse_capture_clause()?;
|
||||||
|
let decl_span = lo.to(self.prev_token.span);
|
||||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
let kind = ExprKind::Gen(capture_clause, body, kind);
|
let kind = ExprKind::Gen(capture_clause, body, kind, decl_span);
|
||||||
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
|
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4022,7 +4023,7 @@ impl MutVisitor for CondChecker<'_> {
|
||||||
| ExprKind::Match(_, _, _)
|
| ExprKind::Match(_, _, _)
|
||||||
| ExprKind::Closure(_)
|
| ExprKind::Closure(_)
|
||||||
| ExprKind::Block(_, _)
|
| ExprKind::Block(_, _)
|
||||||
| ExprKind::Gen(_, _, _)
|
| ExprKind::Gen(_, _, _, _)
|
||||||
| ExprKind::TryBlock(_)
|
| ExprKind::TryBlock(_)
|
||||||
| ExprKind::Underscore
|
| ExprKind::Underscore
|
||||||
| ExprKind::Path(_, _)
|
| ExprKind::Path(_, _)
|
||||||
|
|
|
@ -334,7 +334,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||||
None => closure_def,
|
None => closure_def,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Gen(_, _, _) => {
|
ExprKind::Gen(_, _, _, _) => {
|
||||||
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
|
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
|
||||||
}
|
}
|
||||||
ExprKind::ConstBlock(ref constant) => {
|
ExprKind::ConstBlock(ref constant) => {
|
||||||
|
|
|
@ -2965,8 +2965,9 @@ pub(crate) mod dep_tracking {
|
||||||
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
|
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
|
||||||
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
|
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
|
||||||
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
|
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
|
||||||
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
|
PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
|
||||||
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
|
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
|
||||||
|
WasiExecModel,
|
||||||
};
|
};
|
||||||
use crate::lint;
|
use crate::lint;
|
||||||
use crate::utils::NativeLib;
|
use crate::utils::NativeLib;
|
||||||
|
@ -3073,6 +3074,7 @@ pub(crate) mod dep_tracking {
|
||||||
OomStrategy,
|
OomStrategy,
|
||||||
LanguageIdentifier,
|
LanguageIdentifier,
|
||||||
NextSolverConfig,
|
NextSolverConfig,
|
||||||
|
PatchableFunctionEntry,
|
||||||
Polonius,
|
Polonius,
|
||||||
InliningThreshold,
|
InliningThreshold,
|
||||||
FunctionReturn,
|
FunctionReturn,
|
||||||
|
@ -3250,6 +3252,35 @@ impl DumpMonoStatsFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `-Z patchable-function-entry` representation - how many nops to put before and after function
|
||||||
|
/// entry.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
|
||||||
|
pub struct PatchableFunctionEntry {
|
||||||
|
/// Nops before the entry
|
||||||
|
prefix: u8,
|
||||||
|
/// Nops after the entry
|
||||||
|
entry: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatchableFunctionEntry {
|
||||||
|
pub fn from_total_and_prefix_nops(
|
||||||
|
total_nops: u8,
|
||||||
|
prefix_nops: u8,
|
||||||
|
) -> Option<PatchableFunctionEntry> {
|
||||||
|
if total_nops < prefix_nops {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn prefix(&self) -> u8 {
|
||||||
|
self.prefix
|
||||||
|
}
|
||||||
|
pub fn entry(&self) -> u8 {
|
||||||
|
self.entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
|
/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
|
||||||
/// or future prototype.
|
/// or future prototype.
|
||||||
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
|
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
|
||||||
|
|
|
@ -379,6 +379,7 @@ mod desc {
|
||||||
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
|
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
|
||||||
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
|
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
|
||||||
pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
|
pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
|
||||||
|
pub const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
|
||||||
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
|
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
|
||||||
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
|
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
|
||||||
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
|
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
|
||||||
|
@ -734,6 +735,32 @@ mod parse {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_patchable_function_entry(
|
||||||
|
slot: &mut PatchableFunctionEntry,
|
||||||
|
v: Option<&str>,
|
||||||
|
) -> bool {
|
||||||
|
let mut total_nops = 0;
|
||||||
|
let mut prefix_nops = 0;
|
||||||
|
|
||||||
|
if !parse_number(&mut total_nops, v) {
|
||||||
|
let parts = v.and_then(|v| v.split_once(',')).unzip();
|
||||||
|
if !parse_number(&mut total_nops, parts.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if !parse_number(&mut prefix_nops, parts.1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pfe) =
|
||||||
|
PatchableFunctionEntry::from_total_and_prefix_nops(total_nops, prefix_nops)
|
||||||
|
{
|
||||||
|
*slot = pfe;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
|
pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
|
||||||
match v {
|
match v {
|
||||||
Some("panic") => *slot = OomStrategy::Panic,
|
Some("panic") => *slot = OomStrategy::Panic,
|
||||||
|
@ -1859,6 +1886,8 @@ options! {
|
||||||
"panic strategy for panics in drops"),
|
"panic strategy for panics in drops"),
|
||||||
parse_only: bool = (false, parse_bool, [UNTRACKED],
|
parse_only: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"parse only; do not compile, assemble, or link (default: no)"),
|
"parse only; do not compile, assemble, or link (default: no)"),
|
||||||
|
patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
|
||||||
|
"nop padding at function entry"),
|
||||||
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
"whether to use the PLT when calling into shared libraries;
|
"whether to use the PLT when calling into shared libraries;
|
||||||
only has effect for PIC code on systems with ELF binaries
|
only has effect for PIC code on systems with ELF binaries
|
||||||
|
|
|
@ -6,6 +6,8 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
rustc_abi = { path = "../rustc_abi" }
|
rustc_abi = { path = "../rustc_abi" }
|
||||||
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
|
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
|
|
|
@ -228,6 +228,46 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_attrs_by_path(
|
||||||
|
&self,
|
||||||
|
def_id: stable_mir::DefId,
|
||||||
|
attr: &[stable_mir::Symbol],
|
||||||
|
) -> Vec<stable_mir::crate_def::Attribute> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let did = tables[def_id];
|
||||||
|
let attr_name: Vec<_> =
|
||||||
|
attr.iter().map(|seg| rustc_span::symbol::Symbol::intern(&seg)).collect();
|
||||||
|
tcx.get_attrs_by_path(did, &attr_name)
|
||||||
|
.map(|attribute| {
|
||||||
|
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
|
||||||
|
let span = attribute.span;
|
||||||
|
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_all_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let did = tables[def_id];
|
||||||
|
let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
|
||||||
|
matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
|
||||||
|
};
|
||||||
|
let attrs_iter = if let Some(did) = did.as_local() {
|
||||||
|
tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
||||||
|
} else {
|
||||||
|
tcx.item_attrs(did).iter().filter(filter_fn)
|
||||||
|
};
|
||||||
|
attrs_iter
|
||||||
|
.map(|attribute| {
|
||||||
|
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
|
||||||
|
let span = attribute.span;
|
||||||
|
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
||||||
let tables = self.0.borrow();
|
let tables = self.0.borrow();
|
||||||
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
||||||
|
|
|
@ -768,6 +768,7 @@ symbols! {
|
||||||
enable,
|
enable,
|
||||||
encode,
|
encode,
|
||||||
end,
|
end,
|
||||||
|
entry_nops,
|
||||||
enumerate_method,
|
enumerate_method,
|
||||||
env,
|
env,
|
||||||
env_CFG_RELEASE: env!("CFG_RELEASE"),
|
env_CFG_RELEASE: env!("CFG_RELEASE"),
|
||||||
|
@ -1383,6 +1384,7 @@ symbols! {
|
||||||
passes,
|
passes,
|
||||||
pat,
|
pat,
|
||||||
pat_param,
|
pat_param,
|
||||||
|
patchable_function_entry,
|
||||||
path,
|
path,
|
||||||
pattern_complexity,
|
pattern_complexity,
|
||||||
pattern_parentheses,
|
pattern_parentheses,
|
||||||
|
@ -1421,6 +1423,7 @@ symbols! {
|
||||||
prefetch_read_instruction,
|
prefetch_read_instruction,
|
||||||
prefetch_write_data,
|
prefetch_write_data,
|
||||||
prefetch_write_instruction,
|
prefetch_write_instruction,
|
||||||
|
prefix_nops,
|
||||||
preg,
|
preg,
|
||||||
prelude,
|
prelude,
|
||||||
prelude_import,
|
prelude_import,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use crate::abi::{FnAbi, Layout, LayoutShape};
|
use crate::abi::{FnAbi, Layout, LayoutShape};
|
||||||
|
use crate::crate_def::Attribute;
|
||||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||||
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||||
use crate::mir::{BinOp, Body, Place, UnOp};
|
use crate::mir::{BinOp, Body, Place, UnOp};
|
||||||
|
@ -55,6 +56,15 @@ pub trait Context {
|
||||||
/// Returns the name of given `DefId`
|
/// Returns the name of given `DefId`
|
||||||
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
||||||
|
|
||||||
|
/// Return attributes with the given attribute name.
|
||||||
|
///
|
||||||
|
/// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
|
||||||
|
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
|
||||||
|
fn get_attrs_by_path(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
|
||||||
|
|
||||||
|
/// Get all attributes of a definition.
|
||||||
|
fn get_all_attrs(&self, def_id: DefId) -> Vec<Attribute>;
|
||||||
|
|
||||||
/// Returns printable, human readable form of `Span`
|
/// Returns printable, human readable form of `Span`
|
||||||
fn span_to_string(&self, span: Span) -> String;
|
fn span_to_string(&self, span: Span) -> String;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,21 @@ pub trait CrateDef {
|
||||||
let def_id = self.def_id();
|
let def_id = self.def_id();
|
||||||
with(|cx| cx.span_of_an_item(def_id))
|
with(|cx| cx.span_of_an_item(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return attributes with the given attribute name.
|
||||||
|
///
|
||||||
|
/// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
|
||||||
|
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
|
||||||
|
fn attrs_by_path(&self, attr: &[Symbol]) -> Vec<Attribute> {
|
||||||
|
let def_id = self.def_id();
|
||||||
|
with(|cx| cx.get_attrs_by_path(def_id, attr))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return all attributes of this definition.
|
||||||
|
fn all_attrs(&self) -> Vec<Attribute> {
|
||||||
|
let def_id = self.def_id();
|
||||||
|
with(|cx| cx.get_all_attrs(def_id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that can be used to retrieve a definition's type.
|
/// A trait that can be used to retrieve a definition's type.
|
||||||
|
@ -69,6 +84,28 @@ pub trait CrateDefType: CrateDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Attribute {
|
||||||
|
value: String,
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attribute {
|
||||||
|
pub fn new(value: String, span: Span) -> Attribute {
|
||||||
|
Attribute { value, span }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the span of this attribute.
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
self.span
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the string representation of this attribute.
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! crate_def {
|
macro_rules! crate_def {
|
||||||
( $(#[$attr:meta])*
|
( $(#[$attr:meta])*
|
||||||
$vis:vis $name:ident $(;)?
|
$vis:vis $name:ident $(;)?
|
||||||
|
|
|
@ -206,15 +206,16 @@ impl BorrowMut<str> for String {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl ToOwned for str {
|
impl ToOwned for str {
|
||||||
type Owned = String;
|
type Owned = String;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_owned(&self) -> String {
|
fn to_owned(&self) -> String {
|
||||||
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
|
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn clone_into(&self, target: &mut String) {
|
fn clone_into(&self, target: &mut String) {
|
||||||
let mut b = mem::take(target).into_bytes();
|
target.clear();
|
||||||
self.as_bytes().clone_into(&mut b);
|
target.push_str(self);
|
||||||
*target = unsafe { String::from_utf8_unchecked(b) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -459,6 +459,12 @@ impl<'a> Arguments<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manually implementing these results in better error messages.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl !Send for Arguments<'_> {}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl !Sync for Arguments<'_> {}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Debug for Arguments<'_> {
|
impl Debug for Arguments<'_> {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::hint::unreachable_unchecked;
|
use crate::hint::unreachable_unchecked;
|
||||||
|
use crate::ptr::NonNull;
|
||||||
|
|
||||||
#[lang = "format_placeholder"]
|
#[lang = "format_placeholder"]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -66,7 +67,13 @@ pub(super) enum Flag {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum ArgumentType<'a> {
|
enum ArgumentType<'a> {
|
||||||
Placeholder { value: &'a Opaque, formatter: fn(&Opaque, &mut Formatter<'_>) -> Result },
|
Placeholder {
|
||||||
|
// INVARIANT: `formatter` has type `fn(&T, _) -> _` for some `T`, and `value`
|
||||||
|
// was derived from a `&'a T`.
|
||||||
|
value: NonNull<()>,
|
||||||
|
formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
|
||||||
|
_lifetime: PhantomData<&'a ()>,
|
||||||
|
},
|
||||||
Count(usize),
|
Count(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,21 +97,15 @@ pub struct Argument<'a> {
|
||||||
impl<'a> Argument<'a> {
|
impl<'a> Argument<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
|
fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
|
||||||
// SAFETY: `mem::transmute(x)` is safe because
|
Argument {
|
||||||
// 1. `&'b T` keeps the lifetime it originated with `'b`
|
// INVARIANT: this creates an `ArgumentType<'b>` from a `&'b T` and
|
||||||
// (so as to not have an unbounded lifetime)
|
// a `fn(&T, ...)`, so the invariant is maintained.
|
||||||
// 2. `&'b T` and `&'b Opaque` have the same memory layout
|
ty: ArgumentType::Placeholder {
|
||||||
// (when `T` is `Sized`, as it is here)
|
value: NonNull::from(x).cast(),
|
||||||
// `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
|
// SAFETY: function pointers always have the same layout.
|
||||||
// and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
|
formatter: unsafe { mem::transmute(f) },
|
||||||
// (as long as `T` is `Sized`)
|
_lifetime: PhantomData,
|
||||||
unsafe {
|
},
|
||||||
Argument {
|
|
||||||
ty: ArgumentType::Placeholder {
|
|
||||||
formatter: mem::transmute(f),
|
|
||||||
value: mem::transmute(x),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +163,14 @@ impl<'a> Argument<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
match self.ty {
|
match self.ty {
|
||||||
ArgumentType::Placeholder { formatter, value } => formatter(value, f),
|
// SAFETY:
|
||||||
|
// Because of the invariant that if `formatter` had the type
|
||||||
|
// `fn(&T, _) -> _` then `value` has type `&'b T` where `'b` is
|
||||||
|
// the lifetime of the `ArgumentType`, and because references
|
||||||
|
// and `NonNull` are ABI-compatible, this is completely equivalent
|
||||||
|
// to calling the original function passed to `new` with the
|
||||||
|
// original reference, which is sound.
|
||||||
|
ArgumentType::Placeholder { formatter, value, .. } => unsafe { formatter(value, f) },
|
||||||
// SAFETY: the caller promised this.
|
// SAFETY: the caller promised this.
|
||||||
ArgumentType::Count(_) => unsafe { unreachable_unchecked() },
|
ArgumentType::Count(_) => unsafe { unreachable_unchecked() },
|
||||||
}
|
}
|
||||||
|
@ -208,7 +216,3 @@ impl UnsafeArg {
|
||||||
Self { _private: () }
|
Self { _private: () }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
type Opaque;
|
|
||||||
}
|
|
||||||
|
|
|
@ -888,12 +888,11 @@ impl Step for Rustc {
|
||||||
macro_rules! tool_doc {
|
macro_rules! tool_doc {
|
||||||
(
|
(
|
||||||
$tool: ident,
|
$tool: ident,
|
||||||
$should_run: literal,
|
|
||||||
$path: literal,
|
$path: literal,
|
||||||
$(rustc_tool = $rustc_tool:literal, )?
|
$(rustc_tool = $rustc_tool:literal, )?
|
||||||
$(in_tree = $in_tree:literal ,)?
|
|
||||||
$(is_library = $is_library:expr,)?
|
$(is_library = $is_library:expr,)?
|
||||||
$(crates = $crates:expr)?
|
$(crates = $crates:expr)?
|
||||||
|
$(, submodule $(= $submodule:literal)? )?
|
||||||
) => {
|
) => {
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct $tool {
|
pub struct $tool {
|
||||||
|
@ -907,7 +906,7 @@ macro_rules! tool_doc {
|
||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
let builder = run.builder;
|
let builder = run.builder;
|
||||||
run.crate_or_deps($should_run).default_condition(builder.config.compiler_docs)
|
run.path($path).default_condition(builder.config.compiler_docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
@ -921,6 +920,15 @@ macro_rules! tool_doc {
|
||||||
/// we do not merge it with the other documentation from std, test and
|
/// we do not merge it with the other documentation from std, test and
|
||||||
/// proc_macros. This is largely just a wrapper around `cargo doc`.
|
/// proc_macros. This is largely just a wrapper around `cargo doc`.
|
||||||
fn run(self, builder: &Builder<'_>) {
|
fn run(self, builder: &Builder<'_>) {
|
||||||
|
let source_type = SourceType::InTree;
|
||||||
|
$(
|
||||||
|
let _ = source_type; // silence the "unused variable" warning
|
||||||
|
let source_type = SourceType::Submodule;
|
||||||
|
|
||||||
|
let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
|
||||||
|
builder.update_submodule(&path);
|
||||||
|
)?
|
||||||
|
|
||||||
let stage = builder.top_stage;
|
let stage = builder.top_stage;
|
||||||
let target = self.target;
|
let target = self.target;
|
||||||
|
|
||||||
|
@ -941,12 +949,6 @@ macro_rules! tool_doc {
|
||||||
builder.ensure(compile::Rustc::new(compiler, target));
|
builder.ensure(compile::Rustc::new(compiler, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
let source_type = if true $(&& $in_tree)? {
|
|
||||||
SourceType::InTree
|
|
||||||
} else {
|
|
||||||
SourceType::Submodule
|
|
||||||
};
|
|
||||||
|
|
||||||
// Build cargo command.
|
// Build cargo command.
|
||||||
let mut cargo = prepare_tool_cargo(
|
let mut cargo = prepare_tool_cargo(
|
||||||
builder,
|
builder,
|
||||||
|
@ -1008,21 +1010,14 @@ macro_rules! tool_doc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]);
|
tool_doc!(Rustdoc, "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]);
|
||||||
tool_doc!(
|
tool_doc!(Rustfmt, "src/tools/rustfmt", crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]);
|
||||||
Rustfmt,
|
tool_doc!(Clippy, "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
|
||||||
"rustfmt-nightly",
|
tool_doc!(Miri, "src/tools/miri", crates = ["miri"]);
|
||||||
"src/tools/rustfmt",
|
|
||||||
crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]
|
|
||||||
);
|
|
||||||
tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
|
|
||||||
tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]);
|
|
||||||
tool_doc!(
|
tool_doc!(
|
||||||
Cargo,
|
Cargo,
|
||||||
"cargo",
|
|
||||||
"src/tools/cargo",
|
"src/tools/cargo",
|
||||||
rustc_tool = false,
|
rustc_tool = false,
|
||||||
in_tree = false,
|
|
||||||
crates = [
|
crates = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"cargo-credential",
|
"cargo-credential",
|
||||||
|
@ -1034,12 +1029,12 @@ tool_doc!(
|
||||||
"crates-io",
|
"crates-io",
|
||||||
"mdman",
|
"mdman",
|
||||||
"rustfix",
|
"rustfix",
|
||||||
]
|
],
|
||||||
|
submodule = "src/tools/cargo"
|
||||||
);
|
);
|
||||||
tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, crates = ["tidy"]);
|
tool_doc!(Tidy, "src/tools/tidy", rustc_tool = false, crates = ["tidy"]);
|
||||||
tool_doc!(
|
tool_doc!(
|
||||||
Bootstrap,
|
Bootstrap,
|
||||||
"bootstrap",
|
|
||||||
"src/bootstrap",
|
"src/bootstrap",
|
||||||
rustc_tool = false,
|
rustc_tool = false,
|
||||||
is_library = true,
|
is_library = true,
|
||||||
|
@ -1047,7 +1042,6 @@ tool_doc!(
|
||||||
);
|
);
|
||||||
tool_doc!(
|
tool_doc!(
|
||||||
RunMakeSupport,
|
RunMakeSupport,
|
||||||
"run_make_support",
|
|
||||||
"src/tools/run-make-support",
|
"src/tools/run-make-support",
|
||||||
rustc_tool = false,
|
rustc_tool = false,
|
||||||
is_library = true,
|
is_library = true,
|
||||||
|
|
|
@ -2983,6 +2983,9 @@ impl Step for Bootstrap {
|
||||||
let compiler = builder.compiler(0, host);
|
let compiler = builder.compiler(0, host);
|
||||||
let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
|
let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
|
||||||
|
|
||||||
|
// Some tests require cargo submodule to be present.
|
||||||
|
builder.build.update_submodule(Path::new("src/tools/cargo"));
|
||||||
|
|
||||||
let mut check_bootstrap = Command::new(builder.python());
|
let mut check_bootstrap = Command::new(builder.python());
|
||||||
check_bootstrap
|
check_bootstrap
|
||||||
.args(["-m", "unittest", "bootstrap_test.py"])
|
.args(["-m", "unittest", "bootstrap_test.py"])
|
||||||
|
|
|
@ -656,6 +656,8 @@ impl Step for Cargo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||||
|
builder.build.update_submodule(Path::new("src/tools/cargo"));
|
||||||
|
|
||||||
builder.ensure(ToolBuild {
|
builder.ensure(ToolBuild {
|
||||||
compiler: self.compiler,
|
compiler: self.compiler,
|
||||||
target: self.target,
|
target: self.target,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
@ -34,6 +34,9 @@ impl Step for Vendor {
|
||||||
cmd.arg("--versioned-dirs");
|
cmd.arg("--versioned-dirs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cargo submodule must be present for `x vendor` to work.
|
||||||
|
builder.build.update_submodule(Path::new("src/tools/cargo"));
|
||||||
|
|
||||||
// Sync these paths by default.
|
// Sync these paths by default.
|
||||||
for p in [
|
for p in [
|
||||||
"src/tools/cargo/Cargo.toml",
|
"src/tools/cargo/Cargo.toml",
|
||||||
|
|
|
@ -67,9 +67,9 @@ pub fn build(build: &mut Build) {
|
||||||
|
|
||||||
/// Invokes `cargo metadata` to get package metadata of each workspace member.
|
/// Invokes `cargo metadata` to get package metadata of each workspace member.
|
||||||
///
|
///
|
||||||
/// Note that `src/tools/cargo` is no longer a workspace member but we still
|
/// This is used to resolve specific crate paths in `fn should_run` to compile
|
||||||
/// treat it as one here, by invoking an additional `cargo metadata` command.
|
/// particular crate (e.g., `x build sysroot` to build library/sysroot).
|
||||||
fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
|
fn workspace_members(build: &Build) -> Vec<Package> {
|
||||||
let collect_metadata = |manifest_path| {
|
let collect_metadata = |manifest_path| {
|
||||||
let mut cargo = Command::new(&build.initial_cargo);
|
let mut cargo = Command::new(&build.initial_cargo);
|
||||||
cargo
|
cargo
|
||||||
|
@ -88,13 +88,5 @@ fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collects `metadata.packages` from all workspaces.
|
// Collects `metadata.packages` from all workspaces.
|
||||||
let packages = collect_metadata("Cargo.toml");
|
collect_metadata("Cargo.toml")
|
||||||
let cargo_packages = collect_metadata("src/tools/cargo/Cargo.toml");
|
|
||||||
let ra_packages = collect_metadata("src/tools/rust-analyzer/Cargo.toml");
|
|
||||||
let bootstrap_packages = collect_metadata("src/bootstrap/Cargo.toml");
|
|
||||||
|
|
||||||
// We only care about the root package from `src/tool/cargo` workspace.
|
|
||||||
let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
|
|
||||||
|
|
||||||
packages.into_iter().chain(cargo_package).chain(ra_packages).chain(bootstrap_packages)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,8 +469,7 @@ impl Build {
|
||||||
|
|
||||||
// Make sure we update these before gathering metadata so we don't get an error about missing
|
// Make sure we update these before gathering metadata so we don't get an error about missing
|
||||||
// Cargo.toml files.
|
// Cargo.toml files.
|
||||||
let rust_submodules =
|
let rust_submodules = ["src/doc/book", "library/backtrace", "library/stdarch"];
|
||||||
["src/tools/cargo", "src/doc/book", "library/backtrace", "library/stdarch"];
|
|
||||||
for s in rust_submodules {
|
for s in rust_submodules {
|
||||||
build.update_submodule(Path::new(s));
|
build.update_submodule(Path::new(s));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# `patchable-function-entry`
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The `-Z patchable-function-entry=total_nops,prefix_nops` or `-Z patchable-function-entry=total_nops`
|
||||||
|
compiler flag enables nop padding of function entries with 'total_nops' nops, with
|
||||||
|
an offset for the entry of the function at 'prefix_nops' nops. In the second form,
|
||||||
|
'prefix_nops' defaults to 0.
|
||||||
|
|
||||||
|
As an illustrative example, `-Z patchable-function-entry=3,2` would produce:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
function_label:
|
||||||
|
nop
|
||||||
|
//Actual function code begins here
|
||||||
|
```
|
||||||
|
|
||||||
|
This flag is used for hotpatching, especially in the Linux kernel. The flag
|
||||||
|
arguments are modeled after the `-fpatchable-function-entry` flag as defined
|
||||||
|
for both [Clang](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fpatchable-function-entry)
|
||||||
|
and [gcc](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fpatchable-function-entry)
|
||||||
|
and is intended to provide the same effect.
|
|
@ -549,7 +549,7 @@ fn ident_difference_expr_with_base_location(
|
||||||
| (Assign(_, _, _), Assign(_, _, _))
|
| (Assign(_, _, _), Assign(_, _, _))
|
||||||
| (TryBlock(_), TryBlock(_))
|
| (TryBlock(_), TryBlock(_))
|
||||||
| (Await(_, _), Await(_, _))
|
| (Await(_, _), Await(_, _))
|
||||||
| (Gen(_, _, _), Gen(_, _, _))
|
| (Gen(_, _, _, _), Gen(_, _, _, _))
|
||||||
| (Block(_, _), Block(_, _))
|
| (Block(_, _), Block(_, _))
|
||||||
| (Closure(_), Closure(_))
|
| (Closure(_), Closure(_))
|
||||||
| (Match(_, _, _), Match(_, _, _))
|
| (Match(_, _, _), Match(_, _, _))
|
||||||
|
|
|
@ -226,7 +226,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||||
&& eq_fn_decl(lf, rf)
|
&& eq_fn_decl(lf, rf)
|
||||||
&& eq_expr(le, re)
|
&& eq_expr(le, re)
|
||||||
},
|
},
|
||||||
(Gen(lc, lb, lk), Gen(rc, rb, rk)) => lc == rc && eq_block(lb, rb) && lk == rk,
|
(Gen(lc, lb, lk, _), Gen(rc, rb, rk, _)) => lc == rc && eq_block(lb, rb) && lk == rk,
|
||||||
(Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt),
|
(Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt),
|
||||||
(AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
|
(AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
|
||||||
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
|
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
|
||||||
|
|
|
@ -372,7 +372,7 @@ pub(crate) fn format_expr(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Gen(capture_by, ref block, ref kind) => {
|
ast::ExprKind::Gen(capture_by, ref block, ref kind, _) => {
|
||||||
let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
|
let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
|
||||||
"move "
|
"move "
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//@ compile-flags: -Z patchable-function-entry=15,10
|
||||||
|
|
||||||
|
#![feature(patchable_function_entry)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// This should have the default, as set by the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn fun0() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
|
||||||
|
pub fn fun1() {}
|
||||||
|
|
||||||
|
// If we override an attribute to 0 or unset, the attribute should go away
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(entry_nops = 0)]
|
||||||
|
pub fn fun2() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 20, entry_nops = 1)]
|
||||||
|
pub fn fun3() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 2, entry_nops = 19)]
|
||||||
|
pub fn fun4() {}
|
||||||
|
|
||||||
|
// The attribute should override patchable-function-entry to 3 and
|
||||||
|
// patchable-function-prefix to the default of 0, clearing it entirely
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(entry_nops = 3)]
|
||||||
|
pub fn fun5() {}
|
||||||
|
|
||||||
|
// The attribute should override patchable-function-prefix to 4
|
||||||
|
// and patchable-function-entry to the default of 0, clearing it entirely
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 4)]
|
||||||
|
pub fn fun6() {}
|
||||||
|
|
||||||
|
// CHECK: @fun0() unnamed_addr #0
|
||||||
|
// CHECK: @fun1() unnamed_addr #1
|
||||||
|
// CHECK: @fun2() unnamed_addr #2
|
||||||
|
// CHECK: @fun3() unnamed_addr #3
|
||||||
|
// CHECK: @fun4() unnamed_addr #4
|
||||||
|
// CHECK: @fun5() unnamed_addr #5
|
||||||
|
// CHECK: @fun6() unnamed_addr #6
|
||||||
|
|
||||||
|
// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-prefix"="10" {{.*}} }
|
||||||
|
// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
|
||||||
|
|
||||||
|
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-entry{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
// CHECK: attributes #2 = { {{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #3 = { {{.*}}"patchable-function-entry"="1"{{.*}}"patchable-function-prefix"="20" {{.*}} }
|
||||||
|
// CHECK: attributes #4 = { {{.*}}"patchable-function-entry"="19"{{.*}}"patchable-function-prefix"="2" {{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #5 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #5 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #6 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #6 = { {{.*}}patchable-function-entry{{.*}} }
|
|
@ -0,0 +1,39 @@
|
||||||
|
#![feature(patchable_function_entry)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// No patchable function entry should be set
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn fun0() {}
|
||||||
|
|
||||||
|
// The attribute should work even without compiler flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
|
||||||
|
pub fn fun1() {}
|
||||||
|
|
||||||
|
// The attribute should work even without compiler flags
|
||||||
|
// and only set patchable-function-entry to 3.
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(entry_nops = 3)]
|
||||||
|
pub fn fun2() {}
|
||||||
|
|
||||||
|
// The attribute should work even without compiler flags
|
||||||
|
// and only set patchable-function-prefix to 4.
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 4)]
|
||||||
|
pub fn fun3() {}
|
||||||
|
|
||||||
|
// CHECK: @fun0() unnamed_addr #0
|
||||||
|
// CHECK: @fun1() unnamed_addr #1
|
||||||
|
// CHECK: @fun2() unnamed_addr #2
|
||||||
|
// CHECK: @fun3() unnamed_addr #3
|
||||||
|
|
||||||
|
// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-entry{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #2 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #3 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #3 = { {{.*}}patchable-function-entry{{.*}} }
|
|
@ -0,0 +1,66 @@
|
||||||
|
//@ compile-flags: -Z patchable-function-entry=15
|
||||||
|
|
||||||
|
#![feature(patchable_function_entry)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// This should have the default, as set by the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn fun0() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
|
||||||
|
pub fn fun1() {}
|
||||||
|
|
||||||
|
// If we override an attribute to 0 or unset, the attribute should go away
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(entry_nops = 0)]
|
||||||
|
pub fn fun2() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 20, entry_nops = 1)]
|
||||||
|
pub fn fun3() {}
|
||||||
|
|
||||||
|
// The attribute should override the compile flags
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 2, entry_nops = 19)]
|
||||||
|
pub fn fun4() {}
|
||||||
|
|
||||||
|
// The attribute should override patchable-function-entry to 3
|
||||||
|
// and patchable-function-prefix to the default of 0, clearing it entirely
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(entry_nops = 3)]
|
||||||
|
pub fn fun5() {}
|
||||||
|
|
||||||
|
// The attribute should override patchable-function-prefix to 4
|
||||||
|
// and patchable-function-entry to the default of 0, clearing it entirely
|
||||||
|
#[no_mangle]
|
||||||
|
#[patchable_function_entry(prefix_nops = 4)]
|
||||||
|
pub fn fun6() {}
|
||||||
|
|
||||||
|
// CHECK: @fun0() unnamed_addr #0
|
||||||
|
// CHECK: @fun1() unnamed_addr #1
|
||||||
|
// CHECK: @fun2() unnamed_addr #2
|
||||||
|
// CHECK: @fun3() unnamed_addr #3
|
||||||
|
// CHECK: @fun4() unnamed_addr #4
|
||||||
|
// CHECK: @fun5() unnamed_addr #5
|
||||||
|
// CHECK: @fun6() unnamed_addr #6
|
||||||
|
|
||||||
|
// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="15" {{.*}} }
|
||||||
|
// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
|
||||||
|
|
||||||
|
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-entry{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
// CHECK: attributes #2 = { {{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #3 = { {{.*}}"patchable-function-entry"="1"{{.*}}"patchable-function-prefix"="20" {{.*}} }
|
||||||
|
// CHECK: attributes #4 = { {{.*}}"patchable-function-entry"="19"{{.*}}"patchable-function-prefix"="2" {{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #5 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #5 = { {{.*}}patchable-function-prefix{{.*}} }
|
||||||
|
|
||||||
|
// CHECK: attributes #6 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
|
||||||
|
// CHECK-NOT: attributes #6 = { {{.*}}patchable-function-entry{{.*}} }
|
|
@ -1,12 +1,12 @@
|
||||||
Function name: issue_83601::main
|
Function name: issue_83601::main
|
||||||
Raw bytes (21): 0x[01, 01, 01, 05, 00, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
|
Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 1
|
Number of expressions: 1
|
||||||
- expression 0 operands: lhs = Counter(1), rhs = Zero
|
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
|
||||||
Number of file 0 mappings: 3
|
Number of file 0 mappings: 3
|
||||||
- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
|
- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
|
||||||
- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
|
- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
|
||||||
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
|
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
|
||||||
= (c1 - Zero)
|
= (c1 - c2)
|
||||||
|
|
||||||
|
|
|
@ -54,15 +54,15 @@ Number of file 0 mappings: 1
|
||||||
- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10)
|
- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10)
|
||||||
|
|
||||||
Function name: issue_84561::test3
|
Function name: issue_84561::test3
|
||||||
Raw bytes (375): 0x[01, 01, 31, 05, 00, 0d, 00, 15, 00, 12, 00, 15, 00, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
|
Raw bytes (375): 0x[01, 01, 31, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 49
|
Number of expressions: 49
|
||||||
- expression 0 operands: lhs = Counter(1), rhs = Zero
|
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
|
||||||
- expression 1 operands: lhs = Counter(3), rhs = Zero
|
- expression 1 operands: lhs = Counter(3), rhs = Zero
|
||||||
- expression 2 operands: lhs = Counter(5), rhs = Zero
|
- expression 2 operands: lhs = Counter(5), rhs = Counter(6)
|
||||||
- expression 3 operands: lhs = Expression(4, Sub), rhs = Zero
|
- expression 3 operands: lhs = Expression(4, Sub), rhs = Zero
|
||||||
- expression 4 operands: lhs = Counter(5), rhs = Zero
|
- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
|
||||||
- expression 5 operands: lhs = Counter(8), rhs = Zero
|
- expression 5 operands: lhs = Counter(8), rhs = Zero
|
||||||
- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
|
- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
|
||||||
- expression 7 operands: lhs = Counter(8), rhs = Zero
|
- expression 7 operands: lhs = Counter(8), rhs = Zero
|
||||||
|
@ -111,15 +111,15 @@ Number of file 0 mappings: 51
|
||||||
- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
|
- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
|
||||||
- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
|
- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
|
||||||
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31)
|
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31)
|
||||||
= (c1 - Zero)
|
= (c1 - c2)
|
||||||
- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
|
- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
|
||||||
- Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
|
- Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
|
||||||
= (c3 - Zero)
|
= (c3 - Zero)
|
||||||
- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
|
- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
|
||||||
- Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31)
|
- Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31)
|
||||||
= (c5 - Zero)
|
= (c5 - c6)
|
||||||
- Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
|
- Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
|
||||||
= ((c5 - Zero) - Zero)
|
= ((c5 - c6) - Zero)
|
||||||
- Code(Zero) at (prev + 0, 32) to (start + 0, 48)
|
- Code(Zero) at (prev + 0, 32) to (start + 0, 48)
|
||||||
- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
|
- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
|
||||||
- Code(Zero) at (prev + 3, 32) to (start + 0, 48)
|
- Code(Zero) at (prev + 3, 32) to (start + 0, 48)
|
||||||
|
|
155
tests/ui-fulldeps/stable-mir/check_attribute.rs
Normal file
155
tests/ui-fulldeps/stable-mir/check_attribute.rs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
//@ run-pass
|
||||||
|
//! Test information regarding type layout.
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
|
|
||||||
|
extern crate rustc_hir;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rustc_smir;
|
||||||
|
extern crate rustc_driver;
|
||||||
|
extern crate rustc_interface;
|
||||||
|
extern crate stable_mir;
|
||||||
|
|
||||||
|
use rustc_smir::rustc_internal;
|
||||||
|
use stable_mir::{CrateDef, CrateItems};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
const CRATE_NAME: &str = "input";
|
||||||
|
|
||||||
|
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||||
|
fn test_stable_mir() -> ControlFlow<()> {
|
||||||
|
// Find items in the local crate.
|
||||||
|
let items = stable_mir::all_local_items();
|
||||||
|
|
||||||
|
test_builtins(&items);
|
||||||
|
test_derive(&items);
|
||||||
|
test_tool(&items);
|
||||||
|
test_all_attrs(&items);
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test built-in attributes.
|
||||||
|
fn test_builtins(items: &CrateItems) {
|
||||||
|
let target_fn = *get_item(&items, "builtins_fn").unwrap();
|
||||||
|
let allow_attrs = target_fn.attrs_by_path(&["allow".to_string()]);
|
||||||
|
assert_eq!(allow_attrs[0].as_str(), "#![allow(unused_variables)]");
|
||||||
|
|
||||||
|
let inline_attrs = target_fn.attrs_by_path(&["inline".to_string()]);
|
||||||
|
assert_eq!(inline_attrs[0].as_str(), "#[inline]");
|
||||||
|
|
||||||
|
let deprecated_attrs = target_fn.attrs_by_path(&["deprecated".to_string()]);
|
||||||
|
assert_eq!(deprecated_attrs[0].as_str(), "#[deprecated(since = \"5.2.0\")]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test derive attribute.
|
||||||
|
fn test_derive(items: &CrateItems) {
|
||||||
|
let target_struct = *get_item(&items, "Foo").unwrap();
|
||||||
|
let attrs = target_struct.attrs_by_path(&["derive".to_string()]);
|
||||||
|
// No `derive` attribute since it's expanded before MIR.
|
||||||
|
assert_eq!(attrs.len(), 0);
|
||||||
|
|
||||||
|
// Check derived trait method's attributes.
|
||||||
|
let derived_fmt = *get_item(&items, "<Foo as std::fmt::Debug>::fmt").unwrap();
|
||||||
|
// The Rust reference lies about this attribute. It doesn't show up in `clone` or `fmt` impl.
|
||||||
|
let _fmt_attrs = derived_fmt.attrs_by_path(&["automatically_derived".to_string()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test tool attributes.
|
||||||
|
fn test_tool(items: &CrateItems) {
|
||||||
|
let rustfmt_fn = *get_item(&items, "do_not_format").unwrap();
|
||||||
|
let rustfmt_attrs = rustfmt_fn.attrs_by_path(&["rustfmt".to_string(), "skip".to_string()]);
|
||||||
|
assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]");
|
||||||
|
|
||||||
|
let clippy_fn = *get_item(&items, "complex_fn").unwrap();
|
||||||
|
let clippy_attrs = clippy_fn.attrs_by_path(&["clippy".to_string(),
|
||||||
|
"cyclomatic_complexity".to_string()]);
|
||||||
|
assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_all_attrs(items: &CrateItems) {
|
||||||
|
let target_fn = *get_item(&items, "many_attrs").unwrap();
|
||||||
|
let all_attrs = target_fn.all_attrs();
|
||||||
|
assert_eq!(all_attrs[0].as_str(), "#[inline]");
|
||||||
|
assert_eq!(all_attrs[1].as_str(), "#[allow(unused_variables)]");
|
||||||
|
assert_eq!(all_attrs[2].as_str(), "#[allow(dead_code)]");
|
||||||
|
assert_eq!(all_attrs[3].as_str(), "#[allow(unused_imports)]");
|
||||||
|
assert_eq!(all_attrs[4].as_str(), "#![allow(clippy::filter_map)]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn get_item<'a>(
|
||||||
|
items: &'a CrateItems,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<&'a stable_mir::CrateItem> {
|
||||||
|
items.iter().find(|crate_item| crate_item.name() == name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||||
|
/// For that, it will first write the dummy crate into a file.
|
||||||
|
/// Then it will create a `StableMir` using custom arguments and then
|
||||||
|
/// it will run the compiler.
|
||||||
|
fn main() {
|
||||||
|
let path = "attribute_input.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec![
|
||||||
|
"rustc".to_string(),
|
||||||
|
"--crate-type=lib".to_string(),
|
||||||
|
"--crate-name".to_string(),
|
||||||
|
CRATE_NAME.to_string(),
|
||||||
|
path.to_string(),
|
||||||
|
];
|
||||||
|
run!(args, test_stable_mir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
// General metadata applied to the enclosing module or crate.
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// Mixed inner and outer attributes.
|
||||||
|
#[inline]
|
||||||
|
#[deprecated(since = "5.2.0")]
|
||||||
|
fn builtins_fn() {{
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
let x = ();
|
||||||
|
let y = ();
|
||||||
|
let z = ();
|
||||||
|
}}
|
||||||
|
|
||||||
|
// A derive attribute to automatically implement a trait.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Foo(u32);
|
||||||
|
|
||||||
|
// A rustfmt tool attribute.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn do_not_format() {{}}
|
||||||
|
|
||||||
|
// A clippy tool attribute.
|
||||||
|
#[clippy::cyclomatic_complexity = "100"]
|
||||||
|
pub fn complex_fn() {{}}
|
||||||
|
|
||||||
|
// A function with many attributes.
|
||||||
|
#[inline]
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
fn many_attrs() {{
|
||||||
|
#![allow(clippy::filter_map)]
|
||||||
|
todo!()
|
||||||
|
}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,20 +1,18 @@
|
||||||
error[E0267]: `break` inside `async` block
|
error[E0267]: `break` inside `async` block
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:32:9
|
--> $DIR/async-block-control-flow-static-semantics.rs:32:9
|
||||||
|
|
|
|
||||||
LL | / async {
|
LL | async {
|
||||||
LL | | break 0u8;
|
| ----- enclosing `async` block
|
||||||
| | ^^^^^^^^^ cannot `break` inside `async` block
|
LL | break 0u8;
|
||||||
LL | | };
|
| ^^^^^^^^^ cannot `break` inside `async` block
|
||||||
| |_____- enclosing `async` block
|
|
||||||
|
|
||||||
error[E0267]: `break` inside `async` block
|
error[E0267]: `break` inside `async` block
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:39:13
|
--> $DIR/async-block-control-flow-static-semantics.rs:39:13
|
||||||
|
|
|
|
||||||
LL | / async {
|
LL | async {
|
||||||
LL | | break 0u8;
|
| ----- enclosing `async` block
|
||||||
| | ^^^^^^^^^ cannot `break` inside `async` block
|
LL | break 0u8;
|
||||||
LL | | };
|
| ^^^^^^^^^ cannot `break` inside `async` block
|
||||||
| |_________- enclosing `async` block
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:21:58
|
--> $DIR/async-block-control-flow-static-semantics.rs:21:58
|
||||||
|
@ -29,13 +27,13 @@ LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^ expected `u8`, found `()`
|
| |_^ expected `u8`, found `()`
|
||||||
|
|
||||||
error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to be a future that resolves to `()`, but it resolves to `u8`
|
error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 23:22}` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Future<Output = ()> = █
|
LL | let _: &dyn Future<Output = ()> = █
|
||||||
| ^^^^^^ expected `()`, found `u8`
|
| ^^^^^^ expected `()`, found `u8`
|
||||||
|
|
|
|
||||||
= note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to `&dyn Future<Output = ()>`
|
= note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 23:22}` to `&dyn Future<Output = ()>`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:12:43
|
--> $DIR/async-block-control-flow-static-semantics.rs:12:43
|
||||||
|
@ -45,13 +43,13 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
|
||||||
| |
|
| |
|
||||||
| implicitly returns `()` as its body has no tail or `return` expression
|
| implicitly returns `()` as its body has no tail or `return` expression
|
||||||
|
|
||||||
error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to be a future that resolves to `()`, but it resolves to `u8`
|
error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 14:22}` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Future<Output = ()> = █
|
LL | let _: &dyn Future<Output = ()> = █
|
||||||
| ^^^^^^ expected `()`, found `u8`
|
| ^^^^^^ expected `()`, found `u8`
|
||||||
|
|
|
|
||||||
= note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to `&dyn Future<Output = ()>`
|
= note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 14:22}` to `&dyn Future<Output = ()>`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
||||||
|
|
|
@ -2,9 +2,8 @@ error[E0373]: async block may outlive the current function, but it borrows `x`,
|
||||||
--> $DIR/async-borrowck-escaping-block-error.rs:6:14
|
--> $DIR/async-borrowck-escaping-block-error.rs:6:14
|
||||||
|
|
|
|
||||||
LL | Box::new(async { x } )
|
LL | Box::new(async { x } )
|
||||||
| ^^^^^^^^-^^
|
| ^^^^^ - `x` is borrowed here
|
||||||
| | |
|
| |
|
||||||
| | `x` is borrowed here
|
|
||||||
| may outlive borrowed value `x`
|
| may outlive borrowed value `x`
|
||||||
|
|
|
|
||||||
note: async block is returned here
|
note: async block is returned here
|
||||||
|
@ -21,9 +20,8 @@ error[E0373]: async block may outlive the current function, but it borrows `x`,
|
||||||
--> $DIR/async-borrowck-escaping-block-error.rs:11:5
|
--> $DIR/async-borrowck-escaping-block-error.rs:11:5
|
||||||
|
|
|
|
||||||
LL | async { *x }
|
LL | async { *x }
|
||||||
| ^^^^^^^^--^^
|
| ^^^^^ -- `x` is borrowed here
|
||||||
| | |
|
| |
|
||||||
| | `x` is borrowed here
|
|
||||||
| may outlive borrowed value `x`
|
| may outlive borrowed value `x`
|
||||||
|
|
|
|
||||||
note: async block is returned here
|
note: async block is returned here
|
||||||
|
|
|
@ -22,20 +22,18 @@ LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||||
--> $DIR/wrong-fn-kind.rs:9:20
|
--> $DIR/wrong-fn-kind.rs:9:20
|
||||||
|
|
|
|
||||||
LL | fn needs_async_fn(_: impl async Fn()) {}
|
LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||||
| --------------- change this to accept `FnMut` instead of `Fn`
|
| --------------- change this to accept `FnMut` instead of `Fn`
|
||||||
...
|
...
|
||||||
LL | needs_async_fn(async || {
|
LL | needs_async_fn(async || {
|
||||||
| -------------- ^-------
|
| -------------- ^^^^^^^^
|
||||||
| | |
|
| | |
|
||||||
| _____|______________in this closure
|
| | cannot borrow as mutable
|
||||||
| | |
|
| | in this closure
|
||||||
| | expects `Fn` instead of `FnMut`
|
| expects `Fn` instead of `FnMut`
|
||||||
LL | |
|
LL |
|
||||||
LL | | x += 1;
|
LL | x += 1;
|
||||||
| | - mutable borrow occurs due to use of `x` in closure
|
| - mutable borrow occurs due to use of `x` in closure
|
||||||
LL | | });
|
|
||||||
| |_____^ cannot borrow as mutable
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
|
error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
|
||||||
--> $DIR/async-is-unwindsafe.rs:12:5
|
--> $DIR/async-is-unwindsafe.rs:12:5
|
||||||
|
|
|
|
||||||
LL | is_unwindsafe(async {
|
LL | is_unwindsafe(async {
|
||||||
| ______^ -
|
| ^ ----- within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`
|
||||||
| | ___________________|
|
| _____|
|
||||||
LL | ||
|
| |
|
||||||
LL | || use std::ptr::null;
|
LL | |
|
||||||
LL | || use std::task::{Context, RawWaker, RawWakerVTable, Waker};
|
LL | | use std::ptr::null;
|
||||||
... ||
|
LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker};
|
||||||
LL | || drop(cx_ref);
|
... |
|
||||||
LL | || });
|
LL | | drop(cx_ref);
|
||||||
| ||_____-^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
|
LL | | });
|
||||||
| |_____|
|
| |______^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
|
||||||
| within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`
|
|
||||||
|
|
|
|
||||||
= help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe`
|
= help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}: UnwindSafe`
|
||||||
= note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>`
|
= note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>`
|
||||||
note: future does not implement `UnwindSafe` as this value is used across an await
|
note: future does not implement `UnwindSafe` as this value is used across an await
|
||||||
--> $DIR/async-is-unwindsafe.rs:25:18
|
--> $DIR/async-is-unwindsafe.rs:25:18
|
||||||
|
|
|
@ -8,8 +8,8 @@ LL | fun(async {}, async {});
|
||||||
| | expected all arguments to be this `async` block type because they need to match the type of this parameter
|
| | expected all arguments to be this `async` block type because they need to match the type of this parameter
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
|
= note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:14}`
|
||||||
found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:27}`
|
found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:24}`
|
||||||
= note: no two async blocks, even if identical, have the same type
|
= note: no two async blocks, even if identical, have the same type
|
||||||
= help: consider pinning your async block and casting it to a trait object
|
= help: consider pinning your async block and casting it to a trait object
|
||||||
note: function defined here
|
note: function defined here
|
||||||
|
|
|
@ -26,11 +26,11 @@ note: required by a bound in `takes_coroutine`
|
||||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}: Coroutine<_>` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}: Coroutine<_>` is not satisfied
|
||||||
--> $DIR/coroutine-not-future.rs:39:21
|
--> $DIR/coroutine-not-future.rs:39:21
|
||||||
|
|
|
|
||||||
LL | takes_coroutine(async {});
|
LL | takes_coroutine(async {});
|
||||||
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}`
|
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | | let _a = a;
|
||||||
LL | | });
|
LL | | });
|
||||||
| |______^ future created by async block is not `Send`
|
| |______^ future created by async block is not `Send`
|
||||||
|
|
|
|
||||||
= help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}: Send`
|
= help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}: Send`
|
||||||
note: future is not `Send` as this value is used across an await
|
note: future is not `Send` as this value is used across an await
|
||||||
--> $DIR/issue-67252-unnamed-future.rs:20:17
|
--> $DIR/issue-67252-unnamed-future.rs:20:17
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
|
||||||
LL | require_send(send_fut);
|
LL | require_send(send_fut);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
| ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
||||||
|
|
|
|
||||||
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 33:6}: Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 29:25}: Send`
|
||||||
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
||||||
note: future is not `Send` as it awaits another future which is not `Send`
|
note: future is not `Send` as it awaits another future which is not `Send`
|
||||||
--> $DIR/issue-68112.rs:31:17
|
--> $DIR/issue-68112.rs:31:17
|
||||||
|
@ -23,7 +23,7 @@ error: future cannot be sent between threads safely
|
||||||
LL | require_send(send_fut);
|
LL | require_send(send_fut);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
| ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
||||||
|
|
|
|
||||||
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 42:6}: Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 39:25}: Send`
|
||||||
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
||||||
note: future is not `Send` as it awaits another future which is not `Send`
|
note: future is not `Send` as it awaits another future which is not `Send`
|
||||||
--> $DIR/issue-68112.rs:40:17
|
--> $DIR/issue-68112.rs:40:17
|
||||||
|
@ -42,7 +42,7 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
|
||||||
LL | require_send(send_fut);
|
LL | require_send(send_fut);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
|
| ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
|
||||||
|
|
|
|
||||||
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 61:6}: Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 57:25}: Send`
|
||||||
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
|
||||||
= note: required for `Arc<RefCell<i32>>` to implement `Send`
|
= note: required for `Arc<RefCell<i32>>` to implement `Send`
|
||||||
note: required because it's used within this `async` fn body
|
note: required because it's used within this `async` fn body
|
||||||
|
@ -61,13 +61,8 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
|
||||||
note: required because it's used within this `async` block
|
note: required because it's used within this `async` block
|
||||||
--> $DIR/issue-68112.rs:57:20
|
--> $DIR/issue-68112.rs:57:20
|
||||||
|
|
|
|
||||||
LL | let send_fut = async {
|
LL | let send_fut = async {
|
||||||
| ____________________^
|
| ^^^^^
|
||||||
LL | | let non_send_fut = make_non_send_future2();
|
|
||||||
LL | | let _ = non_send_fut.await;
|
|
||||||
LL | | ready(0).await;
|
|
||||||
LL | | };
|
|
||||||
| |_____^
|
|
||||||
note: required by a bound in `require_send`
|
note: required by a bound in `require_send`
|
||||||
--> $DIR/issue-68112.rs:11:25
|
--> $DIR/issue-68112.rs:11:25
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
|
||||||
LL | fn foo(x: NotSync) -> impl Future + Send {
|
LL | fn foo(x: NotSync) -> impl Future + Send {
|
||||||
| ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
|
| ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
|
||||||
|
|
|
|
||||||
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send`
|
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
|
||||||
note: required because it appears within the type `PhantomData<*mut ()>`
|
note: required because it appears within the type `PhantomData<*mut ()>`
|
||||||
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
||||||
note: required because it appears within the type `NotSync`
|
note: required because it appears within the type `NotSync`
|
||||||
|
@ -28,12 +28,8 @@ LL | | }
|
||||||
note: required because it's used within this `async` block
|
note: required because it's used within this `async` block
|
||||||
--> $DIR/issue-70935-complex-spans.rs:18:5
|
--> $DIR/issue-70935-complex-spans.rs:18:5
|
||||||
|
|
|
|
||||||
LL | / async move {
|
LL | async move {
|
||||||
LL | | baz(|| async {
|
| ^^^^^^^^^^
|
||||||
LL | | foo(x.clone());
|
|
||||||
LL | | }).await;
|
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
||||||
error[E0277]: `*mut ()` cannot be shared between threads safely
|
error[E0277]: `*mut ()` cannot be shared between threads safely
|
||||||
--> $DIR/issue-70935-complex-spans.rs:15:23
|
--> $DIR/issue-70935-complex-spans.rs:15:23
|
||||||
|
@ -41,7 +37,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
|
||||||
LL | fn foo(x: NotSync) -> impl Future + Send {
|
LL | fn foo(x: NotSync) -> impl Future + Send {
|
||||||
| ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
|
| ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
|
||||||
|
|
|
|
||||||
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send`
|
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
|
||||||
note: required because it appears within the type `PhantomData<*mut ()>`
|
note: required because it appears within the type `PhantomData<*mut ()>`
|
||||||
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
||||||
note: required because it appears within the type `NotSync`
|
note: required because it appears within the type `NotSync`
|
||||||
|
@ -65,12 +61,8 @@ LL | | }
|
||||||
note: required because it's used within this `async` block
|
note: required because it's used within this `async` block
|
||||||
--> $DIR/issue-70935-complex-spans.rs:18:5
|
--> $DIR/issue-70935-complex-spans.rs:18:5
|
||||||
|
|
|
|
||||||
LL | / async move {
|
LL | async move {
|
||||||
LL | | baz(|| async {
|
| ^^^^^^^^^^
|
||||||
LL | | foo(x.clone());
|
|
||||||
LL | | }).await;
|
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -13,14 +13,15 @@ LL | y
|
||||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
|
--> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
|
||||||
|
|
|
|
||||||
|
LL | (async move || {
|
||||||
|
| - return type of async closure is &'1 i32
|
||||||
|
...
|
||||||
LL | let y = &*x;
|
LL | let y = &*x;
|
||||||
| --- `*x` is borrowed here
|
| --- `*x` is borrowed here
|
||||||
LL | *x += 1;
|
LL | *x += 1;
|
||||||
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
||||||
LL | y
|
LL | y
|
||||||
| - returning this value requires that `*x` is borrowed for `'1`
|
| - returning this value requires that `*x` is borrowed for `'1`
|
||||||
LL | })()
|
|
||||||
| - return type of async closure is &'1 i32
|
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
|
--> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
|
||||||
|
@ -61,14 +62,15 @@ LL | }
|
||||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
|
--> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
|
||||||
|
|
|
|
||||||
|
LL | (async move || -> &i32 {
|
||||||
|
| - return type of async closure is &'1 i32
|
||||||
|
...
|
||||||
LL | let y = &*x;
|
LL | let y = &*x;
|
||||||
| --- `*x` is borrowed here
|
| --- `*x` is borrowed here
|
||||||
LL | *x += 1;
|
LL | *x += 1;
|
||||||
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
||||||
LL | y
|
LL | y
|
||||||
| - returning this value requires that `*x` is borrowed for `'1`
|
| - returning this value requires that `*x` is borrowed for `'1`
|
||||||
LL | })()
|
|
||||||
| - return type of async closure is &'1 i32
|
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
|
--> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
|
||||||
|
@ -109,14 +111,14 @@ LL | }
|
||||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
|
--> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
|
||||||
|
|
|
|
||||||
|
LL | async move {
|
||||||
|
| - return type of async block is &'1 i32
|
||||||
LL | let y = &*x;
|
LL | let y = &*x;
|
||||||
| --- `*x` is borrowed here
|
| --- `*x` is borrowed here
|
||||||
LL | *x += 1;
|
LL | *x += 1;
|
||||||
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
||||||
LL | y
|
LL | y
|
||||||
| - returning this value requires that `*x` is borrowed for `'1`
|
| - returning this value requires that `*x` is borrowed for `'1`
|
||||||
LL | }
|
|
||||||
| - return type of async block is &'1 i32
|
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
|
||||||
|
|
|
|
||||||
LL | let x = x;
|
LL | let x = x;
|
||||||
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
||||||
= note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 20:18}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
|
= note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
|
||||||
help: consider further restricting this bound
|
help: consider further restricting this bound
|
||||||
|
|
|
|
||||||
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
|
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
|
error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
|
||||||
--> $DIR/issue-78938-async-block.rs:8:33
|
--> $DIR/issue-78938-async-block.rs:8:33
|
||||||
|
|
|
|
||||||
LL | let gameloop_handle = spawn(async {
|
LL | let gameloop_handle = spawn(async {
|
||||||
| _________________________________^
|
| ^^^^^ may outlive borrowed value `room_ref`
|
||||||
LL | | game_loop(Arc::clone(&room_ref))
|
LL | game_loop(Arc::clone(&room_ref))
|
||||||
| | -------- `room_ref` is borrowed here
|
| -------- `room_ref` is borrowed here
|
||||||
LL | | });
|
|
||||||
| |_____^ may outlive borrowed value `room_ref`
|
|
||||||
|
|
|
|
||||||
= note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
|
= note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
|
||||||
help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
|
help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
|
||||||
|
|
|
@ -72,7 +72,7 @@ LL | | }
|
||||||
| |_____^ expected `()`, found `async` block
|
| |_____^ expected `()`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 32:6}`
|
found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 27:10}`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-closure-gate.rs:44:5
|
--> $DIR/async-closure-gate.rs:44:5
|
||||||
|
@ -89,7 +89,7 @@ LL | | }
|
||||||
| |_____^ expected `()`, found `async` block
|
| |_____^ expected `()`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 51:6}`
|
found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 44:10}`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ LL | | }
|
||||||
| |_____^ expected `()`, found `async` block
|
| |_____^ expected `()`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 32:6}`
|
found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 27:10}`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-closure-gate.rs:44:5
|
--> $DIR/async-closure-gate.rs:44:5
|
||||||
|
@ -89,7 +89,7 @@ LL | | }
|
||||||
| |_____^ expected `()`, found `async` block
|
| |_____^ expected `()`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 51:6}`
|
found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 44:10}`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||||
--> $DIR/try-on-option-in-async.rs:8:10
|
--> $DIR/try-on-option-in-async.rs:8:10
|
||||||
|
|
|
|
||||||
LL | / async {
|
LL | async {
|
||||||
LL | | let x: Option<u32> = None;
|
| ----- this function should return `Result` or `Option` to accept `?`
|
||||||
LL | | x?;
|
LL | let x: Option<u32> = None;
|
||||||
| | ^ cannot use the `?` operator in an async block that returns `{integer}`
|
LL | x?;
|
||||||
LL | | 22
|
| ^ cannot use the `?` operator in an async block that returns `{integer}`
|
||||||
LL | | }
|
|
||||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
|
||||||
|
|
|
|
||||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
error[E0382]: use of moved value: `value`
|
error[E0382]: use of moved value: `value`
|
||||||
--> $DIR/cloning-in-async-block-121547.rs:5:9
|
--> $DIR/cloning-in-async-block-121547.rs:5:9
|
||||||
|
|
|
|
||||||
LL | async fn clone_async_block(value: String) {
|
LL | async fn clone_async_block(value: String) {
|
||||||
| ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
|
| ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
|
||||||
LL | for _ in 0..10 {
|
LL | for _ in 0..10 {
|
||||||
| -------------- inside of this loop
|
| -------------- inside of this loop
|
||||||
LL | / async {
|
LL | async {
|
||||||
LL | | drop(value);
|
| ^^^^^ value moved here, in previous iteration of loop
|
||||||
| | ----- use occurs due to use in coroutine
|
LL | drop(value);
|
||||||
LL | |
|
| ----- use occurs due to use in coroutine
|
||||||
LL | | }.await
|
|
||||||
| |_________^ value moved here, in previous iteration of loop
|
|
||||||
|
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,67 +1,57 @@
|
||||||
error[E0267]: `break` inside `async` function
|
error[E0267]: `break` inside `async` function
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:8:5
|
--> $DIR/break-inside-coroutine-issue-124495.rs:8:5
|
||||||
|
|
|
|
||||||
LL | async fn async_fn() {
|
LL | async fn async_fn() {
|
||||||
| _____________________-
|
| ------------------- enclosing `async` function
|
||||||
LL | | break;
|
LL | break;
|
||||||
| | ^^^^^ cannot `break` inside `async` function
|
| ^^^^^ cannot `break` inside `async` function
|
||||||
LL | | }
|
|
||||||
| |_- enclosing `async` function
|
|
||||||
|
|
||||||
error[E0267]: `break` inside `gen` function
|
error[E0267]: `break` inside `gen` function
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:12:5
|
--> $DIR/break-inside-coroutine-issue-124495.rs:12:5
|
||||||
|
|
|
|
||||||
LL | gen fn gen_fn() {
|
LL | gen fn gen_fn() {
|
||||||
| _________________-
|
| --------------- enclosing `gen` function
|
||||||
LL | | break;
|
LL | break;
|
||||||
| | ^^^^^ cannot `break` inside `gen` function
|
| ^^^^^ cannot `break` inside `gen` function
|
||||||
LL | | }
|
|
||||||
| |_- enclosing `gen` function
|
|
||||||
|
|
||||||
error[E0267]: `break` inside `async gen` function
|
error[E0267]: `break` inside `async gen` function
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:16:5
|
--> $DIR/break-inside-coroutine-issue-124495.rs:16:5
|
||||||
|
|
|
|
||||||
LL | async gen fn async_gen_fn() {
|
LL | async gen fn async_gen_fn() {
|
||||||
| _____________________________-
|
| --------------------------- enclosing `async gen` function
|
||||||
LL | | break;
|
LL | break;
|
||||||
| | ^^^^^ cannot `break` inside `async gen` function
|
| ^^^^^ cannot `break` inside `async gen` function
|
||||||
LL | | }
|
|
||||||
| |_- enclosing `async gen` function
|
|
||||||
|
|
||||||
error[E0267]: `break` inside `async` block
|
error[E0267]: `break` inside `async` block
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:20:21
|
--> $DIR/break-inside-coroutine-issue-124495.rs:20:21
|
||||||
|
|
|
|
||||||
LL | let _ = async { break; };
|
LL | let _ = async { break; };
|
||||||
| --------^^^^^---
|
| ----- ^^^^^ cannot `break` inside `async` block
|
||||||
| | |
|
| |
|
||||||
| | cannot `break` inside `async` block
|
|
||||||
| enclosing `async` block
|
| enclosing `async` block
|
||||||
|
|
||||||
error[E0267]: `break` inside `async` closure
|
error[E0267]: `break` inside `async` closure
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:22:24
|
--> $DIR/break-inside-coroutine-issue-124495.rs:22:24
|
||||||
|
|
|
|
||||||
LL | let _ = async || { break; };
|
LL | let _ = async || { break; };
|
||||||
| -----------^^^^^---
|
| -------- ^^^^^ cannot `break` inside `async` closure
|
||||||
| | |
|
| |
|
||||||
| | cannot `break` inside `async` closure
|
|
||||||
| enclosing `async` closure
|
| enclosing `async` closure
|
||||||
|
|
||||||
error[E0267]: `break` inside `gen` block
|
error[E0267]: `break` inside `gen` block
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:24:19
|
--> $DIR/break-inside-coroutine-issue-124495.rs:24:19
|
||||||
|
|
|
|
||||||
LL | let _ = gen { break; };
|
LL | let _ = gen { break; };
|
||||||
| ------^^^^^---
|
| --- ^^^^^ cannot `break` inside `gen` block
|
||||||
| | |
|
| |
|
||||||
| | cannot `break` inside `gen` block
|
|
||||||
| enclosing `gen` block
|
| enclosing `gen` block
|
||||||
|
|
||||||
error[E0267]: `break` inside `async gen` block
|
error[E0267]: `break` inside `async gen` block
|
||||||
--> $DIR/break-inside-coroutine-issue-124495.rs:26:25
|
--> $DIR/break-inside-coroutine-issue-124495.rs:26:25
|
||||||
|
|
|
|
||||||
LL | let _ = async gen { break; };
|
LL | let _ = async gen { break; };
|
||||||
| ------------^^^^^---
|
| --------- ^^^^^ cannot `break` inside `async gen` block
|
||||||
| | |
|
| |
|
||||||
| | cannot `break` inside `async gen` block
|
|
||||||
| enclosing `async gen` block
|
| enclosing `async gen` block
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Copy` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Copy` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:17:16
|
--> $DIR/clone-impl-async.rs:17:16
|
||||||
|
|
|
|
||||||
LL | check_copy(&inner_non_clone);
|
LL | check_copy(&inner_non_clone);
|
||||||
| ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}`
|
| ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -12,11 +12,11 @@ note: required by a bound in `check_copy`
|
||||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||||
| ^^^^ required by this bound in `check_copy`
|
| ^^^^ required by this bound in `check_copy`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Clone` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Clone` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:19:17
|
--> $DIR/clone-impl-async.rs:19:17
|
||||||
|
|
|
|
||||||
LL | check_clone(&inner_non_clone);
|
LL | check_clone(&inner_non_clone);
|
||||||
| ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}`
|
| ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -26,11 +26,11 @@ note: required by a bound in `check_clone`
|
||||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||||
| ^^^^^ required by this bound in `check_clone`
|
| ^^^^^ required by this bound in `check_clone`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Copy` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Copy` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:26:16
|
--> $DIR/clone-impl-async.rs:26:16
|
||||||
|
|
|
|
||||||
LL | check_copy(&outer_non_clone);
|
LL | check_copy(&outer_non_clone);
|
||||||
| ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}`
|
| ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -40,11 +40,11 @@ note: required by a bound in `check_copy`
|
||||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||||
| ^^^^ required by this bound in `check_copy`
|
| ^^^^ required by this bound in `check_copy`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Clone` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Clone` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:28:17
|
--> $DIR/clone-impl-async.rs:28:17
|
||||||
|
|
|
|
||||||
LL | check_clone(&outer_non_clone);
|
LL | check_clone(&outer_non_clone);
|
||||||
| ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}`
|
| ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -54,11 +54,11 @@ note: required by a bound in `check_clone`
|
||||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||||
| ^^^^^ required by this bound in `check_clone`
|
| ^^^^^ required by this bound in `check_clone`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Copy` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Copy` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:32:16
|
--> $DIR/clone-impl-async.rs:32:16
|
||||||
|
|
|
|
||||||
LL | check_copy(&maybe_copy_clone);
|
LL | check_copy(&maybe_copy_clone);
|
||||||
| ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}`
|
| ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -68,11 +68,11 @@ note: required by a bound in `check_copy`
|
||||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||||
| ^^^^ required by this bound in `check_copy`
|
| ^^^^ required by this bound in `check_copy`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Clone` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Clone` is not satisfied
|
||||||
--> $DIR/clone-impl-async.rs:34:17
|
--> $DIR/clone-impl-async.rs:34:17
|
||||||
|
|
|
|
||||||
LL | check_clone(&maybe_copy_clone);
|
LL | check_clone(&maybe_copy_clone);
|
||||||
| ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}`
|
| ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:21}: Coroutine` is not satisfied
|
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}: Coroutine` is not satisfied
|
||||||
--> $DIR/gen_block_is_coro.rs:6:13
|
--> $DIR/gen_block_is_coro.rs:6:13
|
||||||
|
|
|
|
||||||
LL | fn foo() -> impl Coroutine<Yield = u32, Return = ()> {
|
LL | fn foo() -> impl Coroutine<Yield = u32, Return = ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:21}`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:21}: Coroutine` is not satisfied
|
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}: Coroutine` is not satisfied
|
||||||
--> $DIR/gen_block_is_coro.rs:10:13
|
--> $DIR/gen_block_is_coro.rs:10:13
|
||||||
|
|
|
|
||||||
LL | fn bar() -> impl Coroutine<Yield = i64, Return = ()> {
|
LL | fn bar() -> impl Coroutine<Yield = i64, Return = ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:21}`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}`
|
||||||
|
|
||||||
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:21}: Coroutine` is not satisfied
|
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}: Coroutine` is not satisfied
|
||||||
--> $DIR/gen_block_is_coro.rs:14:13
|
--> $DIR/gen_block_is_coro.rs:14:13
|
||||||
|
|
|
|
||||||
LL | fn baz() -> impl Coroutine<Yield = i32, Return = ()> {
|
LL | fn baz() -> impl Coroutine<Yield = i32, Return = ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:21}`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
|
error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future
|
||||||
--> $DIR/gen_block_is_no_future.rs:4:13
|
--> $DIR/gen_block_is_no_future.rs:4:13
|
||||||
|
|
|
|
||||||
LL | fn foo() -> impl std::future::Future {
|
LL | fn foo() -> impl std::future::Future {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future
|
||||||
|
|
|
|
||||||
= help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}`
|
= help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
error[E0373]: gen block may outlive the current function, but it borrows `x`, which is owned by the current function
|
error[E0373]: gen block may outlive the current function, but it borrows `x`, which is owned by the current function
|
||||||
--> $DIR/gen_block_move.rs:7:5
|
--> $DIR/gen_block_move.rs:7:5
|
||||||
|
|
|
|
||||||
LL | / gen {
|
LL | gen {
|
||||||
LL | | yield 42;
|
| ^^^ may outlive borrowed value `x`
|
||||||
LL | | if x == "foo" { return }
|
...
|
||||||
LL | | x.clear();
|
LL | x.clear();
|
||||||
| | - `x` is borrowed here
|
| - `x` is borrowed here
|
||||||
LL | | for x in 3..6 { yield x }
|
|
||||||
LL | | }
|
|
||||||
| |_____^ may outlive borrowed value `x`
|
|
||||||
|
|
|
|
||||||
note: gen block is returned here
|
note: gen block is returned here
|
||||||
--> $DIR/gen_block_move.rs:7:5
|
--> $DIR/gen_block_move.rs:7:5
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#[patchable_function_entry(prefix_nops = 1, entry_nops = 1)]
|
||||||
|
//~^ ERROR: the `#[patchable_function_entry]` attribute is an experimental feature
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,13 @@
|
||||||
|
error[E0658]: the `#[patchable_function_entry]` attribute is an experimental feature
|
||||||
|
--> $DIR/feature-gate-patchable-function-entry.rs:1:1
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry(prefix_nops = 1, entry_nops = 1)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #123115 <https://github.com/rust-lang/rust/issues/123115> for more information
|
||||||
|
= help: add `#![feature(patchable_function_entry)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,45 +1,27 @@
|
||||||
error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
|
error[E0277]: `Arguments<'_>` cannot be sent between threads safely
|
||||||
--> $DIR/send-sync.rs:8:10
|
--> $DIR/send-sync.rs:8:10
|
||||||
|
|
|
|
||||||
LL | send(format_args!("{:?}", c));
|
LL | send(format_args!("{:?}", c));
|
||||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
|
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `Arguments<'_>` cannot be sent between threads safely
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Send`
|
= help: the trait `Send` is not implemented for `Arguments<'_>`
|
||||||
= note: required because it appears within the type `&core::fmt::rt::Opaque`
|
|
||||||
note: required because it appears within the type `core::fmt::rt::ArgumentType<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
|
||||||
note: required because it appears within the type `core::fmt::rt::Argument<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
|
||||||
= note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
|
|
||||||
= note: required for `&[core::fmt::rt::Argument<'_>]` to implement `Send`
|
|
||||||
note: required because it appears within the type `Arguments<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
|
||||||
note: required by a bound in `send`
|
note: required by a bound in `send`
|
||||||
--> $DIR/send-sync.rs:1:12
|
--> $DIR/send-sync.rs:1:12
|
||||||
|
|
|
|
||||||
LL | fn send<T: Send>(_: T) {}
|
LL | fn send<T: Send>(_: T) {}
|
||||||
| ^^^^ required by this bound in `send`
|
| ^^^^ required by this bound in `send`
|
||||||
|
|
||||||
error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
|
error[E0277]: `Arguments<'_>` cannot be shared between threads safely
|
||||||
--> $DIR/send-sync.rs:9:10
|
--> $DIR/send-sync.rs:9:10
|
||||||
|
|
|
|
||||||
LL | sync(format_args!("{:?}", c));
|
LL | sync(format_args!("{:?}", c));
|
||||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
|
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `Arguments<'_>` cannot be shared between threads safely
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Sync`
|
= help: the trait `Sync` is not implemented for `Arguments<'_>`
|
||||||
= note: required because it appears within the type `&core::fmt::rt::Opaque`
|
|
||||||
note: required because it appears within the type `core::fmt::rt::ArgumentType<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
|
||||||
note: required because it appears within the type `core::fmt::rt::Argument<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
|
||||||
= note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
|
|
||||||
= note: required because it appears within the type `&[core::fmt::rt::Argument<'_>]`
|
|
||||||
note: required because it appears within the type `Arguments<'_>`
|
|
||||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
|
||||||
note: required by a bound in `sync`
|
note: required by a bound in `sync`
|
||||||
--> $DIR/send-sync.rs:2:12
|
--> $DIR/send-sync.rs:2:12
|
||||||
|
|
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ LL | async { () }
|
||||||
| ^^^^^^^^^^^^ expected future, found `async` block
|
| ^^^^^^^^^^^^ expected future, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected opaque type `Foo<'_>::Fut<'a>`
|
= note: expected opaque type `Foo<'_>::Fut<'a>`
|
||||||
found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18:21}`
|
found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18:14}`
|
||||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||||
--> $DIR/issue-90014-tait.rs:17:8
|
--> $DIR/issue-90014-tait.rs:17:8
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}: Copy` is not satisfied
|
error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}: Copy` is not satisfied
|
||||||
--> $DIR/issue-55872-3.rs:13:20
|
--> $DIR/issue-55872-3.rs:13:20
|
||||||
|
|
|
|
||||||
LL | fn foo<T>() -> Self::E {
|
LL | fn foo<T>() -> Self::E {
|
||||||
| ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}`
|
| ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:21}` to be a future that resolves to `u8`, but it resolves to `()`
|
error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be a future that resolves to `u8`, but it resolves to `()`
|
||||||
--> $DIR/issue-78722-2.rs:11:30
|
--> $DIR/issue-78722-2.rs:11:30
|
||||||
|
|
|
|
||||||
LL | fn concrete_use() -> F {
|
LL | fn concrete_use() -> F {
|
||||||
|
@ -16,7 +16,7 @@ LL | let f: F = async { 1 };
|
||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected opaque type `F`
|
= note: expected opaque type `F`
|
||||||
found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:31}`
|
found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:25}`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | let f: F = async { 1 };
|
||||||
= help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
|
= help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:21}` to be a future that resolves to `u8`, but it resolves to `()`
|
error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:18}` to be a future that resolves to `u8`, but it resolves to `()`
|
||||||
--> $DIR/issue-78722.rs:8:30
|
--> $DIR/issue-78722.rs:8:30
|
||||||
|
|
|
|
||||||
LL | fn concrete_use() -> F {
|
LL | fn concrete_use() -> F {
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
|
||||||
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
|
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
|
||||||
| -- --------------------------------------------- opaque type defined here
|
| -- --------------------------------------------- opaque type defined here
|
||||||
| |
|
| |
|
||||||
| hidden type `{async block@$DIR/nested-return-type4.rs:4:5: 4:31}` captures the lifetime `'s` as defined here
|
| hidden type `{async block@$DIR/nested-return-type4.rs:4:5: 4:15}` captures the lifetime `'s` as defined here
|
||||||
LL | async move { let _s = s; }
|
LL | async move { let _s = s; }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
|
|
@ -52,13 +52,13 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20
|
--> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20
|
||||||
|
|
|
|
||||||
LL | let a = async { 42 };
|
LL | let a = async { 42 };
|
||||||
| ------------ the found `async` block
|
| ----- the found `async` block
|
||||||
...
|
...
|
||||||
LL | let s = Demo { a };
|
LL | let s = Demo { a };
|
||||||
| ^ expected `Pin<Box<...>>`, found `async` block
|
| ^ expected `Pin<Box<...>>`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
|
||||||
found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}`
|
found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:18}`
|
||||||
help: you need to pin and box this expression
|
help: you need to pin and box this expression
|
||||||
|
|
|
|
||||||
LL | let s = Demo { a: Box::pin(a) };
|
LL | let s = Demo { a: Box::pin(a) };
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#![feature(patchable_function_entry)]
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[patchable_function_entry(prefix_nops = 256, entry_nops = 0)]//~error: integer value out of range
|
||||||
|
pub fn too_high_pnops() {}
|
||||||
|
|
||||||
|
#[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)]//~error: invalid literal value
|
||||||
|
pub fn non_int_nop() {}
|
||||||
|
|
||||||
|
#[patchable_function_entry]//~error: malformed `patchable_function_entry` attribute input
|
||||||
|
pub fn malformed_attribute() {}
|
||||||
|
|
||||||
|
#[patchable_function_entry(prefix_nops = 10, something = 0)]//~error: unexpected parameter name
|
||||||
|
pub fn unexpected_parameter_name() {}
|
||||||
|
|
||||||
|
#[patchable_function_entry()]//~error: must specify at least one parameter
|
||||||
|
pub fn no_parameters_given() {}
|
|
@ -0,0 +1,32 @@
|
||||||
|
error: malformed `patchable_function_entry` attribute input
|
||||||
|
--> $DIR/patchable-function-entry-attribute.rs:10:1
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
|
||||||
|
|
||||||
|
error: integer value out of range
|
||||||
|
--> $DIR/patchable-function-entry-attribute.rs:4:42
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry(prefix_nops = 256, entry_nops = 0)]
|
||||||
|
| ^^^ value must be between `0` and `255`
|
||||||
|
|
||||||
|
error: invalid literal value
|
||||||
|
--> $DIR/patchable-function-entry-attribute.rs:7:42
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)]
|
||||||
|
| ^^^^^^^^^^^^^ value must be an integer between `0` and `255`
|
||||||
|
|
||||||
|
error: unexpected parameter name
|
||||||
|
--> $DIR/patchable-function-entry-attribute.rs:13:46
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry(prefix_nops = 10, something = 0)]
|
||||||
|
| ^^^^^^^^^^^^^ expected prefix_nops or entry_nops
|
||||||
|
|
||||||
|
error: must specify at least one parameter
|
||||||
|
--> $DIR/patchable-function-entry-attribute.rs:16:1
|
||||||
|
|
|
||||||
|
LL | #[patchable_function_entry()]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
//@ compile-flags: -Z patchable-function-entry=1,2
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: incorrect value `1,2` for unstable option `patchable-function-entry` - either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops) was expected
|
||||||
|
|
|
@ -4,7 +4,7 @@ error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used
|
||||||
LL | const { || {} } => {}
|
LL | const { || {} } => {}
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns
|
error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
|
||||||
--> $DIR/non-structural-match-types.rs:12:9
|
--> $DIR/non-structural-match-types.rs:12:9
|
||||||
|
|
|
|
||||||
LL | const { async {} } => {}
|
LL | const { async {} } => {}
|
||||||
|
|
|
@ -79,7 +79,7 @@ LL | | }
|
||||||
| |_____^ expected `Pin<Box<...>>`, found `async` block
|
| |_____^ expected `Pin<Box<...>>`, found `async` block
|
||||||
|
|
|
|
||||||
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
|
||||||
found `async` block `{async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6}`
|
found `async` block `{async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 28:10}`
|
||||||
help: you need to pin and box this expression
|
help: you need to pin and box this expression
|
||||||
|
|
|
|
||||||
LL ~ Box::pin(async {
|
LL ~ Box::pin(async {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:25} as Future>::Output == i32`
|
error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:22} as Future>::Output == i32`
|
||||||
--> $DIR/async.rs:12:17
|
--> $DIR/async.rs:12:17
|
||||||
|
|
|
|
||||||
LL | needs_async(async {});
|
LL | needs_async(async {});
|
||||||
|
|
|
@ -2,9 +2,7 @@ error[E0733]: recursion in an async block requires boxing
|
||||||
--> $DIR/indirect-recursion-issue-112047.rs:22:9
|
--> $DIR/indirect-recursion-issue-112047.rs:22:9
|
||||||
|
|
|
|
||||||
LL | async move { recur(self).await; }
|
LL | async move { recur(self).await; }
|
||||||
| ^^^^^^^^^^^^^-----------------^^^
|
| ^^^^^^^^^^ ----------------- recursive call here
|
||||||
| |
|
|
||||||
| recursive call here
|
|
||||||
|
|
|
|
||||||
note: which leads to this async fn
|
note: which leads to this async fn
|
||||||
--> $DIR/indirect-recursion-issue-112047.rs:14:1
|
--> $DIR/indirect-recursion-issue-112047.rs:14:1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue