mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #127133 - matthiaskrgr:rollup-jxkp3yf, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #123237 (Various rustc_codegen_ssa cleanups) - #126960 (Improve error message in tidy) - #127002 (Implement `x perf` as a separate tool) - #127081 (Add a run-make test that LLD is not being used by default on the x64 beta/stable channel) - #127106 (Improve unsafe extern blocks diagnostics) - #127110 (Fix a error suggestion for E0121 when using placeholder _ as return types on function signature.) - #127114 (fix: prefer `(*p).clone` to `p.clone` if the `p` is a raw pointer) - #127118 (Show `used attribute`'s kind for user when find it isn't applied to a `static` variable.) - #127122 (Remove uneccessary condition in `div_ceil`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
716752ebe6
@ -3461,6 +3461,13 @@ dependencies = [
|
||||
"stable_mir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-perf-wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon"
|
||||
version = "0.5.0"
|
||||
|
@ -44,6 +44,7 @@ members = [
|
||||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/opt-dist",
|
||||
"src/tools/coverage-dump",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
@ -469,13 +469,18 @@ impl<'a> AstValidator<'a> {
|
||||
fn check_item_safety(&self, span: Span, safety: Safety) {
|
||||
match self.extern_mod_safety {
|
||||
Some(extern_safety) => {
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
|
||||
&& (extern_safety == Safety::Default || !self.features.unsafe_extern_blocks)
|
||||
{
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: self.current_extern_span().shrink_to_lo(),
|
||||
});
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) {
|
||||
if extern_safety == Safety::Default {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: Some(self.current_extern_span().shrink_to_lo()),
|
||||
});
|
||||
} else if !self.features.unsafe_extern_blocks {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@ -1098,7 +1103,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
} else if let &Safety::Unsafe(span) = safety {
|
||||
this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
let mut diag = this
|
||||
.dcx()
|
||||
.create_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
&mut diag,
|
||||
self.session,
|
||||
sym::unsafe_extern_blocks,
|
||||
);
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
if abi.is_none() {
|
||||
|
@ -222,7 +222,7 @@ pub struct InvalidSafetyOnExtern {
|
||||
#[primary_span]
|
||||
pub item_span: Span,
|
||||
#[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")]
|
||||
pub block: Span,
|
||||
pub block: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -1288,7 +1288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let suggestion =
|
||||
let mut suggestion =
|
||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
format!(": {symbol}.clone()")
|
||||
} else {
|
||||
@ -1296,6 +1296,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
};
|
||||
let mut sugg = Vec::with_capacity(2);
|
||||
let mut inner_expr = expr;
|
||||
let mut is_raw_ptr = false;
|
||||
let typeck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
// Remove uses of `&` and `*` when suggesting `.clone()`.
|
||||
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
|
||||
&inner_expr.kind
|
||||
@ -1306,14 +1308,32 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
inner_expr = inner;
|
||||
if let Some(inner_type) = typeck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if inner_expr.span.lo() != expr.span.lo() {
|
||||
// Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863)
|
||||
if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr {
|
||||
// Remove "(*" or "(&"
|
||||
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
|
||||
}
|
||||
// Check whether `expr` is surrounded by parentheses or not.
|
||||
let span = if inner_expr.span.hi() != expr.span.hi() {
|
||||
// Account for `(*x)` to suggest `x.clone()`.
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
if is_raw_ptr {
|
||||
expr.span.shrink_to_hi()
|
||||
} else {
|
||||
// Remove the close parenthesis ")"
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
}
|
||||
} else {
|
||||
if is_raw_ptr {
|
||||
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||
suggestion = ").clone()".to_string();
|
||||
}
|
||||
expr.span.shrink_to_hi()
|
||||
};
|
||||
sugg.push((span, suggestion));
|
||||
|
@ -639,12 +639,27 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
||||
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
||||
Ok(snippet) if snippet.starts_with('*') => {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let sp = span.with_lo(span.lo() + BytePos(1));
|
||||
let inner = self.find_expr(sp);
|
||||
let mut is_raw_ptr = false;
|
||||
if let Some(inner) = inner {
|
||||
let typck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
if let Some(inner_type) = typck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the `inner` is a raw pointer, do not suggest removing the "*", see #126863
|
||||
// FIXME: need to check whether the assigned object can be a raw pointer, see `tests/ui/borrowck/issue-20801.rs`.
|
||||
if !is_raw_ptr {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
err.span_suggestion_verbose(
|
||||
|
@ -28,6 +28,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
global
|
||||
// TODO(antoyo): set linkage.
|
||||
}
|
||||
|
||||
pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
|
||||
@ -239,19 +252,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
const_alloc_to_gcc(self, alloc)
|
||||
}
|
||||
|
||||
fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
self.context
|
||||
.new_array_access(None, base_addr, self.const_usize(offset.bytes()))
|
||||
|
@ -27,7 +27,6 @@ use crate::callee::get_fn;
|
||||
use crate::common::SignType;
|
||||
|
||||
pub struct CodegenCx<'gcc, 'tcx> {
|
||||
pub check_overflow: bool,
|
||||
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
pub context: &'gcc Context<'gcc>,
|
||||
|
||||
@ -134,8 +133,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
supports_128bit_integers: bool,
|
||||
) -> Self {
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
@ -271,7 +268,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
let mut cx = Self {
|
||||
check_overflow,
|
||||
codegen_unit,
|
||||
context,
|
||||
current_func: RefCell::new(None),
|
||||
@ -511,10 +507,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
&self.tcx.sess
|
||||
}
|
||||
|
||||
fn check_overflow(&self) -> bool {
|
||||
self.check_overflow
|
||||
}
|
||||
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
|
||||
self.codegen_unit
|
||||
}
|
||||
|
@ -89,13 +89,34 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
ty::FloatTy::F128 => self.type_f128(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_i1(&self) -> Type<'gcc> {
|
||||
pub fn type_i1(&self) -> Type<'gcc> {
|
||||
self.bool_type
|
||||
}
|
||||
|
||||
pub fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
|
||||
let types = fields.to_vec();
|
||||
if let Some(typ) = self.struct_types.borrow().get(fields) {
|
||||
return *typ;
|
||||
}
|
||||
let fields: Vec<_> = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, field)| {
|
||||
self.context.new_field(None, *field, format!("field{}_TODO", index))
|
||||
})
|
||||
.collect();
|
||||
let typ = self.context.new_struct_type(None, "struct", &fields).as_type();
|
||||
if packed {
|
||||
#[cfg(feature = "master")]
|
||||
typ.set_packed();
|
||||
}
|
||||
self.struct_types.borrow_mut().insert(types, typ);
|
||||
typ
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_i8(&self) -> Type<'gcc> {
|
||||
self.i8_type
|
||||
}
|
||||
@ -131,7 +152,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_f64(&self) -> Type<'gcc> {
|
||||
self.double_type
|
||||
}
|
||||
|
||||
|
||||
fn type_f128(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
}
|
||||
@ -140,27 +161,6 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
self.context.new_function_pointer_type(None, return_type, params, false)
|
||||
}
|
||||
|
||||
fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
|
||||
let types = fields.to_vec();
|
||||
if let Some(typ) = self.struct_types.borrow().get(fields) {
|
||||
return *typ;
|
||||
}
|
||||
let fields: Vec<_> = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, field)| {
|
||||
self.context.new_field(None, *field, format!("field{}_TODO", index))
|
||||
})
|
||||
.collect();
|
||||
let typ = self.context.new_struct_type(None, "struct", &fields).as_type();
|
||||
if packed {
|
||||
#[cfg(feature = "master")]
|
||||
typ.set_packed();
|
||||
}
|
||||
self.struct_types.borrow_mut().insert(types, typ);
|
||||
typ
|
||||
}
|
||||
|
||||
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||
if self.is_int_type_or_bool(typ) {
|
||||
TypeKind::Integer
|
||||
|
@ -329,10 +329,6 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
const_alloc_to_llvm(self, alloc, /*static*/ false)
|
||||
}
|
||||
|
||||
fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||
self.const_bitcast(val, ty)
|
||||
}
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
unsafe {
|
||||
llvm::LLVMConstInBoundsGEP2(
|
||||
|
@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::coverageinfo;
|
||||
use crate::debuginfo;
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm;
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
@ -43,7 +44,6 @@ use std::str;
|
||||
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
|
||||
pub struct CodegenCx<'ll, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
pub check_overflow: bool,
|
||||
pub use_dll_storage_attrs: bool,
|
||||
pub tls_model: llvm::ThreadLocalMode,
|
||||
|
||||
@ -441,8 +441,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
// start) and then strongly recommending static linkage on Windows!
|
||||
let use_dll_storage_attrs = tcx.sess.target.is_like_windows;
|
||||
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let tls_model = to_llvm_tls_model(tcx.sess.tls_model());
|
||||
|
||||
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
|
||||
@ -466,7 +464,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
|
||||
CodegenCx {
|
||||
tcx,
|
||||
check_overflow,
|
||||
use_dll_storage_attrs,
|
||||
tls_model,
|
||||
llmod,
|
||||
@ -522,6 +519,15 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
&self.vtables
|
||||
}
|
||||
|
||||
fn apply_vcall_visibility_metadata(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);
|
||||
}
|
||||
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
|
||||
get_fn(self, instance)
|
||||
}
|
||||
@ -596,10 +602,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
self.tcx.sess
|
||||
}
|
||||
|
||||
fn check_overflow(&self) -> bool {
|
||||
self.check_overflow
|
||||
}
|
||||
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
|
||||
self.codegen_unit
|
||||
}
|
||||
|
@ -1449,12 +1449,18 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
|
||||
.di_node
|
||||
}
|
||||
|
||||
fn vcall_visibility_metadata<'ll, 'tcx>(
|
||||
pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
// FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
|
||||
// LLVM at the moment.
|
||||
if !cx.sess().opts.unstable_opts.virtual_function_elimination || cx.sess().lto() != Lto::Fat {
|
||||
return;
|
||||
}
|
||||
|
||||
enum VCallVisibility {
|
||||
Public = 0,
|
||||
LinkageUnit = 1,
|
||||
@ -1531,12 +1537,6 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
// FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
|
||||
// LLVM at the moment.
|
||||
if cx.sess().opts.unstable_opts.virtual_function_elimination && cx.sess().lto() == Lto::Fat {
|
||||
vcall_visibility_metadata(cx, ty, poly_trait_ref, vtable);
|
||||
}
|
||||
|
||||
if cx.dbg_cx.is_none() {
|
||||
return;
|
||||
}
|
||||
|
@ -274,10 +274,11 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
||||
}
|
||||
|
||||
fn print(&self, req: &PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
||||
use std::fmt::Write;
|
||||
match req.kind {
|
||||
PrintKind::RelocationModels => {
|
||||
writeln!(out, "Available relocation models:");
|
||||
writeln!(out, "Available relocation models:").unwrap();
|
||||
for name in &[
|
||||
"static",
|
||||
"pic",
|
||||
@ -288,25 +289,25 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||
"ropi-rwpi",
|
||||
"default",
|
||||
] {
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::CodeModels => {
|
||||
writeln!(out, "Available code models:");
|
||||
writeln!(out, "Available code models:").unwrap();
|
||||
for name in &["tiny", "small", "kernel", "medium", "large"] {
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::TlsModels => {
|
||||
writeln!(out, "Available TLS models:");
|
||||
writeln!(out, "Available TLS models:").unwrap();
|
||||
for name in
|
||||
&["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"]
|
||||
{
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::StackProtectorStrategies => {
|
||||
writeln!(
|
||||
@ -332,7 +333,8 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||
none
|
||||
Do not generate stack canaries.
|
||||
"#
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
_other => llvm_util::print(req, out, sess),
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ use crate::errors::{
|
||||
use crate::llvm;
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||
use rustc_codegen_ssa::traits::PrintBackendInfo;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_fs_util::path_to_c_string;
|
||||
@ -18,6 +17,7 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
|
||||
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
use std::fmt::Write;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
@ -372,7 +372,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
|
||||
ret
|
||||
}
|
||||
|
||||
fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &llvm::TargetMachine) {
|
||||
fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMachine) {
|
||||
let mut llvm_target_features = llvm_target_features(tm);
|
||||
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
|
||||
let mut rustc_target_features = sess
|
||||
@ -412,24 +412,26 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
writeln!(out, "Features supported by rustc for this target:");
|
||||
writeln!(out, "Features supported by rustc for this target:").unwrap();
|
||||
for (feature, desc) in &rustc_target_features {
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.");
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap();
|
||||
}
|
||||
writeln!(out, "\nCode-generation features supported by LLVM for this target:");
|
||||
writeln!(out, "\nCode-generation features supported by LLVM for this target:").unwrap();
|
||||
for (feature, desc) in &llvm_target_features {
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.");
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap();
|
||||
}
|
||||
if llvm_target_features.is_empty() {
|
||||
writeln!(out, " Target features listing is not supported by this LLVM version.");
|
||||
writeln!(out, " Target features listing is not supported by this LLVM version.")
|
||||
.unwrap();
|
||||
}
|
||||
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.");
|
||||
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n");
|
||||
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],");
|
||||
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n");
|
||||
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.").unwrap();
|
||||
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n")
|
||||
.unwrap();
|
||||
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],").unwrap();
|
||||
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||
require_inited();
|
||||
let tm = create_informational_target_machine(sess);
|
||||
match req.kind {
|
||||
@ -440,9 +442,9 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess
|
||||
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
||||
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
||||
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
|
||||
let out = &mut *(out as *mut &mut dyn PrintBackendInfo);
|
||||
let out = &mut *(out as *mut &mut String);
|
||||
let bytes = slice::from_raw_parts(string as *const u8, len);
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes));
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap();
|
||||
}
|
||||
unsafe {
|
||||
llvm::LLVMRustPrintTargetCPUs(
|
||||
|
@ -127,13 +127,24 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn type_i1(&self) -> &'ll Type {
|
||||
pub(crate) fn type_i1(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt1TypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(
|
||||
self.llcx,
|
||||
els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
packed as Bool,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn type_i8(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt8TypeInContext(self.llcx) }
|
||||
}
|
||||
@ -178,17 +189,6 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
|
||||
}
|
||||
|
||||
fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(
|
||||
self.llcx,
|
||||
els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
packed as Bool,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn type_kind(&self, ty: &'ll Type) -> TypeKind {
|
||||
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
|
||||
}
|
||||
|
@ -133,6 +133,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
||||
let align = cx.data_layout().pointer_align.abi;
|
||||
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
|
||||
|
||||
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
|
||||
cx.create_vtable_debuginfo(ty, trait_ref, vtable);
|
||||
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
|
||||
vtable
|
||||
|
@ -658,7 +658,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
// with #[rustc_inherit_overflow_checks] and inlined from
|
||||
// another crate (mostly core::num generic/#[inline] fns),
|
||||
// while the current crate doesn't use overflow checks.
|
||||
if !bx.cx().check_overflow() && msg.is_optional_overflow_check() {
|
||||
if !bx.sess().overflow_checks() && msg.is_optional_overflow_check() {
|
||||
const_cond = Some(expected);
|
||||
}
|
||||
|
||||
@ -751,7 +751,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
&mut self,
|
||||
helper: &TerminatorCodegenHelper<'tcx>,
|
||||
bx: &mut Bx,
|
||||
intrinsic: Option<ty::IntrinsicDef>,
|
||||
intrinsic: ty::IntrinsicDef,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
source_info: mir::SourceInfo,
|
||||
target: Option<mir::BasicBlock>,
|
||||
@ -761,8 +761,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
// Emit a panic or a no-op for `assert_*` intrinsics.
|
||||
// These are intrinsics that compile to panics so that we can get a message
|
||||
// which mentions the offending type, even from a const context.
|
||||
let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
|
||||
if let Some(requirement) = panic_intrinsic {
|
||||
if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
|
||||
let ty = instance.unwrap().args.type_at(0);
|
||||
|
||||
let do_panic = !bx
|
||||
@ -869,12 +868,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let sig = callee.layout.ty.fn_sig(bx.tcx());
|
||||
let abi = sig.abi();
|
||||
|
||||
// Handle intrinsics old codegen wants Expr's for, ourselves.
|
||||
let intrinsic = match def {
|
||||
Some(ty::InstanceKind::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
||||
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
|
||||
let op_ty = op_arg.node.ty(self.mir, bx.tcx());
|
||||
@ -886,50 +879,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
None => bx.fn_abi_of_fn_ptr(sig, extra_args),
|
||||
};
|
||||
|
||||
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
||||
&helper,
|
||||
bx,
|
||||
intrinsic,
|
||||
instance,
|
||||
source_info,
|
||||
target,
|
||||
unwind,
|
||||
mergeable_succ,
|
||||
) {
|
||||
return merging_succ;
|
||||
}
|
||||
|
||||
// The arguments we'll be passing. Plus one to account for outptr, if used.
|
||||
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
|
||||
|
||||
if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
|
||||
return if let Some(target) = target {
|
||||
let location =
|
||||
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
let ret_dest = self.make_return_dest(
|
||||
let instance = match def {
|
||||
Some(ty::InstanceKind::Intrinsic(def_id)) => {
|
||||
let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
|
||||
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
||||
&helper,
|
||||
bx,
|
||||
destination,
|
||||
&fn_abi.ret,
|
||||
&mut llargs,
|
||||
intrinsic,
|
||||
Some(target),
|
||||
);
|
||||
assert_eq!(llargs, []);
|
||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||
location.val.store(bx, tmp);
|
||||
instance,
|
||||
source_info,
|
||||
target,
|
||||
unwind,
|
||||
mergeable_succ,
|
||||
) {
|
||||
return merging_succ;
|
||||
}
|
||||
self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
|
||||
helper.funclet_br(self, bx, target, mergeable_succ)
|
||||
} else {
|
||||
MergingSucc::False
|
||||
};
|
||||
}
|
||||
|
||||
let instance = match intrinsic {
|
||||
None => instance,
|
||||
Some(intrinsic) => {
|
||||
let mut llargs = Vec::with_capacity(1);
|
||||
let ret_dest = self.make_return_dest(
|
||||
bx,
|
||||
@ -971,6 +939,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) {
|
||||
let location = self
|
||||
.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
||||
|
||||
assert_eq!(llargs, []);
|
||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||
location.val.store(bx, tmp);
|
||||
}
|
||||
self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
|
||||
return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
|
||||
}
|
||||
|
||||
let instance = *instance.as_ref().unwrap();
|
||||
match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
|
||||
Ok(()) => {
|
||||
@ -997,6 +977,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => instance,
|
||||
};
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
|
@ -22,8 +22,6 @@ use rustc_session::{
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub trait BackendTypes {
|
||||
type Value: CodegenObject;
|
||||
type Function: CodegenObject;
|
||||
@ -62,7 +60,7 @@ pub trait CodegenBackend {
|
||||
fn locale_resource(&self) -> &'static str;
|
||||
|
||||
fn init(&self, _sess: &Session) {}
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut dyn PrintBackendInfo, _sess: &Session) {}
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
|
||||
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
|
||||
vec![]
|
||||
}
|
||||
@ -150,19 +148,3 @@ pub trait ExtraBackendMethods:
|
||||
std::thread::Builder::new().name(name).spawn(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PrintBackendInfo {
|
||||
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>);
|
||||
}
|
||||
|
||||
impl PrintBackendInfo for String {
|
||||
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||
fmt::Write::write_fmt(self, args).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn PrintBackendInfo + '_ {
|
||||
pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||
self.infallible_write_fmt(args);
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,5 @@ pub trait ConstMethods<'tcx>: BackendTypes {
|
||||
|
||||
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
|
||||
|
||||
fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
|
||||
fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value;
|
||||
}
|
||||
|
@ -9,7 +9,13 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
||||
fn vtables(
|
||||
&self,
|
||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
|
||||
fn check_overflow(&self) -> bool;
|
||||
fn apply_vcall_visibility_metadata(
|
||||
&self,
|
||||
_ty: Ty<'tcx>,
|
||||
_poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
_vtable: Self::Value,
|
||||
) {
|
||||
}
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
|
||||
fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value;
|
||||
fn eh_personality(&self) -> Self::Value;
|
||||
|
@ -30,9 +30,7 @@ mod write;
|
||||
|
||||
pub use self::abi::AbiBuilderMethods;
|
||||
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
|
||||
pub use self::backend::{
|
||||
Backend, BackendTypes, CodegenBackend, ExtraBackendMethods, PrintBackendInfo,
|
||||
};
|
||||
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||
pub use self::consts::ConstMethods;
|
||||
pub use self::coverageinfo::CoverageInfoBuilderMethods;
|
||||
|
@ -12,7 +12,6 @@ use rustc_target::abi::{AddressSpace, Float, Integer};
|
||||
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
||||
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
||||
pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
||||
fn type_i1(&self) -> Self::Type;
|
||||
fn type_i8(&self) -> Self::Type;
|
||||
fn type_i16(&self) -> Self::Type;
|
||||
fn type_i32(&self) -> Self::Type;
|
||||
@ -27,7 +26,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
||||
|
||||
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
|
||||
fn type_kind(&self, ty: Self::Type) -> TypeKind;
|
||||
fn type_ptr(&self) -> Self::Type;
|
||||
fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type;
|
||||
@ -115,8 +113,8 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
|
||||
/// The backend type used for a rust type when it's in an SSA register.
|
||||
///
|
||||
/// For nearly all types this is the same as the [`Self::backend_type`], however
|
||||
/// `bool` (and other `0`-or-`1` values) are kept as [`BaseTypeMethods::type_i1`]
|
||||
/// in registers but as [`BaseTypeMethods::type_i8`] in memory.
|
||||
/// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as
|
||||
/// [`BaseTypeMethods::type_i8`] in memory.
|
||||
///
|
||||
/// Converting values between the two different backend types is done using
|
||||
/// [`from_immediate`](super::BuilderMethods::from_immediate) and
|
||||
|
@ -1459,8 +1459,25 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||
Some(ty) => {
|
||||
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||
// This is a heuristic approach. If the scope has region paramters,
|
||||
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
|
||||
// otherwise to `ReStatic`.
|
||||
let has_region_params = generics.params.iter().any(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
|
||||
ty::ReErased => tcx.lifetimes.re_static,
|
||||
ty::ReErased => {
|
||||
if has_region_params {
|
||||
ty::Region::new_error_with_message(
|
||||
tcx,
|
||||
DUMMY_SP,
|
||||
"erased region is not allowed here in return type",
|
||||
)
|
||||
} else {
|
||||
tcx.lifetimes.re_static
|
||||
}
|
||||
}
|
||||
_ => r,
|
||||
});
|
||||
|
||||
|
@ -782,6 +782,7 @@ passes_used_compiler_linker =
|
||||
|
||||
passes_used_static =
|
||||
attribute must be applied to a `static` variable
|
||||
.label = but this is a {$target}
|
||||
|
||||
passes_useless_assignment =
|
||||
useless assignment of {$is_field_assign ->
|
||||
|
@ -274,7 +274,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
|
||||
self.check_repr(attrs, span, target, item, hir_id);
|
||||
self.check_used(attrs, target);
|
||||
self.check_used(attrs, target, span);
|
||||
}
|
||||
|
||||
fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
|
||||
@ -1930,12 +1930,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_used(&self, attrs: &[Attribute], target: Target) {
|
||||
fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) {
|
||||
let mut used_linker_span = None;
|
||||
let mut used_compiler_span = None;
|
||||
for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) {
|
||||
if target != Target::Static {
|
||||
self.dcx().emit_err(errors::UsedStatic { span: attr.span });
|
||||
self.dcx().emit_err(errors::UsedStatic {
|
||||
attr_span: attr.span,
|
||||
span: target_span,
|
||||
target: target.name(),
|
||||
});
|
||||
}
|
||||
let inner = attr.meta_item_list();
|
||||
match inner.as_deref() {
|
||||
|
@ -551,7 +551,10 @@ pub struct ReprConflictingLint;
|
||||
#[diag(passes_used_static)]
|
||||
pub struct UsedStatic {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub target: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -2726,7 +2726,7 @@ macro_rules! uint_impl {
|
||||
pub const fn div_ceil(self, rhs: Self) -> Self {
|
||||
let d = self / rhs;
|
||||
let r = self % rhs;
|
||||
if r > 0 && rhs > 0 {
|
||||
if r > 0 {
|
||||
d + 1
|
||||
} else {
|
||||
d
|
||||
|
@ -1,7 +1,5 @@
|
||||
use std::process::Command;
|
||||
|
||||
use crate::core::build_steps::compile::{Std, Sysroot};
|
||||
use crate::core::build_steps::tool::RustcPerf;
|
||||
use crate::core::build_steps::tool::{RustcPerf, Tool};
|
||||
use crate::core::builder::Builder;
|
||||
use crate::core::config::DebuginfoLevel;
|
||||
|
||||
@ -22,24 +20,16 @@ Consider setting `rust.debuginfo-level = 1` in `config.toml`."#);
|
||||
let sysroot = builder.ensure(Sysroot::new(compiler));
|
||||
let rustc = sysroot.join("bin/rustc");
|
||||
|
||||
let results_dir = builder.build.tempdir().join("rustc-perf");
|
||||
let rustc_perf_dir = builder.build.tempdir().join("rustc-perf");
|
||||
let profile_results_dir = rustc_perf_dir.join("results");
|
||||
|
||||
let mut cmd = Command::new(collector);
|
||||
let cmd = cmd
|
||||
.arg("profile_local")
|
||||
.arg("eprintln")
|
||||
.arg("--out-dir")
|
||||
.arg(&results_dir)
|
||||
.arg("--include")
|
||||
.arg("helloworld")
|
||||
.arg(&rustc);
|
||||
// We need to take args passed after `--` and pass them to `rustc-perf-wrapper`
|
||||
let args = std::env::args().skip_while(|a| a != "--").skip(1);
|
||||
|
||||
builder.info(&format!("Running `rustc-perf` using `{}`", rustc.display()));
|
||||
|
||||
// We need to set the working directory to `src/tools/perf`, so that it can find the directory
|
||||
// with compile-time benchmarks.
|
||||
let cmd = cmd.current_dir(builder.src.join("src/tools/rustc-perf"));
|
||||
builder.build.run(cmd);
|
||||
|
||||
builder.info(&format!("You can find the results at `{}`", results_dir.display()));
|
||||
let mut cmd = builder.tool_cmd(Tool::RustcPerfWrapper);
|
||||
cmd.env("RUSTC_REAL", rustc)
|
||||
.env("PERF_COLLECTOR", collector)
|
||||
.env("PERF_RESULT_DIR", profile_results_dir)
|
||||
.args(args);
|
||||
builder.run(&mut cmd);
|
||||
}
|
||||
|
@ -337,6 +337,7 @@ bootstrap_tool!(
|
||||
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
|
||||
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
|
||||
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
|
||||
RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper";
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
|
@ -470,7 +470,9 @@ Arguments:
|
||||
versioned_dirs: bool,
|
||||
},
|
||||
/// Perform profiling and benchmarking of the compiler using the
|
||||
/// `rustc-perf` benchmark suite.
|
||||
/// `rustc-perf-wrapper` tool.
|
||||
///
|
||||
/// You need to pass arguments after `--`, e.g.`x perf -- cachegrind`.
|
||||
Perf {},
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained
|
||||
complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development'
|
||||
complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files'
|
||||
complete -c x.py -n "__fish_use_subcommand" -f -a "vendor" -d 'Vendor dependencies'
|
||||
complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite'
|
||||
complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool'
|
||||
complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F
|
||||
complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
|
||||
complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f
|
||||
|
@ -75,7 +75,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
|
||||
[CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development')
|
||||
[CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files')
|
||||
[CompletionResult]::new('vendor', 'vendor', [CompletionResultType]::ParameterValue, 'Vendor dependencies')
|
||||
[CompletionResult]::new('perf', 'perf', [CompletionResultType]::ParameterValue, 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite')
|
||||
[CompletionResult]::new('perf', 'perf', [CompletionResultType]::ParameterValue, 'Perform profiling and benchmarking of the compiler using the `rustc-perf-wrapper` tool')
|
||||
break
|
||||
}
|
||||
'x.py;build' {
|
||||
|
@ -856,7 +856,7 @@ _x.py_commands() {
|
||||
'setup:Set up the environment for development' \
|
||||
'suggest:Suggest a subset of tests to run, based on modified files' \
|
||||
'vendor:Vendor dependencies' \
|
||||
'perf:Perform profiling and benchmarking of the compiler using the \`rustc-perf\` benchmark suite' \
|
||||
'perf:Perform profiling and benchmarking of the compiler using the \`rustc-perf-wrapper\` tool' \
|
||||
)
|
||||
_describe -t commands 'x.py commands' commands "$@"
|
||||
}
|
||||
|
7
src/tools/rustc-perf-wrapper/Cargo.toml
Normal file
7
src/tools/rustc-perf-wrapper/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "rustc-perf-wrapper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.7", features = ["derive", "env"] }
|
3
src/tools/rustc-perf-wrapper/README.md
Normal file
3
src/tools/rustc-perf-wrapper/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# rustc-perf wrapper
|
||||
Utility tool for invoking [`rustc-perf`](https://github.com/rust-lang/rustc-perf) for benchmarking/profiling
|
||||
a stage1/2 compiler built by bootstrap using `x perf -- <command>`.
|
45
src/tools/rustc-perf-wrapper/src/config.rs
Normal file
45
src/tools/rustc-perf-wrapper/src/config.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
|
||||
#[value(rename_all = "PascalCase")]
|
||||
pub enum Profile {
|
||||
Check,
|
||||
Debug,
|
||||
Doc,
|
||||
Opt,
|
||||
Clippy,
|
||||
}
|
||||
|
||||
impl Display for Profile {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
Profile::Check => "Check",
|
||||
Profile::Debug => "Debug",
|
||||
Profile::Doc => "Doc",
|
||||
Profile::Opt => "Opt",
|
||||
Profile::Clippy => "Clippy",
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
|
||||
#[value(rename_all = "PascalCase")]
|
||||
pub enum Scenario {
|
||||
Full,
|
||||
IncrFull,
|
||||
IncrUnchanged,
|
||||
IncrPatched,
|
||||
}
|
||||
|
||||
impl Display for Scenario {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
Scenario::Full => "Full",
|
||||
Scenario::IncrFull => "IncrFull",
|
||||
Scenario::IncrUnchanged => "IncrUnchanged",
|
||||
Scenario::IncrPatched => "IncrPatched",
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
130
src/tools/rustc-perf-wrapper/src/main.rs
Normal file
130
src/tools/rustc-perf-wrapper/src/main.rs
Normal file
@ -0,0 +1,130 @@
|
||||
use crate::config::{Profile, Scenario};
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
mod config;
|
||||
|
||||
/// Performs profiling or benchmarking with [`rustc-perf`](https://github.com/rust-lang/rustc-perf)
|
||||
/// using a locally built compiler.
|
||||
#[derive(Debug, clap::Parser)]
|
||||
// Hide arguments from BuildContext in the default usage string.
|
||||
// Clap does not seem to have a way of disabling the usage of these arguments.
|
||||
#[clap(override_usage = "rustc-perf-wrapper [OPTIONS] <COMMAND>")]
|
||||
pub struct Args {
|
||||
#[clap(subcommand)]
|
||||
cmd: PerfCommand,
|
||||
|
||||
#[clap(flatten)]
|
||||
opts: SharedOpts,
|
||||
|
||||
#[clap(flatten)]
|
||||
ctx: BuildContext,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
enum PerfCommand {
|
||||
/// Run `profile_local eprintln`.
|
||||
/// This executes the compiler on the given benchmarks and stores its stderr output.
|
||||
Eprintln,
|
||||
/// Run `profile_local samply`
|
||||
/// This executes the compiler on the given benchmarks and profiles it with `samply`.
|
||||
/// You need to install `samply`, e.g. using `cargo install samply`.
|
||||
Samply,
|
||||
/// Run `profile_local cachegrind`.
|
||||
/// This executes the compiler on the given benchmarks under `Cachegrind`.
|
||||
Cachegrind,
|
||||
}
|
||||
|
||||
impl PerfCommand {
|
||||
fn is_profiling(&self) -> bool {
|
||||
match self {
|
||||
PerfCommand::Eprintln | PerfCommand::Samply | PerfCommand::Cachegrind => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct SharedOpts {
|
||||
/// Select the benchmarks that you want to run (separated by commas).
|
||||
/// If unspecified, all benchmarks will be executed.
|
||||
#[clap(long, global = true, value_delimiter = ',')]
|
||||
include: Vec<String>,
|
||||
/// Select the scenarios that should be benchmarked.
|
||||
#[clap(
|
||||
long,
|
||||
global = true,
|
||||
value_delimiter = ',',
|
||||
default_value = "Full,IncrFull,IncrUnchanged,IncrPatched"
|
||||
)]
|
||||
scenarios: Vec<Scenario>,
|
||||
/// Select the profiles that should be benchmarked.
|
||||
#[clap(long, global = true, value_delimiter = ',', default_value = "Check,Debug,Opt")]
|
||||
profiles: Vec<Profile>,
|
||||
}
|
||||
|
||||
/// These arguments are mostly designed to be passed from bootstrap, not by users
|
||||
/// directly.
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct BuildContext {
|
||||
/// Compiler binary that will be benchmarked/profiled.
|
||||
#[clap(long, hide = true, env = "RUSTC_REAL")]
|
||||
compiler: PathBuf,
|
||||
/// rustc-perf collector binary that will be used for running benchmarks/profilers.
|
||||
#[clap(long, hide = true, env = "PERF_COLLECTOR")]
|
||||
collector: PathBuf,
|
||||
/// Directory where to store results.
|
||||
#[clap(long, hide = true, env = "PERF_RESULT_DIR")]
|
||||
results_dir: PathBuf,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
run(args);
|
||||
}
|
||||
|
||||
fn run(args: Args) {
|
||||
let mut cmd = Command::new(args.ctx.collector);
|
||||
match &args.cmd {
|
||||
PerfCommand::Eprintln => {
|
||||
cmd.arg("profile_local").arg("eprintln");
|
||||
}
|
||||
PerfCommand::Samply => {
|
||||
cmd.arg("profile_local").arg("samply");
|
||||
}
|
||||
PerfCommand::Cachegrind => {
|
||||
cmd.arg("profile_local").arg("cachegrind");
|
||||
}
|
||||
}
|
||||
if args.cmd.is_profiling() {
|
||||
cmd.arg("--out-dir").arg(&args.ctx.results_dir);
|
||||
}
|
||||
|
||||
if !args.opts.include.is_empty() {
|
||||
cmd.arg("--include").arg(args.opts.include.join(","));
|
||||
}
|
||||
if !args.opts.profiles.is_empty() {
|
||||
cmd.arg("--profiles")
|
||||
.arg(args.opts.profiles.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
|
||||
}
|
||||
if !args.opts.scenarios.is_empty() {
|
||||
cmd.arg("--scenarios")
|
||||
.arg(args.opts.scenarios.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
|
||||
}
|
||||
cmd.arg(&args.ctx.compiler);
|
||||
|
||||
println!("Running `rustc-perf` using `{}`", args.ctx.compiler.display());
|
||||
|
||||
const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
||||
|
||||
let rustc_perf_dir = PathBuf::from(MANIFEST_DIR).join("../rustc-perf");
|
||||
|
||||
// We need to set the working directory to `src/tools/perf`, so that it can find the directory
|
||||
// with compile-time benchmarks.
|
||||
let cmd = cmd.current_dir(rustc_perf_dir);
|
||||
cmd.status().expect("error while running rustc-perf collector");
|
||||
|
||||
if args.cmd.is_profiling() {
|
||||
println!("You can find the results at `{}`", args.ctx.results_dir.display());
|
||||
}
|
||||
}
|
@ -364,11 +364,10 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> {
|
||||
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
let err = if stderr.contains("No module named virtualenv") {
|
||||
Error::Generic(
|
||||
Error::Generic(format!(
|
||||
"virtualenv not found: you may need to install it \
|
||||
(`python3 -m pip install venv`)"
|
||||
.to_owned(),
|
||||
)
|
||||
(`{sys_py} -m pip install virtualenv`)"
|
||||
))
|
||||
} else {
|
||||
Error::Generic(format!(
|
||||
"failed to create venv at '{}' using {sys_py}: {stderr}",
|
||||
|
1
tests/run-make/rust-lld-by-default-beta-stable/main.rs
Normal file
1
tests/run-make/rust-lld-by-default-beta-stable/main.rs
Normal file
@ -0,0 +1 @@
|
||||
fn main() {}
|
29
tests/run-make/rust-lld-by-default-beta-stable/rmake.rs
Normal file
29
tests/run-make/rust-lld-by-default-beta-stable/rmake.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Ensure that rust-lld is *not* used as the default linker on `x86_64-unknown-linux-gnu` on stable
|
||||
// or beta.
|
||||
|
||||
//@ ignore-nightly
|
||||
//@ only-x86_64-unknown-linux-gnu
|
||||
|
||||
use run_make_support::regex::Regex;
|
||||
use run_make_support::rustc;
|
||||
use std::process::Output;
|
||||
|
||||
fn main() {
|
||||
// A regular compilation should not use rust-lld by default. We'll check that by asking the
|
||||
// linker to display its version number with a link-arg.
|
||||
let output = rustc()
|
||||
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
|
||||
.link_arg("-Wl,-v")
|
||||
.input("main.rs")
|
||||
.run();
|
||||
assert!(
|
||||
!find_lld_version_in_logs(output.stderr_utf8()),
|
||||
"the LLD version string should not be present in the output logs:\n{}",
|
||||
output.stderr_utf8()
|
||||
);
|
||||
}
|
||||
|
||||
fn find_lld_version_in_logs(stderr: String) -> bool {
|
||||
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
|
||||
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu`, and that it can
|
||||
// also be turned off with a CLI flag.
|
||||
// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu` on the nightly
|
||||
// channel, and that it can also be turned off with a CLI flag.
|
||||
|
||||
//@ needs-rust-lld
|
||||
//@ ignore-beta
|
6
tests/ui/attributes/used-issue-126789.rs
Normal file
6
tests/ui/attributes/used-issue-126789.rs
Normal file
@ -0,0 +1,6 @@
|
||||
extern "C" {
|
||||
#[used] //~ ERROR attribute must be applied to a `static` variable
|
||||
static FOO: i32;
|
||||
}
|
||||
|
||||
fn main() {}
|
10
tests/ui/attributes/used-issue-126789.stderr
Normal file
10
tests/ui/attributes/used-issue-126789.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used-issue-126789.rs:2:5
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
LL | static FOO: i32;
|
||||
| ---------------- but this is a foreign static item
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -4,16 +4,10 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer
|
||||
LL | let y = *x;
|
||||
| ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: consider removing the dereference here
|
||||
|
|
||||
LL - let y = *x;
|
||||
LL + let y = x;
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL - let y = *x;
|
||||
LL + let y = x.clone();
|
||||
|
|
||||
LL | let y = (*x).clone();
|
||||
| + +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -67,11 +67,6 @@ LL | struct T(u8);
|
||||
...
|
||||
LL | let c = unsafe { *mut_ptr() };
|
||||
| ---------- you could clone this value
|
||||
help: consider removing the dereference here
|
||||
|
|
||||
LL - let c = unsafe { *mut_ptr() };
|
||||
LL + let c = unsafe { mut_ptr() };
|
||||
|
|
||||
|
||||
error[E0507]: cannot move out of a raw pointer
|
||||
--> $DIR/issue-20801.rs:36:22
|
||||
@ -87,11 +82,6 @@ LL | struct T(u8);
|
||||
...
|
||||
LL | let d = unsafe { *const_ptr() };
|
||||
| ------------ you could clone this value
|
||||
help: consider removing the dereference here
|
||||
|
|
||||
LL - let d = unsafe { *const_ptr() };
|
||||
LL + let d = unsafe { const_ptr() };
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -30,9 +30,8 @@ LL | *u.c
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL - *u.c
|
||||
LL + u.c.clone()
|
||||
|
|
||||
LL | (*u.c).clone()
|
||||
| + +++++++++
|
||||
|
||||
error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
|
||||
--> $DIR/move-from-union-field-issue-66500.rs:24:5
|
||||
@ -42,9 +41,8 @@ LL | *u.d
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL - *u.d
|
||||
LL + u.d.clone()
|
||||
|
|
||||
LL | (*u.d).clone()
|
||||
| + +++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -3,6 +3,10 @@ error: extern block cannot be declared unsafe
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
|
||||
= help: add `#![feature(unsafe_extern_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
|
||||
|
||||
error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental
|
||||
--> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5
|
||||
|
@ -9,17 +9,16 @@ error: extern block cannot be declared unsafe
|
||||
|
|
||||
LL | extern "C" unsafe {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
|
||||
= help: add `#![feature(unsafe_extern_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
|
||||
|
||||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/unsafe-foreign-mod-2.rs:4:5
|
||||
|
|
||||
LL | unsafe fn foo();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add unsafe to this `extern` block
|
||||
|
|
||||
LL | unsafe extern "C" unsafe {
|
||||
| ++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -3,6 +3,10 @@ error: extern block cannot be declared unsafe
|
||||
|
|
||||
LL | unsafe extern "C" {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
|
||||
= help: add `#![feature(unsafe_extern_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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
//@ run-rustfix
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
fn main() {
|
||||
struct S<'a>(&'a ());
|
||||
|
||||
fn f1(s: S<'_>) -> S<'_> {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
s
|
||||
}
|
||||
|
||||
fn f2(s: S<'_>) -> S<'_> {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
let x = true;
|
||||
if x {
|
||||
s
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn f3(s: S<'_>) -> S<'_> {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
return s;
|
||||
}
|
||||
|
||||
fn f4(s: S<'_>) -> S<'_> {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
let _x = 1;
|
||||
return s;
|
||||
}
|
||||
}
|
33
tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.rs
Normal file
33
tests/ui/return/infer-return-ty-for-fn-sig-issue-125488.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//@ run-rustfix
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
fn main() {
|
||||
struct S<'a>(&'a ());
|
||||
|
||||
fn f1(s: S<'_>) -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
s
|
||||
}
|
||||
|
||||
fn f2(s: S<'_>) -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
let x = true;
|
||||
if x {
|
||||
s
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn f3(s: S<'_>) -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
return s;
|
||||
}
|
||||
|
||||
fn f4(s: S<'_>) -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed
|
||||
let _x = 1;
|
||||
return s;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:8:24
|
||||
|
|
||||
LL | fn f1(s: S<'_>) -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `S<'_>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:13:24
|
||||
|
|
||||
LL | fn f2(s: S<'_>) -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `S<'_>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:23:24
|
||||
|
|
||||
LL | fn f3(s: S<'_>) -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `S<'_>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/infer-return-ty-for-fn-sig-issue-125488.rs:28:24
|
||||
|
|
||||
LL | fn f4(s: S<'_>) -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `S<'_>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
@ -47,7 +47,7 @@ impl Test9 {
|
||||
|
||||
fn test11(x: &usize) -> &_ {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
&x //~ ERROR cannot return reference to function parameter
|
||||
&x
|
||||
}
|
||||
|
||||
unsafe fn test12(x: *const usize) -> *const *const _ {
|
||||
|
@ -158,7 +158,7 @@ LL | fn test11(x: &usize) -> &_ {
|
||||
| -^
|
||||
| ||
|
||||
| |not allowed in type signatures
|
||||
| help: replace with the correct return type: `&'static &'static usize`
|
||||
| help: replace with the correct return type: `&&usize`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:53:52
|
||||
@ -687,13 +687,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
LL + #![feature(const_trait_impl)]
|
||||
|
|
||||
|
||||
error[E0515]: cannot return reference to function parameter `x`
|
||||
--> $DIR/typeck_type_placeholder_item.rs:50:5
|
||||
|
|
||||
LL | &x
|
||||
| ^^ returns a reference to data owned by the current function
|
||||
error: aborting due to 74 previous errors
|
||||
|
||||
error: aborting due to 75 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403, E0515.
|
||||
Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
@ -3,24 +3,32 @@ error: attribute must be applied to a `static` variable
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
LL | fn foo() {}
|
||||
| ----------- but this is a function
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:7:1
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
LL | struct Foo {}
|
||||
| ------------- but this is a struct
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:10:1
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
LL | trait Bar {}
|
||||
| ------------ but this is a trait
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:13:1
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
LL | impl Bar for Foo {}
|
||||
| ------------------- but this is a implementation block
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -331,6 +331,7 @@ trigger_files = [
|
||||
"src/tools/tidy",
|
||||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/libcxx-version",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
]
|
||||
|
||||
[autolabel."T-infra"]
|
||||
|
Loading…
Reference in New Issue
Block a user