1
Fork 0

Auto merge of #137284 - matthiaskrgr:rollup-deuhk46, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #127793 (Added project-specific Zed IDE settings)
 - #134995 (Stabilize const_slice_flatten)
 - #136301 (Improve instant docs)
 - #136347 (Add a bullet point to `std::fs::copy`)
 - #136794 (Stabilize file_lock)
 - #137094 (x86_win64 ABI: do not use xmm0 with softfloat ABI)
 - #137227 (docs(dev): Update the feature-gate instructions)
 - #137232 (Don't mention `FromResidual` on bad `?`)
 - #137251 (coverage: Get hole spans from nested items without fully visiting them)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-19 20:14:30 +00:00
commit f280acf4c7
21 changed files with 330 additions and 125 deletions

View file

@ -346,35 +346,37 @@ fn extract_hole_spans_from_hir<'tcx>(
body_span: Span, // Usually `hir_body.value.span`, but not always
hir_body: &hir::Body<'tcx>,
) -> Vec<Span> {
struct HolesVisitor<'hir, F> {
tcx: TyCtxt<'hir>,
visit_hole_span: F,
struct HolesVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
body_span: Span,
hole_spans: Vec<Span>,
}
impl<'hir, F: FnMut(Span)> Visitor<'hir> for HolesVisitor<'hir, F> {
/// - We need `NestedFilter::INTRA = true` so that `visit_item` will be called.
/// - Bodies of nested items don't actually get visited, because of the
/// `visit_item` override.
/// - For nested bodies that are not part of an item, we do want to visit any
/// items contained within them.
type NestedFilter = nested_filter::All;
impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> {
/// We have special handling for nested items, but we still want to
/// traverse into nested bodies of things that are not considered items,
/// such as "anon consts" (e.g. array lengths).
type NestedFilter = nested_filter::OnlyBodies;
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
(self.visit_hole_span)(item.span);
/// We override `visit_nested_item` instead of `visit_item` because we
/// only need the item's span, not the item itself.
fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result {
let span = self.tcx.def_span(id.owner_id.def_id);
self.visit_hole_span(span);
// Having visited this item, we don't care about its children,
// so don't call `walk_item`.
}
// We override `visit_expr` instead of the more specific expression
// visitors, so that we have direct access to the expression span.
fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => {
(self.visit_hole_span)(expr.span);
self.visit_hole_span(expr.span);
// Having visited this expression, we don't care about its
// children, so don't call `walk_expr`.
}
@ -384,18 +386,17 @@ fn extract_hole_spans_from_hir<'tcx>(
}
}
}
let mut hole_spans = vec![];
let mut visitor = HolesVisitor {
tcx,
visit_hole_span: |hole_span| {
impl HolesVisitor<'_> {
fn visit_hole_span(&mut self, hole_span: Span) {
// Discard any holes that aren't directly visible within the body span.
if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) {
hole_spans.push(hole_span);
if self.body_span.contains(hole_span) && self.body_span.eq_ctxt(hole_span) {
self.hole_spans.push(hole_span);
}
},
};
}
}
let mut visitor = HolesVisitor { tcx, body_span, hole_spans: vec![] };
visitor.visit_body(hir_body);
hole_spans
visitor.hole_spans
}

View file

