Auto merge of #75510 - tmandry:rollup-tb9mllu, r=tmandry
Rollup of 12 pull requests Successful merges: - #74650 (Correctly parse `{} && false` in tail expression) - #75319 (Fix ICE #75307 in `format`) - #75417 (Don't spill operands onto the stack in naked functions) - #75452 (self-profile: Cache more query key strings when doing self-profiling.) - #75459 (fix LocalInfo doc comment) - #75462 (Remove unused tcx parameter) - #75467 (Fix E0741 error code explanation) - #75471 (Change registered "program name" for -Cllvm-args usage messages) - #75477 (Expand function pointer docs) - #75479 (make rustc-docs component available to rustup) - #75496 (Prioritization WG: Open Zulip topics only for `I-prioritize` issues) - #75500 (Disable zlib in LLVM on aarch64-apple-darwin) Failed merges: r? @ghost
This commit is contained in:
commit
8e5a27766f
@ -1058,6 +1058,8 @@ mod prim_ref {}
|
||||
/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
|
||||
/// pointers, make your type `Option<fn()>` with your required signature.
|
||||
///
|
||||
/// ### Safety
|
||||
///
|
||||
/// Plain function pointers are obtained by casting either plain functions, or closures that don't
|
||||
/// capture an environment:
|
||||
///
|
||||
@ -1095,23 +1097,60 @@ mod prim_ref {}
|
||||
/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
|
||||
/// ```
|
||||
///
|
||||
/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
|
||||
/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
|
||||
/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
|
||||
/// fn()`, and so on for the various ABIs that Rust supports. Non-`extern` functions have an ABI
|
||||
/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
|
||||
/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
|
||||
/// ### ABI
|
||||
///
|
||||
/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
|
||||
/// On top of that, function pointers can vary based on what ABI they use. This
|
||||
/// is achieved by adding the `extern` keyword before the type, followed by the
|
||||
/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
|
||||
/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
|
||||
/// type `extern "C" fn()`.
|
||||
///
|
||||
/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
|
||||
/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
|
||||
/// ABI.
|
||||
///
|
||||
/// For more information and a list of supported ABIs, see [the nomicon's
|
||||
/// section on foreign calling conventions][nomicon-abi].
|
||||
///
|
||||
/// ### Variadic functions
|
||||
///
|
||||
/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
|
||||
/// to be called with a variable number of arguments. Normal rust functions, even those with an
|
||||
/// to be called with a variable number of arguments. Normal Rust functions, even those with an
|
||||
/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
|
||||
/// variadic functions][nomicon-variadic].
|
||||
///
|
||||
/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
|
||||
///
|
||||
/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
|
||||
/// ### Creating function pointers
|
||||
///
|
||||
/// When `bar` is the name of a function, then the expression `bar` is *not* a
|
||||
/// function pointer. Rather, it denotes a value of an unnameable type that
|
||||
/// uniquely identifies the function `bar`. The value is zero-sized because the
|
||||
/// type already identifies the function. This has the advantage that "calling"
|
||||
/// the value (it implements the `Fn*` traits) does not require dynamic
|
||||
/// dispatch.
|
||||
///
|
||||
/// This zero-sized type *coerces* to a regular function pointer. For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
///
|
||||
/// fn bar(x: i32) {}
|
||||
///
|
||||
/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
|
||||
/// assert_eq!(mem::size_of_val(¬_bar_ptr), 0);
|
||||
///
|
||||
/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
|
||||
/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
|
||||
///
|
||||
/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
|
||||
/// ```
|
||||
///
|
||||
/// The last line shows that `&bar` is not a function pointer either. Rather, it
|
||||
/// is a reference to the function-specific ZST. `&bar` is basically never what you
|
||||
/// want when `bar` is a function.
|
||||
///
|
||||
/// ### Traits
|
||||
///
|
||||
/// Function pointers implement the following traits:
|
||||
///
|
||||
|
@ -178,7 +178,7 @@ impl Step for Llvm {
|
||||
.define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
|
||||
.define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
|
||||
|
||||
if !target.contains("netbsd") {
|
||||
if !target.contains("netbsd") && target != "aarch64-apple-darwin" {
|
||||
cfg.define("LLVM_ENABLE_ZLIB", "ON");
|
||||
} else {
|
||||
// FIXME: Enable zlib on NetBSD too
|
||||
|
@ -222,7 +222,6 @@ impl AssocOp {
|
||||
Greater | // `{ 42 } > 3`
|
||||
GreaterEqual | // `{ 42 } >= 3`
|
||||
AssignOp(_) | // `{ 42 } +=`
|
||||
LAnd | // `{ 42 } &&foo`
|
||||
As | // `{ 42 } as usize`
|
||||
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
|
||||
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
|
||||
|
@ -149,7 +149,7 @@ fn parse_args<'a>(
|
||||
return Err(err);
|
||||
} else {
|
||||
// ...after that delegate to `expect` to also include the other expected tokens.
|
||||
return Err(p.expect(&token::Comma).err().unwrap());
|
||||
let _ = p.expect(&token::Comma)?;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
@ -359,24 +359,18 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||
// for `println!("{7:7$}", 1);`
|
||||
refs.sort();
|
||||
refs.dedup();
|
||||
let (arg_list, mut sp) = if refs.len() == 1 {
|
||||
let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
|
||||
(
|
||||
format!("argument {}", refs[0]),
|
||||
if spans.is_empty() {
|
||||
MultiSpan::from_span(self.fmtsp)
|
||||
} else {
|
||||
MultiSpan::from_spans(spans)
|
||||
},
|
||||
)
|
||||
let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
|
||||
let sp = if self.arg_spans.is_empty() || spans.is_empty() {
|
||||
MultiSpan::from_span(self.fmtsp)
|
||||
} else {
|
||||
let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect());
|
||||
let reg = refs.pop().unwrap();
|
||||
(format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg,), pos)
|
||||
MultiSpan::from_spans(spans)
|
||||
};
|
||||
let arg_list = if refs.len() == 1 {
|
||||
format!("argument {}", refs[0])
|
||||
} else {
|
||||
let reg = refs.pop().unwrap();
|
||||
format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg)
|
||||
};
|
||||
if self.arg_spans.is_empty() {
|
||||
sp = MultiSpan::from_span(self.fmtsp);
|
||||
}
|
||||
|
||||
e = self.ecx.struct_span_err(
|
||||
sp,
|
||||
@ -1067,10 +1061,9 @@ pub fn expand_preparsed_format_args(
|
||||
let args_unused = errs_len;
|
||||
|
||||
let mut diag = {
|
||||
if errs_len == 1 {
|
||||
let (sp, msg) = errs.into_iter().next().unwrap();
|
||||
let mut diag = cx.ecx.struct_span_err(sp, msg);
|
||||
diag.span_label(sp, msg);
|
||||
if let [(sp, msg)] = &errs[..] {
|
||||
let mut diag = cx.ecx.struct_span_err(*sp, *msg);
|
||||
diag.span_label(*sp, *msg);
|
||||
diag
|
||||
} else {
|
||||
let mut diag = cx.ecx.struct_span_err(
|
||||
|
@ -73,7 +73,8 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
llvm_c_strs.push(s);
|
||||
}
|
||||
};
|
||||
add("rustc", true); // fake program name
|
||||
// Set the llvm "program name" to make usage and invalid argument messages more clear.
|
||||
add("rustc -Cllvm-args=\"...\" with", true);
|
||||
if sess.time_llvm_passes() {
|
||||
add("-time-passes", false);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::traits::*;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::config::DebugInfo;
|
||||
@ -216,6 +217,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
LocalRef::Operand(None) => return,
|
||||
|
||||
LocalRef::Operand(Some(operand)) => {
|
||||
// Don't spill operands onto the stack in naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "Spill" the value onto the stack, for debuginfo,
|
||||
// without forcing non-debuginfo uses of the local
|
||||
// to also load from the stack every single time.
|
||||
|
@ -37,8 +37,7 @@ fn i_want_static_closure<F>(a: F)
|
||||
|
||||
fn print_string(s: Mutex<MyString<'static>>) {
|
||||
|
||||
i_want_static_closure(move || { // error: this closure has lifetime 'a
|
||||
// rather than 'static
|
||||
i_want_static_closure(move || { // ok!
|
||||
println!("{}", s.lock().unwrap().data);
|
||||
});
|
||||
}
|
||||
|
@ -857,9 +857,12 @@ pub struct LocalDecl<'tcx> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(LocalDecl<'_>, 56);
|
||||
|
||||
/// Extra information about a some locals that's used for diagnostics. (Not
|
||||
/// used for non-StaticRef temporaries, the return place, or anonymous function
|
||||
/// parameters.)
|
||||
/// Extra information about a some locals that's used for diagnostics and for
|
||||
/// classifying variables into local variables, statics, etc, which is needed e.g.
|
||||
/// for unsafety checking.
|
||||
///
|
||||
/// Not used for non-StaticRef temporaries, the return place, or anonymous
|
||||
/// function parameters.
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
|
||||
pub enum LocalInfo<'tcx> {
|
||||
/// A user-defined local variable or function parameter
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::ty::context::TyCtxt;
|
||||
use crate::ty::WithOptConstParam;
|
||||
use measureme::{StringComponent, StringId};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::profiling::SelfProfiler;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_query_system::query::QueryCache;
|
||||
use rustc_query_system::query::QueryState;
|
||||
@ -154,6 +155,49 @@ impl SpecIntoSelfProfilingString for DefIndex {
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecIntoSelfProfilingString for LocalDefId {
|
||||
fn spec_to_self_profile_string(
|
||||
&self,
|
||||
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
|
||||
) -> StringId {
|
||||
builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
|
||||
fn spec_to_self_profile_string(
|
||||
&self,
|
||||
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
|
||||
) -> StringId {
|
||||
// We print `WithOptConstParam` values as tuples to make them shorter
|
||||
// and more readable, without losing information:
|
||||
//
|
||||
// "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
|
||||
// becomes "(foo::bar, foo::baz)" and
|
||||
// "WithOptConstParam { did: foo::bar, const_param_did: None }"
|
||||
// becomes "(foo::bar, _)".
|
||||
|
||||
let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
|
||||
|
||||
let const_param_did = if let Some(const_param_did) = self.const_param_did {
|
||||
let const_param_did = builder.def_id_to_string_id(const_param_did);
|
||||
StringComponent::Ref(const_param_did)
|
||||
} else {
|
||||
StringComponent::Value("_")
|
||||
};
|
||||
|
||||
let components = [
|
||||
StringComponent::Value("("),
|
||||
did,
|
||||
StringComponent::Value(", "),
|
||||
const_param_did,
|
||||
StringComponent::Value(")"),
|
||||
];
|
||||
|
||||
builder.profiler.alloc_string(&components[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
|
||||
where
|
||||
T0: SpecIntoSelfProfilingString,
|
||||
|
@ -10,7 +10,6 @@ use rustc_hir::lang_items;
|
||||
use rustc_hir::{GeneratorKind, HirIdMap, Node};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
@ -798,22 +797,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
argument_scope: region::Scope,
|
||||
ast_body: &'tcx hir::Expr<'tcx>,
|
||||
) -> BlockAnd<()> {
|
||||
let tcx = self.hir.tcx();
|
||||
let attrs = tcx.codegen_fn_attrs(fn_def_id);
|
||||
let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED);
|
||||
|
||||
// Allocate locals for the function arguments
|
||||
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
|
||||
let source_info =
|
||||
SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
|
||||
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||
|
||||
// Emit function argument debuginfo only for non-naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
if naked {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a simple binding pattern, give debuginfo a nice name.
|
||||
if let Some(arg) = arg_opt {
|
||||
if let Some(ident) = arg.pat.simple_ident() {
|
||||
@ -826,6 +815,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = self.hir.tcx();
|
||||
let tcx_hir = tcx.hir();
|
||||
let hir_typeck_results = self.hir.typeck_results();
|
||||
|
||||
|
@ -318,11 +318,18 @@ impl<'a> Parser<'a> {
|
||||
// want to keep their span info to improve diagnostics in these cases in a later stage.
|
||||
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
|
||||
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
|
||||
(true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
|
||||
(true, Some(AssocOp::Add)) // `{ 42 } + 42
|
||||
// If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
|
||||
// `if x { a } else { b } && if y { c } else { d }`
|
||||
if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
|
||||
if !self.look_ahead(1, |t| t.is_used_keyword()) => {
|
||||
// These cases are ambiguous and can't be identified in the parser alone.
|
||||
let sp = self.sess.source_map().start_point(self.token.span);
|
||||
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
|
||||
false
|
||||
}
|
||||
(true, Some(AssocOp::LAnd)) => {
|
||||
// `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
|
||||
// above due to #74233.
|
||||
// These cases are ambiguous and can't be identified in the parser alone.
|
||||
let sp = self.sess.source_map().start_point(self.token.span);
|
||||
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
|
||||
|
@ -43,9 +43,8 @@ pub trait QueryCache: QueryStorage {
|
||||
OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
|
||||
OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;
|
||||
|
||||
fn complete<CTX: QueryContext>(
|
||||
fn complete(
|
||||
&self,
|
||||
tcx: CTX,
|
||||
lock_sharded_storage: &mut Self::Sharded,
|
||||
key: Self::Key,
|
||||
value: Self::Value,
|
||||
@ -112,9 +111,8 @@ impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn complete<CTX: QueryContext>(
|
||||
fn complete(
|
||||
&self,
|
||||
_: CTX,
|
||||
lock_sharded_storage: &mut Self::Sharded,
|
||||
key: K,
|
||||
value: V,
|
||||
@ -195,9 +193,8 @@ impl<'tcx, K: Eq + Hash, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn complete<CTX: QueryContext>(
|
||||
fn complete(
|
||||
&self,
|
||||
_: CTX,
|
||||
lock_sharded_storage: &mut Self::Sharded,
|
||||
key: K,
|
||||
value: V,
|
||||
|
@ -264,7 +264,7 @@ where
|
||||
/// Completes the query by updating the query cache with the `result`,
|
||||
/// signals the waiter and forgets the JobOwner, so it won't poison the query
|
||||
#[inline(always)]
|
||||
fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
|
||||
fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
|
||||
// We can move out of `self` here because we `mem::forget` it below
|
||||
let key = unsafe { ptr::read(&self.key) };
|
||||
let state = self.state;
|
||||
@ -278,7 +278,7 @@ where
|
||||
QueryResult::Started(job) => job,
|
||||
QueryResult::Poisoned => panic!(),
|
||||
};
|
||||
let result = state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index);
|
||||
let result = state.cache.complete(&mut lock.cache, key, result, dep_node_index);
|
||||
(job, result)
|
||||
};
|
||||
|
||||
@ -432,7 +432,7 @@ where
|
||||
tcx.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
|
||||
}
|
||||
|
||||
return job.complete(tcx, result, dep_node_index);
|
||||
return job.complete(result, dep_node_index);
|
||||
}
|
||||
|
||||
let dep_node = query.to_dep_node(tcx, &key);
|
||||
@ -458,7 +458,7 @@ where
|
||||
})
|
||||
});
|
||||
if let Some((result, dep_node_index)) = loaded {
|
||||
return job.complete(tcx, result, dep_node_index);
|
||||
return job.complete(result, dep_node_index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,7 +609,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let result = job.complete(tcx, result, dep_node_index);
|
||||
let result = job.complete(result, dep_node_index);
|
||||
|
||||
(result, dep_node_index)
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_await(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_parentheses(err, expr);
|
||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
}
|
||||
|
||||
|
@ -5401,6 +5401,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_missing_parentheses(&self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>) {
|
||||
let sp = self.tcx.sess.source_map().start_point(expr.span);
|
||||
if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
|
||||
// `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
|
||||
self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
|
||||
}
|
||||
}
|
||||
|
||||
fn note_need_for_fn_pointer(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
|
@ -18,7 +18,7 @@ pub fn naked_empty() {
|
||||
// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
|
||||
pub fn naked_with_args(a: isize) {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
|
||||
// CHECK-NEXT: %a = alloca i{{[0-9]+}}
|
||||
&a; // keep variable in an alloca
|
||||
// CHECK: ret void
|
||||
}
|
||||
@ -39,7 +39,7 @@ pub fn naked_with_return() -> isize {
|
||||
#[naked]
|
||||
pub fn naked_with_args_and_return(a: isize) -> isize {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
|
||||
// CHECK-NEXT: %a = alloca i{{[0-9]+}}
|
||||
&a; // keep variable in an alloca
|
||||
// CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
|
||||
a
|
||||
|
@ -1,42 +0,0 @@
|
||||
// min-lldb-version: 310
|
||||
|
||||
// We have to ignore android because of this issue:
|
||||
// https://github.com/rust-lang/rust/issues/74847
|
||||
// ignore-android
|
||||
//
|
||||
// We need to use inline assembly, so just use one platform
|
||||
// only-x86_64
|
||||
|
||||
// compile-flags:-g
|
||||
|
||||
// === GDB TESTS ===================================================================================
|
||||
|
||||
// gdb-command:run
|
||||
|
||||
// gdb-command:info args
|
||||
// gdb-check:No arguments.
|
||||
// gdb-command:continue
|
||||
|
||||
// === LLDB TESTS ==================================================================================
|
||||
|
||||
// lldb-command:run
|
||||
|
||||
// lldb-command:frame variable
|
||||
// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
|
||||
// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
|
||||
// lldb-command:continue
|
||||
|
||||
|
||||
#![feature(asm)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(omit_gdb_pretty_printer_section)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
fn main() {
|
||||
naked(111, 222);
|
||||
}
|
||||
|
||||
#[naked]
|
||||
extern "C" fn naked(x: usize, y: usize) {
|
||||
unsafe { asm!("ret"); } // #break
|
||||
}
|
3
src/test/ui/issues/issue-75307.rs
Normal file
3
src/test/ui/issues/issue-75307.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
|
||||
}
|
10
src/test/ui/issues/issue-75307.stderr
Normal file
10
src/test/ui/issues/issue-75307.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
|
||||
--> $DIR/issue-75307.rs:2:13
|
||||
|
|
||||
LL | format!(r"{}{}{}", named_arg=1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
src/test/ui/parser/expr-as-stmt-2.rs
Normal file
10
src/test/ui/parser/expr-as-stmt-2.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// This is not autofixable because we give extra suggestions to end the first expression with `;`.
|
||||
fn foo(a: Option<u32>, b: Option<u32>) -> bool {
|
||||
if let Some(x) = a { true } else { false }
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
&& //~ ERROR mismatched types
|
||||
if let Some(y) = a { true } else { false }
|
||||
}
|
||||
|
||||
fn main() {}
|
33
src/test/ui/parser/expr-as-stmt-2.stderr
Normal file
33
src/test/ui/parser/expr-as-stmt-2.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expr-as-stmt-2.rs:3:26
|
||||
|
|
||||
LL | if let Some(x) = a { true } else { false }
|
||||
| ---------------------^^^^------------------ help: consider using a semicolon here
|
||||
| | |
|
||||
| | expected `()`, found `bool`
|
||||
| expected this to be `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expr-as-stmt-2.rs:3:40
|
||||
|
|
||||
LL | if let Some(x) = a { true } else { false }
|
||||
| -----------------------------------^^^^^--- help: consider using a semicolon here
|
||||
| | |
|
||||
| | expected `()`, found `bool`
|
||||
| expected this to be `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expr-as-stmt-2.rs:6:5
|
||||
|
|
||||
LL | fn foo(a: Option<u32>, b: Option<u32>) -> bool {
|
||||
| ---- expected `bool` because of return type
|
||||
LL | if let Some(x) = a { true } else { false }
|
||||
| ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
|
||||
...
|
||||
LL | / &&
|
||||
LL | | if let Some(y) = a { true } else { false }
|
||||
| |______________________________________________^ expected `bool`, found `&&bool`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -25,12 +25,6 @@ fn baz() -> i32 {
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn qux(a: Option<u32>, b: Option<u32>) -> bool {
|
||||
(if let Some(x) = a { true } else { false })
|
||||
&& //~ ERROR expected expression
|
||||
if let Some(y) = a { true } else { false }
|
||||
}
|
||||
|
||||
fn moo(x: u32) -> bool {
|
||||
(match x {
|
||||
_ => 1,
|
||||
|
@ -25,12 +25,6 @@ fn baz() -> i32 {
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn qux(a: Option<u32>, b: Option<u32>) -> bool {
|
||||
if let Some(x) = a { true } else { false }
|
||||
&& //~ ERROR expected expression
|
||||
if let Some(y) = a { true } else { false }
|
||||
}
|
||||
|
||||
fn moo(x: u32) -> bool {
|
||||
match x {
|
||||
_ => 1,
|
||||
|
@ -22,16 +22,8 @@ LL | { 42 } + foo;
|
||||
| |
|
||||
| help: parentheses are required to parse this as an expression: `({ 42 })`
|
||||
|
||||
error: expected expression, found `&&`
|
||||
--> $DIR/expr-as-stmt.rs:30:5
|
||||
|
|
||||
LL | if let Some(x) = a { true } else { false }
|
||||
| ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
|
||||
LL | &&
|
||||
| ^^ expected expression
|
||||
|
||||
error: expected expression, found `>`
|
||||
--> $DIR/expr-as-stmt.rs:37:7
|
||||
--> $DIR/expr-as-stmt.rs:31:7
|
||||
|
|
||||
LL | } > 0
|
||||
| ^ expected expression
|
||||
@ -75,7 +67,7 @@ LL | { 3 } * 3
|
||||
| |
|
||||
| help: parentheses are required to parse this as an expression: `({ 3 })`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0614.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
22
src/test/ui/unknown-llvm-arg.rs
Normal file
22
src/test/ui/unknown-llvm-arg.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// compile-flags: -Cllvm-args=-not-a-real-llvm-arg
|
||||
// normalize-stderr-test "--help" -> "-help"
|
||||
// normalize-stderr-test "\n(\n|.)*" -> ""
|
||||
|
||||
// I'm seeing "--help" locally, but "-help" in CI, so I'm normalizing it to just "-help".
|
||||
|
||||
// Note that the rustc-supplied "program name", given when invoking LLVM, is used by LLVM to
|
||||
// generate user-facing error messages and a usage (--help) messages. If the program name is
|
||||
// `rustc`, the usage message in response to `--llvm-args="--help"` starts with:
|
||||
// ```
|
||||
// USAGE: rustc [options]
|
||||
// ```
|
||||
// followed by the list of options not to `rustc` but to `llvm`.
|
||||
//
|
||||
// On the other hand, if the program name is set to `rustc -Cllvm-args="..." with`, the usage
|
||||
// message is more clear:
|
||||
// ```
|
||||
// USAGE: rustc -Cllvm-args="..." with [options]
|
||||
// ```
|
||||
// This test captures the effect of the current program name setting on LLVM command line
|
||||
// error messages.
|
||||
fn main() {}
|
1
src/test/ui/unknown-llvm-arg.stderr
Normal file
1
src/test/ui/unknown-llvm-arg.stderr
Normal file
@ -0,0 +1 @@
|
||||
rustc -Cllvm-args="..." with: Unknown command line argument '-not-a-real-llvm-arg'. Try: 'rustc -Cllvm-args="..." with -help'
|
@ -447,6 +447,7 @@ impl Builder {
|
||||
let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets);
|
||||
package("rustc", HOSTS);
|
||||
package("rustc-dev", HOSTS);
|
||||
package("rustc-docs", HOSTS);
|
||||
package("cargo", HOSTS);
|
||||
package("rust-mingw", MINGW);
|
||||
package("rust-std", TARGETS);
|
||||
|
@ -99,94 +99,3 @@ message_on_add = """\
|
||||
- Needs `I-nominated`?
|
||||
"""
|
||||
message_on_remove = "Issue #{number}'s prioritization request has been removed."
|
||||
|
||||
[notify-zulip."I-nominated"]
|
||||
required_labels = ["T-compiler"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "I-nominated #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-i-nominated-issues)
|
||||
- Already discussed?
|
||||
- Worth the meeting time?
|
||||
- Add agenda entry:
|
||||
- Why nominated?
|
||||
- Assignee?
|
||||
- Issue? PR? What's the status?
|
||||
- Summary and important details?
|
||||
"""
|
||||
message_on_remove = "#{number}'s nomination has been removed."
|
||||
|
||||
[notify-zulip."beta-nominated"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "Backport #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* PR #{number} has been requested for beta backport.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
|
||||
Prepare agenda entry:
|
||||
- Why nominated?
|
||||
- Author, assignee?
|
||||
- Important details?
|
||||
"""
|
||||
message_on_remove = "PR #{number}'s beta backport request has been removed."
|
||||
|
||||
[notify-zulip."stable-nominated"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "Backport #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* PR #{number} has been requested for stable backport.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
|
||||
Prepare agenda entry:
|
||||
- Why nominated?
|
||||
- Author, assignee?
|
||||
- Important details?
|
||||
"""
|
||||
message_on_remove = "PR #{number}'s stable backport request has been removed."
|
||||
|
||||
[notify-zulip."S-waiting-on-team"]
|
||||
required_labels = ["T-compiler"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "S-waiting-on-team #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* PR #{number} is waiting on `T-compiler`.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-prs-waiting-on-team)
|
||||
- Prepare agenda entry:
|
||||
- What is it waiting for?
|
||||
- Important details?
|
||||
- Could be resolved quickly? Tag `I-nominated`.
|
||||
"""
|
||||
message_on_remove = "PR #{number}'s is no longer waiting on `T-compiler`."
|
||||
|
||||
[notify-zulip."P-critical"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "P-critical #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* issue #{number} has been assigned `P-critical`.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
|
||||
- Notify people/groups?
|
||||
- Assign if possible?
|
||||
- Add to agenda:
|
||||
- Assignee?
|
||||
- Summary and important details?
|
||||
- Other actions to move forward?
|
||||
"""
|
||||
|
||||
[notify-zulip."P-high"]
|
||||
required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "P-high regression #{number} {title}"
|
||||
message_on_add = """\
|
||||
@*WG-prioritization/alerts* issue #{number} has been assigned `P-high` and is a regression.
|
||||
|
||||
# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
|
||||
Is issue assigned? If not:
|
||||
- Try to find an assignee?
|
||||
- Otherwise add to agenda:
|
||||
- Mark as unassigned.
|
||||
- Summary and important details?
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user