@ -1,11 +1,11 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size};
use crate::callconv::{ArgAbi, FnAbi, Reg};
use crate::spec::HasTargetSpec;
use crate::spec::{HasTargetSpec, RustcAbi};
// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
pub(crate) fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| {
match a.layout.backend_repr {
BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
@ -24,10 +24,14 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<
}
BackendRepr::Scalar(scalar) => {
if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
// `i128` is returned in xmm0 by Clang and GCC
// FIXME(#134288): This may change for the `-msvc` targets in the future.
let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
a.cast_to(reg);
if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) {
// Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing.
} else {
// `i128` is returned in xmm0 by Clang and GCC
// FIXME(#134288): This may change for the `-msvc` targets in the future.
let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
a.cast_to(reg);
}
} else if a.layout.size.bytes() > 8
&& !matches!(scalar.primitive(), Primitive::Float(Float::F128))
{

View file

@ -3289,6 +3289,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut parent_trait_pred =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
let parent_def_id = parent_trait_pred.def_id();
if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id)
&& !tcx.features().enabled(sym::try_trait_v2)
{
// If `#![feature(try_trait_v2)]` is not enabled, then there's no point on
// talking about `FromResidual<Result<A, B>>`, as the end user has nothing they
// can do about it. As far as they are concerned, `?` is compiler magic.
return;
}
let self_ty_str =
tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();

View file

@ -4796,7 +4796,7 @@ impl<T, const N: usize> [[T; N]] {
/// assert!(empty_slice_of_arrays.as_flattened().is_empty());
/// ```
#[stable(feature = "slice_flatten", since = "1.80.0")]
#[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
#[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")]
pub const fn as_flattened(&self) -> &[T] {
let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")
@ -4833,7 +4833,7 @@ impl<T, const N: usize> [[T; N]] {
/// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
/// ```
#[stable(feature = "slice_flatten", since = "1.80.0")]
#[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
#[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")]
pub const fn as_flattened_mut(&mut self) -> &mut [T] {
let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")

View file

@ -664,7 +664,6 @@ impl File {
/// # Examples
///
/// ```no_run
/// #![feature(file_lock)]
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
@ -673,7 +672,7 @@ impl File {
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_lock", issue = "130994")]
#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
pub fn lock(&self) -> io::Result<()> {
self.inner.lock()
}
@ -717,7 +716,6 @@ impl File {
/// # Examples
///
/// ```no_run
/// #![feature(file_lock)]
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
@ -726,7 +724,7 @@ impl File {
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_lock", issue = "130994")]
#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
pub fn lock_shared(&self) -> io::Result<()> {
self.inner.lock_shared()
}
@ -775,7 +773,6 @@ impl File {
/// # Examples
///
/// ```no_run
/// #![feature(file_lock)]
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
@ -784,7 +781,7 @@ impl File {
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_lock", issue = "130994")]
#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
pub fn try_lock(&self) -> io::Result<bool> {
self.inner.try_lock()
}
@ -832,7 +829,6 @@ impl File {
/// # Examples
///
/// ```no_run
/// #![feature(file_lock)]
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
@ -841,7 +837,7 @@ impl File {
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_lock", issue = "130994")]
#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
pub fn try_lock_shared(&self) -> io::Result<bool> {
self.inner.try_lock_shared()
}
@ -869,7 +865,6 @@ impl File {
/// # Examples
///
/// ```no_run
/// #![feature(file_lock)]
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
@ -879,7 +874,7 @@ impl File {
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_lock", issue = "130994")]
#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
pub fn unlock(&self) -> io::Result<()> {
self.inner.unlock()
}
@ -2531,6 +2526,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
/// * `from` does not exist.
/// * The current process does not have the permission rights to read
/// `from` or write `to`.
/// * The parent directory of `to` doesn't exist.
///
/// # Examples
///

View file

@ -93,11 +93,17 @@ use crate::sys_common::{FromInner, IntoInner};
/// use std::time::{Instant, Duration};
///
/// let now = Instant::now();
/// let max_seconds = u64::MAX / 1_000_000_000;
/// let duration = Duration::new(max_seconds, 0);
/// let days_per_10_millennia = 365_2425;
/// let solar_seconds_per_day = 60 * 60 * 24;
/// let millenium_in_solar_seconds = 31_556_952_000;
/// assert_eq!(millenium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10);
///
/// let duration = Duration::new(millenium_in_solar_seconds, 0);
/// println!("{:?}", now + duration);
/// ```
///
/// For cross-platform code, you can comfortably use durations of up to around one hundred years.
///
/// # Underlying System calls
///
/// The following system calls are [currently] being used by `now()` to find out

View file

@ -523,19 +523,31 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
/// Handles editor-specific setup differences
#[derive(Clone, Debug, Eq, PartialEq)]
enum EditorKind {
Vscode,
Vim,
Emacs,
Helix,
Vim,
VsCode,
Zed,
}
impl EditorKind {
// Used in `./tests.rs`.
#[allow(dead_code)]
pub const ALL: &[EditorKind] = &[
EditorKind::Emacs,
EditorKind::Helix,
EditorKind::Vim,
EditorKind::VsCode,
EditorKind::Zed,
];
fn prompt_user() -> io::Result<Option<EditorKind>> {
let prompt_str = "Available editors:
1. vscode
2. vim
3. emacs
4. helix
1. Emacs
2. Helix
3. Vim
4. VS Code
5. Zed
Select which editor you would like to set up [default: None]: ";
@ -543,28 +555,41 @@ Select which editor you would like to set up [default: None]: ";
loop {
print!("{}", prompt_str);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
match input.trim().to_lowercase().as_str() {
"1" | "vscode" => return Ok(Some(EditorKind::Vscode)),
"2" | "vim" => return Ok(Some(EditorKind::Vim)),
"3" | "emacs" => return Ok(Some(EditorKind::Emacs)),
"4" | "helix" => return Ok(Some(EditorKind::Helix)),
"" => return Ok(None),
let mut modified_input = input.to_lowercase();
modified_input.retain(|ch| !ch.is_whitespace());
match modified_input.as_str() {
"1" | "emacs" => return Ok(Some(EditorKind::Emacs)),
"2" | "helix" => return Ok(Some(EditorKind::Helix)),
"3" | "vim" => return Ok(Some(EditorKind::Vim)),
"4" | "vscode" => return Ok(Some(EditorKind::VsCode)),
"5" | "zed" => return Ok(Some(EditorKind::Zed)),
"" | "none" => return Ok(None),
_ => {
eprintln!("ERROR: unrecognized option '{}'", input.trim());
eprintln!("NOTE: press Ctrl+C to exit");
}
};
}
input.clear();
}
}
/// A list of historical hashes of each LSP settings file
/// New entries should be appended whenever this is updated so we can detect
/// outdated vs. user-modified settings files.
fn hashes(&self) -> Vec<&str> {
fn hashes(&self) -> &'static [&'static str] {
match self {
EditorKind::Vscode | EditorKind::Vim => vec![
EditorKind::Emacs => &[
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
"d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
],
EditorKind::Helix => &[
"2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
"6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040",
],
EditorKind::Vim | EditorKind::VsCode => &[
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
@ -576,12 +601,8 @@ Select which editor you would like to set up [default: None]: ";
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
],
EditorKind::Emacs => vec![
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
"d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
],
EditorKind::Helix => {
vec!["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"]
EditorKind::Zed => {
&["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"]
}
}
}
@ -592,29 +613,31 @@ Select which editor you would like to set up [default: None]: ";
fn settings_short_path(&self) -> PathBuf {
self.settings_folder().join(match self {
EditorKind::Vscode => "settings.json",
EditorKind::Vim => "coc-settings.json",
EditorKind::Emacs => ".dir-locals.el",
EditorKind::Helix => "languages.toml",
EditorKind::Vim => "coc-settings.json",
EditorKind::VsCode | EditorKind::Zed => "settings.json",
})
}
fn settings_folder(&self) -> PathBuf {
match self {
EditorKind::Vscode => PathBuf::from(".vscode"),
EditorKind::Vim => PathBuf::from(".vim"),
EditorKind::Emacs => PathBuf::new(),
EditorKind::Helix => PathBuf::from(".helix"),
EditorKind::Vim => PathBuf::from(".vim"),
EditorKind::VsCode => PathBuf::from(".vscode"),
EditorKind::Zed => PathBuf::from(".zed"),
}
}
fn settings_template(&self) -> &str {
fn settings_template(&self) -> &'static str {
match self {
EditorKind::Vscode | EditorKind::Vim => {
include_str!("../../../../etc/rust_analyzer_settings.json")
}
EditorKind::Emacs => include_str!("../../../../etc/rust_analyzer_eglot.el"),
EditorKind::Helix => include_str!("../../../../etc/rust_analyzer_helix.toml"),
EditorKind::Vim | EditorKind::VsCode => {
include_str!("../../../../etc/rust_analyzer_settings.json")
}
EditorKind::Zed => include_str!("../../../../etc/rust_analyzer_zed.json"),
}
}

View file

@ -5,13 +5,16 @@ use crate::utils::helpers::hex_encode;
#[test]
fn check_matching_settings_hash() {
let editor = EditorKind::Vscode;
let mut hasher = sha2::Sha256::new();
hasher.update(&editor.settings_template());
let hash = hex_encode(hasher.finalize().as_slice());
assert_eq!(
&hash,
editor.hashes().last().unwrap(),
"Update `EditorKind::hashes()` with the new hash of `src/etc/rust_analyzer_settings.json`"
);
for editor in EditorKind::ALL {
let mut hasher = sha2::Sha256::new();
hasher.update(&editor.settings_template());
let hash = hex_encode(hasher.finalize().as_slice());
assert_eq!(
&hash,
editor.hashes().last().unwrap(),
"Update `EditorKind::hashes()` with the new hash of `{}` for `EditorKind::{:?}`",
editor.settings_template(),
editor,
);
}
}

View file

@ -154,6 +154,16 @@ You can run `./x setup editor` and select `helix`, which will prompt you to
create `languages.toml` with the recommended configuration for Helix. The
recommended settings live at [`src/etc/rust_analyzer_helix.toml`].
### Zed
Zed comes with built-in LSP and rust-analyzer support.
It can be configured through `.zed/settings.json`, as described
[here](https://zed.dev/docs/configuring-languages). Selecting `zed`
in `./x setup editor` will prompt you to create a `.zed/settings.json`
file which will configure Zed with the recommended configuration. The
recommended `rust-analyzer` settings live
at [`src/etc/rust_analyzer_zed.json`].
## Check, check, and check again
When doing simple refactoring, it can be useful to run `./x check`
@ -381,4 +391,5 @@ load this completion.
[`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json
[`src/etc/rust_analyzer_eglot.el`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_eglot.el
[`src/etc/rust_analyzer_helix.toml`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_helix.toml
[`src/etc/rust_analyzer_zed.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_zed.json
[`src/etc/pre-push.sh`]: https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh

View file

@ -167,9 +167,7 @@ a new unstable feature:
1. Prevent usage of the new feature unless the feature gate is set.
You can check it in most places in the compiler using the
expression `tcx.features().$feature_name` (or
`sess.features_untracked().$feature_name` if the
tcx is unavailable)
expression `tcx.features().$feature_name()`
If the feature gate is not set, you should either maintain
the pre-feature behavior or raise an error, depending on

View file

@ -0,0 +1,52 @@
{
"lsp": {
"rust-analyzer": {
"initialization_options": {
"cargo": {
"buildScripts": {
"enable": true,
"invocationLocation": "root",
"invocationStrategy": "once",
"overrideCommand": ["python3", "x.py", "check", "--json-output"]
},
"extraEnv": {
"RUSTC_BOOTSTRAP": "1"
},
"sysrootSrc": "./library"
},
"check": {
"invocationLocation": "root",
"invocationStrategy": "once",
"overrideCommand": ["python3", "x.py", "check", "--json-output"]
},
"linkedProjects": [
"Cargo.toml",
"library/Cargo.toml",
"src/tools/x/Cargo.toml",
"src/bootstrap/Cargo.toml",
"src/tools/rust-analyzer/Cargo.toml",
"compiler/rustc_codegen_cranelift/Cargo.toml",
"compiler/rustc_codegen_gcc/Cargo.toml"
],
"procMacro": {
"enable": true,
"server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv"
},
"rustc": {
"source": "./Cargo.toml"
},
"rustfmt": {
"overrideCommand": [
"${workspaceFolder}/build/host/rustfmt/bin/rustfmt",
"--edition=2021"
]
},
"server": {
"extraEnv": {
"RUSTUP_TOOLCHAIN": "nightly"
}
}
}
}
}
}

View file

@ -0,0 +1,26 @@
//@ assembly-output: emit-asm
//@ add-core-stubs
//@ revisions: msvc softfloat
//@ compile-flags: -Copt-level=3
//@[msvc] compile-flags: --target x86_64-pc-windows-msvc
//@[msvc] needs-llvm-components: x86
//@[softfloat] compile-flags: --target x86_64-unknown-uefi
//@[softfloat] needs-llvm-components: x86
#![feature(no_core)]
#![no_core]
#![crate_type = "lib"]
extern crate minicore;
use minicore::*;
// CHECK-LABEL: ret_i128
// Hardfloat targets return via xmm0, softfloat targets via rax and rdx.
// msvc: movaps {{.*}}, %xmm0
// softfloat: movq (%[[INPUT:.*]]), %rax
// softfloat-NEXT: movq 8(%[[INPUT]]), %rdx
// CHECK-NEXT: retq
#[no_mangle]
pub extern "C" fn ret_i128(x: &i128) -> i128 {
*x
}

View file

@ -4,13 +4,18 @@
//@ compile-flags: -Copt-level=1
//@ add-core-stubs
//@ revisions: MSVC MINGW
//@ revisions: MSVC MINGW softfloat
//@ [MSVC] needs-llvm-components: x86
//@ [MINGW] needs-llvm-components: x86
//@ [MSVC] compile-flags: --target x86_64-pc-windows-msvc
//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu
// Use `WIN` as a common prefix for MSVC and MINGW but *not* the softfloat test.
//@ [MSVC] filecheck-flags: --check-prefix=WIN
//@ [MINGW] needs-llvm-components: x86
//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu
//@ [MINGW] filecheck-flags: --check-prefix=WIN
// The `x86_64-unknown-uefi` target also uses the Windows calling convention,
// but does not have SSE registers available.
//@ [softfloat] needs-llvm-components: x86
//@ [softfloat] compile-flags: --target x86_64-unknown-uefi
#![crate_type = "lib"]
#![no_std]
@ -28,24 +33,26 @@ extern "C" {
pub extern "C" fn pass(_arg0: u32, arg1: i128) {
// CHECK-LABEL: @pass(
// i128 is passed indirectly on Windows. It should load the pointer to the stack and pass
// a pointer to that allocation.
// WIN-SAME: %_arg0, ptr{{.*}} %arg1)
// WIN: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16
// WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
// WIN: store i128 [[LOADED]], ptr [[PASS]]
// WIN: call void @extern_call
// a pointer to that allocation. The softfloat ABI works the same.
// CHECK-SAME: %_arg0, ptr{{.*}} %arg1)
// CHECK: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16
// CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
// CHECK: store i128 [[LOADED]], ptr [[PASS]]
// CHECK: call void @extern_call
unsafe { extern_call(arg1) };
}
// Check that we produce the correct return ABI
#[no_mangle]
pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 {
// CHECK-LABEL: @ret(
// WIN-LABEL: @ret(
// i128 is returned in xmm0 on Windows
// FIXME(#134288): This may change for the `-msvc` targets in the future.
// WIN-SAME: i32{{.*}} %_arg0, ptr{{.*}} %arg1)
// WIN: [[LOADED:%[_0-9]+]] = load <16 x i8>, ptr %arg1
// WIN-NEXT: ret <16 x i8> [[LOADED]]
// The softfloat ABI returns this indirectly.
// softfloat-LABEL: i128 @ret(i32{{.*}} %_arg0, ptr{{.*}} %arg1)
arg1
}
@ -57,6 +64,7 @@ pub extern "C" fn forward(dst: *mut i128) {
// WIN: [[RETURNED:%[_0-9]+]] = tail call <16 x i8> @extern_ret()
// WIN: store <16 x i8> [[RETURNED]], ptr %dst
// WIN: ret void
// softfloat: [[RETURNED:%[_0-9]+]] = tail call {{.*}}i128 @extern_ret()
unsafe { *dst = extern_ret() };
}
@ -70,10 +78,10 @@ struct RetAggregate {
pub extern "C" fn ret_aggregate(_arg0: u32, arg1: i128) -> RetAggregate {
// CHECK-LABEL: @ret_aggregate(
// Aggregates should also be returned indirectly
// WIN-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1)
// WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
// WIN: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]]
// WIN: store i128 [[LOADED]], ptr [[GEP]]
// WIN: ret void
// CHECK-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1)
// CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
// CHECK: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]]
// CHECK: store i128 [[LOADED]], ptr [[GEP]]
// CHECK: ret void
RetAggregate { a: 1, b: arg1 }
}

View file

@ -1,52 +1,57 @@
Function name: <holes::main::MyStruct>::_method (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 25, 09, 00, 1d]
Raw bytes (9): 0x[01, 01, 00, 01, 00, 2b, 09, 00, 1d]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 37, 9) to (start + 0, 29)
- Code(Zero) at (prev + 43, 9) to (start + 0, 29)
Highest counter ID seen: (none)
Function name: holes::main
Raw bytes (44): 0x[01, 01, 00, 08, 01, 08, 01, 06, 11, 01, 0f, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 01, 02]
Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 8
- Code(Counter(0)) at (prev + 8, 1) to (start + 6, 17)
- Code(Counter(0)) at (prev + 15, 5) to (start + 0, 18)
Number of file 0 mappings: 13
- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18)
- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17)
- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
- Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15)
- Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15)
- Code(Counter(0)) at (prev + 10, 5) to (start + 1, 2)
- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13)
- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2)
Highest counter ID seen: c0
Function name: holes::main::_unused_fn (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 17]
Raw bytes (9): 0x[01, 01, 00, 01, 00, 1f, 05, 00, 17]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 25, 5) to (start + 0, 23)
- Code(Zero) at (prev + 31, 5) to (start + 0, 23)
Highest counter ID seen: (none)
Function name: holes::main::{closure#0} (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a]
Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 09, 02, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 18, 9) to (start + 2, 10)
- Code(Zero) at (prev + 24, 9) to (start + 2, 10)
Highest counter ID seen: (none)
Function name: holes::main::{closure#1} (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 3d, 09, 02, 0a]
Raw bytes (9): 0x[01, 01, 00, 01, 00, 4b, 09, 02, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 61, 9) to (start + 2, 10)
- Code(Zero) at (prev + 75, 9) to (start + 2, 10)
Highest counter ID seen: (none)

View file

@ -7,10 +7,16 @@
LL| |
LL| 1|fn main() {
LL| 1| black_box(());
LL| 1|
LL| 1| // Splitting this across multiple lines makes it easier to see where the
LL| 1| // coverage mapping regions begin and end.
LL| 1| #[rustfmt::skip]
LL| |
LL| | static MY_STATIC: () = ();
LL| |
LL| 1| black_box(());
LL| |
LL| | const MY_CONST: () = ();
LL| |
LL| | // Splitting this across multiple lines makes it easier to see where the
LL| | // coverage mapping regions begin and end.
LL| | #[rustfmt::skip]
LL| 1| let _closure =
LL| | |
LL| | _arg: (),
@ -39,6 +45,14 @@
LL| |
LL| 1| black_box(());
LL| |
LL| | trait MyTrait {}
LL| |
LL| 1| black_box(());
LL| |
LL| | impl MyTrait for MyStruct {}
LL| |
LL| 1| black_box(());
LL| |
LL| | macro_rules! _my_macro {
LL| | () => {};
LL| | }
@ -64,5 +78,24 @@
LL| | ;
LL| |
LL| 1| black_box(());
LL| 1|
LL| 1| // This tests the edge case of a const block nested inside an "anon const",
LL| 1| // such as the length of an array literal. Handling this case requires
LL| 1| // `nested_filter::OnlyBodies` or equivalent.
LL| 1| #[rustfmt::skip]
LL| 1| let _const_block_inside_anon_const =
LL| 1| [
LL| 1| 0
LL| 1| ;
LL| 1| 7
LL| 1| +
LL| 1| const
LL| | {
LL| | 3
LL| 1| }
LL| 1| ]
LL| 1| ;
LL| 1|
LL| 1| black_box(());
LL| 1|}

View file

@ -8,6 +8,12 @@ use core::hint::black_box;
fn main() {
black_box(());
static MY_STATIC: () = ();
black_box(());
const MY_CONST: () = ();
// Splitting this across multiple lines makes it easier to see where the
// coverage mapping regions begin and end.
#[rustfmt::skip]
@ -39,6 +45,14 @@ fn main() {
black_box(());
trait MyTrait {}
black_box(());
impl MyTrait for MyStruct {}
black_box(());
macro_rules! _my_macro {
() => {};
}
@ -64,4 +78,23 @@ fn main() {
;
black_box(());
// This tests the edge case of a const block nested inside an "anon const",
// such as the length of an array literal. Handling this case requires
// `nested_filter::OnlyBodies` or equivalent.
#[rustfmt::skip]
let _const_block_inside_anon_const =
[
0
;
7
+
const
{
3
}
]
;
black_box(());
}

View file

@ -1,3 +1,4 @@
#![feature(try_trait_v2)]
fn foo() -> Result<String, String> { //~ NOTE expected `String` because of this
let test = String::from("one,two");
let x = test

View file

@ -1,5 +1,5 @@
error[E0277]: `?` couldn't convert the error to `String`
--> $DIR/question-mark-result-err-mismatch.rs:14:22
--> $DIR/question-mark-result-err-mismatch.rs:15:22
|
LL | fn foo() -> Result<String, String> {
| ---------------------- expected `String` because of this
@ -17,7 +17,7 @@ LL | .map(|()| "")?;
= note: required for `Result<String, String>` to implement `FromResidual<Result<Infallible, ()>>`
error[E0277]: `?` couldn't convert the error to `String`
--> $DIR/question-mark-result-err-mismatch.rs:28:25
--> $DIR/question-mark-result-err-mismatch.rs:29:25
|
LL | fn bar() -> Result<(), String> {
| ------------------ expected `String` because of this
@ -40,7 +40,7 @@ LL | .map_err(|_| ())?;
= note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, ()>>`
error[E0277]: `?` couldn't convert the error to `String`
--> $DIR/question-mark-result-err-mismatch.rs:48:11
--> $DIR/question-mark-result-err-mismatch.rs:49:11
|
LL | fn baz() -> Result<String, String> {
| ---------------------- expected `String` because of this

View file

@ -10,7 +10,6 @@ LL | Err("")?;
= help: the trait `From<&str>` is not implemented for `TryFromSliceError`
but trait `From<Infallible>` is implemented for it
= help: for that trait implementation, expected `Infallible`, found `&str`
= note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
--> $DIR/try-block-bad-type.rs:12:9

View file

@ -12,7 +12,6 @@ LL | Ok(Err(123_i32)?)
= help: the following other types implement trait `From<T>`:
`u8` implements `From<Char>`
`u8` implements `From<bool>`
= note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> $DIR/bad-interconversion.rs:9:12

View file

@ -19,7 +19,6 @@ LL | Err(5)?;
`(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>`
`(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>`
and 4 others
= note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`
error: aborting due to 1 previous error