commit
33f1700cfc
173 changed files with 2455 additions and 2024 deletions
|
|
@ -1592,24 +1592,33 @@ pub enum TagEncoding<VariantIdx: Idx> {
|
|||
/// (so converting the tag to the discriminant can require sign extension).
|
||||
Direct,
|
||||
|
||||
/// Niche (values invalid for a type) encoding the discriminant:
|
||||
/// Discriminant and variant index coincide.
|
||||
/// The variant `untagged_variant` contains a niche at an arbitrary
|
||||
/// offset (field `tag_field` of the enum), which for a variant with
|
||||
/// discriminant `d` is set to
|
||||
/// `(d - niche_variants.start).wrapping_add(niche_start)`
|
||||
/// (this is wrapping arithmetic using the type of the niche field).
|
||||
/// Niche (values invalid for a type) encoding the discriminant.
|
||||
/// Note that for this encoding, the discriminant and variant index of each variant coincide!
|
||||
/// This invariant is codified as part of [`layout_sanity_check`](../rustc_ty_utils/layout/invariant/fn.layout_sanity_check.html).
|
||||
///
|
||||
/// For example, `Option<(usize, &T)>` is represented such that
|
||||
/// `None` has a null pointer for the second tuple field, and
|
||||
/// `Some` is the identity function (with a non-null reference).
|
||||
/// The variant `untagged_variant` contains a niche at an arbitrary
|
||||
/// offset (field [`Variants::Multiple::tag_field`] of the enum).
|
||||
/// For a variant with variant index `i`, such that `i != untagged_variant`,
|
||||
/// the tag is set to `(i - niche_variants.start).wrapping_add(niche_start)`
|
||||
/// (this is wrapping arithmetic using the type of the niche field, cf. the
|
||||
/// [`tag_for_variant`](../rustc_const_eval/interpret/struct.InterpCx.html#method.tag_for_variant)
|
||||
/// query implementation).
|
||||
/// To recover the variant index `i` from a `tag`, the above formula has to be reversed,
|
||||
/// i.e. `i = tag.wrapping_sub(niche_start) + niche_variants.start`. If `i` ends up outside
|
||||
/// `niche_variants`, the tag must have encoded the `untagged_variant`.
|
||||
///
|
||||
/// For example, `Option<(usize, &T)>` is represented such that the tag for
|
||||
/// `None` is the null pointer in the second tuple field, and
|
||||
/// `Some` is the identity function (with a non-null reference)
|
||||
/// and has no additional tag, i.e. the reference being non-null uniquely identifies this variant.
|
||||
///
|
||||
/// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
|
||||
/// range cannot be represented; they must be uninhabited.
|
||||
/// Nonetheless, uninhabited variants can also fall into the range of `niche_variants`.
|
||||
Niche {
|
||||
untagged_variant: VariantIdx,
|
||||
/// This range *may* contain `untagged_variant`; that is then just a "dead value" and
|
||||
/// not used to encode anything.
|
||||
/// This range *may* contain `untagged_variant` or uninhabited variants;
|
||||
/// these are then just "dead values" and not used to encode anything.
|
||||
niche_variants: RangeInclusive<VariantIdx>,
|
||||
/// This is inbounds of the type of the niche field
|
||||
/// (not sign-extended, i.e., all bits beyond the niche field size are 0).
|
||||
|
|
|
|||
|
|
@ -16,10 +16,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -469,7 +469,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
"`if let` guards are experimental",
|
||||
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
|
||||
);
|
||||
gate_all!(let_chains, "`let` expressions in this position are unstable");
|
||||
gate_all!(
|
||||
async_trait_bounds,
|
||||
"`async` trait bounds are unstable",
|
||||
|
|
|
|||
|
|
@ -253,6 +253,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[inline]` and `#[rustc_force_inline]`.
|
||||
Inline(InlineAttr, Span),
|
||||
|
||||
/// Represents `#[link_name]`.
|
||||
LinkName { name: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[loop_match]`.
|
||||
LoopMatch(Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ impl AttributeKind {
|
|||
Stability { .. } => Yes,
|
||||
Cold(..) => No,
|
||||
ConstContinue(..) => No,
|
||||
LinkName { .. } => Yes,
|
||||
LoopMatch(..) => No,
|
||||
MayDangle(..) => No,
|
||||
MustUse { .. } => Yes,
|
||||
|
|
|
|||
30
compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Normal file
30
compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::AttributeKind::LinkName;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct LinkNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
|
||||
const PATH: &[Symbol] = &[sym::link_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
let Some(name) = nv.value_as_str() else {
|
||||
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(LinkName { name, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ pub(crate) mod codegen_attrs;
|
|||
pub(crate) mod confusables;
|
||||
pub(crate) mod deprecation;
|
||||
pub(crate) mod inline;
|
||||
pub(crate) mod link_attrs;
|
||||
pub(crate) mod lint_helpers;
|
||||
pub(crate) mod loop_match;
|
||||
pub(crate) mod must_use;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use crate::attributes::codegen_attrs::{
|
|||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::link_attrs::LinkNameParser;
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
|
|
@ -121,6 +122,7 @@ attribute_parsers!(
|
|||
Single<DeprecationParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<InlineParser>,
|
||||
Single<LinkNameParser>,
|
||||
Single<LoopMatchParser>,
|
||||
Single<MayDangleParser>,
|
||||
Single<MustUseParser>,
|
||||
|
|
|
|||
|
|
@ -496,7 +496,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
| sym::simd_flog
|
||||
| sym::simd_flog10
|
||||
| sym::simd_flog2
|
||||
| sym::simd_round => {
|
||||
| sym::simd_round
|
||||
| sym::simd_round_ties_even => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
||||
if !a.layout().ty.is_simd() {
|
||||
|
|
@ -527,6 +528,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
(sym::simd_flog2, types::F64) => "log2",
|
||||
(sym::simd_round, types::F32) => "roundf",
|
||||
(sym::simd_round, types::F64) => "round",
|
||||
(sym::simd_round_ties_even, types::F32) => "rintf",
|
||||
(sym::simd_round_ties_even, types::F64) => "rint",
|
||||
_ => unreachable!("{:?}", intrinsic),
|
||||
};
|
||||
fx.lib_call(
|
||||
|
|
|
|||
65
compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
Normal file
65
compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::utils::run_command_with_output;
|
||||
|
||||
fn show_usage() {
|
||||
println!(
|
||||
r#"
|
||||
`abi-test` command help:
|
||||
--help : Show this help"#
|
||||
);
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(), String> {
|
||||
let mut args = std::env::args().skip(2);
|
||||
// FractalFir: In the future, I'd like to add some more subcommands / options.
|
||||
// So, this loop ought to stay for that purpose. It should also stay as a while loop(to parse args)
|
||||
#[allow(clippy::never_loop, clippy::while_let_on_iterator)]
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"--help" => {
|
||||
show_usage();
|
||||
return Ok(());
|
||||
}
|
||||
_ => return Err(format!("Unknown option {arg:?}")),
|
||||
}
|
||||
}
|
||||
// Ensure that we have a cloned version of abi-cafe on hand.
|
||||
crate::utils::git_clone(
|
||||
"https://github.com/Gankra/abi-cafe.git",
|
||||
Some("clones/abi-cafe".as_ref()),
|
||||
true,
|
||||
)
|
||||
.map_err(|err| (format!("Git clone failed with message: {err:?}!")))?;
|
||||
// Configure abi-cafe to use the exact same rustc version we use - this is crucial.
|
||||
// Otherwise, the concept of ABI compatibility becomes meanignless.
|
||||
std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain")
|
||||
.expect("Could not copy toolchain configs!");
|
||||
// Get the backend path.
|
||||
// We will use the *debug* build of the backend - it has more checks enabled.
|
||||
let backend_path = std::path::absolute("target/debug/librustc_codegen_gcc.so").unwrap();
|
||||
let backend_arg = format!("--add-rustc-codegen-backend=cg_gcc:{}", backend_path.display());
|
||||
// Run ABI cafe using cargo.
|
||||
let cmd: &[&dyn AsRef<OsStr>] = &[
|
||||
&"cargo",
|
||||
&"run",
|
||||
&"--release",
|
||||
&"--",
|
||||
&backend_arg,
|
||||
// Test rust-LLVM to Rust-GCC calls
|
||||
&"--pairs",
|
||||
&"rustc_calls_cg_gcc",
|
||||
&"--pairs",
|
||||
&"cg_gcc_calls_rustc",
|
||||
// Test Rust-GCC to C calls
|
||||
&"--pairs",
|
||||
&"cg_gcc_calls_c",
|
||||
&"--pairs",
|
||||
&"c_calls_cg_gcc",
|
||||
];
|
||||
// Run ABI cafe.
|
||||
run_command_with_output(cmd, Some(Path::new("clones/abi-cafe")))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
use std::{env, process};
|
||||
|
||||
mod abi_test;
|
||||
mod build;
|
||||
mod clean;
|
||||
mod clone_gcc;
|
||||
|
|
@ -12,7 +13,6 @@ mod rust_tools;
|
|||
mod rustc_info;
|
||||
mod test;
|
||||
mod utils;
|
||||
|
||||
const BUILD_DIR: &str = "build";
|
||||
|
||||
macro_rules! arg_error {
|
||||
|
|
@ -44,7 +44,8 @@ Commands:
|
|||
info : Displays information about the build environment and project configuration.
|
||||
clone-gcc : Clones the GCC compiler from a specified source.
|
||||
fmt : Runs rustfmt
|
||||
fuzz : Fuzzes `cg_gcc` using rustlantis"
|
||||
fuzz : Fuzzes `cg_gcc` using rustlantis
|
||||
abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ pub enum Command {
|
|||
Info,
|
||||
Fmt,
|
||||
Fuzz,
|
||||
AbiTest,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -77,6 +79,7 @@ fn main() {
|
|||
Some("test") => Command::Test,
|
||||
Some("info") => Command::Info,
|
||||
Some("clone-gcc") => Command::CloneGcc,
|
||||
Some("abi-test") => Command::AbiTest,
|
||||
Some("fmt") => Command::Fmt,
|
||||
Some("fuzz") => Command::Fuzz,
|
||||
Some("--help") => {
|
||||
|
|
@ -102,6 +105,7 @@ fn main() {
|
|||
Command::CloneGcc => clone_gcc::run(),
|
||||
Command::Fmt => fmt::run(),
|
||||
Command::Fuzz => fuzz::run(),
|
||||
Command::AbiTest => abi_test::run(),
|
||||
} {
|
||||
eprintln!("Command failed to run: {e}");
|
||||
process::exit(1);
|
||||
|
|
|
|||
|
|
@ -738,14 +738,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
|
|||
let path = get_sysroot_dir().join("sysroot_src/library/coretests");
|
||||
let _ = remove_dir_all(path.join("target"));
|
||||
// TODO(antoyo): run in release mode when we fix the failures.
|
||||
// TODO(antoyo): remove the --skip f16::test_total_cmp when this issue is fixed:
|
||||
// https://github.com/rust-lang/rust/issues/141503
|
||||
run_cargo_command(
|
||||
&[&"test", &"--", &"--skip", &"f16::test_total_cmp"],
|
||||
Some(&path),
|
||||
env,
|
||||
args,
|
||||
)?;
|
||||
run_cargo_command(&[&"test"], Some(&path), env, args)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
From cdb3d407740e4f15c3746051f8ba89b8e74e99d3 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Fri, 30 May 2025 13:46:22 -0400
|
||||
Subject: [PATCH] Pin compiler_builtins to 0.1.160
|
||||
|
||||
---
|
||||
library/alloc/Cargo.toml | 2 +-
|
||||
library/std/Cargo.toml | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
|
||||
index 9d0d957..365c9dc 100644
|
||||
--- a/library/alloc/Cargo.toml
|
||||
+++ b/library/alloc/Cargo.toml
|
||||
@@ -16,7 +16,7 @@ bench = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core", public = true }
|
||||
-compiler_builtins = { version = "=0.1.159", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.160", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[features]
|
||||
compiler-builtins-mem = ['compiler_builtins/mem']
|
||||
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
|
||||
index 4ff4895..31371f0 100644
|
||||
--- a/library/std/Cargo.toml
|
||||
+++ b/library/std/Cargo.toml
|
||||
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
panic_unwind = { path = "../panic_unwind", optional = true }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
core = { path = "../core", public = true }
|
||||
-compiler_builtins = { version = "=0.1.159" }
|
||||
+compiler_builtins = { version = "=0.1.160" }
|
||||
unwind = { path = "../unwind" }
|
||||
hashbrown = { version = "0.15", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-05-21"
|
||||
channel = "nightly-2025-06-02"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
self.block
|
||||
}
|
||||
|
||||
fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
|
||||
let func = cx.rvalue_as_function(func);
|
||||
fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
|
||||
func.new_block(name)
|
||||
}
|
||||
|
||||
|
|
@ -782,6 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
return self.context.new_call(self.location, fmod, &[a, b]);
|
||||
}
|
||||
TypeKind::FP128 => {
|
||||
// TODO(antoyo): use get_simple_function_f128_2args.
|
||||
let f128_type = self.type_f128();
|
||||
let fmodf128 = self.context.new_function(
|
||||
None,
|
||||
|
|
@ -938,22 +938,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
|
||||
let block = self.llbb();
|
||||
let function = block.get_function();
|
||||
// NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
|
||||
// For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
|
||||
// Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
|
||||
//
|
||||
// From GCCs perspective:
|
||||
// __int128_t __attribute__((aligned(16))) __attribute__((aligned(16)))
|
||||
// and:
|
||||
// __int128_t __attribute__((aligned(16)))
|
||||
// are 2 distinct, incompatible types.
|
||||
//
|
||||
// So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
|
||||
// but the GCC APIs to facilitate this just aren't quite there yet.
|
||||
|
||||
// This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
|
||||
// Otherwise, this may be an under-aligned load, so we will still call get_aligned.
|
||||
let mut can_skip_align = (pointee_ty == self.cx.u128_type
|
||||
|| pointee_ty == self.cx.i128_type)
|
||||
&& align == self.int128_align;
|
||||
// We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
|
||||
can_skip_align = can_skip_align
|
||||
|| (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
|
||||
&& align.bytes() == 1;
|
||||
// Skip the call to `get_aligned` when possible.
|
||||
let aligned_type =
|
||||
if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };
|
||||
|
||||
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
|
||||
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
|
||||
// the current basic block. Otherwise, it could be used in another basic block, causing a
|
||||
// dereference after a drop, for instance.
|
||||
// FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
|
||||
// Ideally, we shouldn't need to do this check.
|
||||
// FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
|
||||
// the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
|
||||
// under-aligned loads correctly.
|
||||
let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type)
|
||||
&& align == self.int128_align
|
||||
{
|
||||
pointee_ty
|
||||
} else {
|
||||
pointee_ty.get_aligned(align.bytes())
|
||||
};
|
||||
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
|
||||
let deref = ptr.dereference(self.location).to_rvalue();
|
||||
let loaded_value = function.new_local(
|
||||
self.location,
|
||||
|
|
@ -1105,7 +1119,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
// TODO(antoyo)
|
||||
}
|
||||
|
||||
fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
|
||||
fn store(&mut self, mut val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
|
||||
if self.structs_as_pointer.borrow().contains(&val) {
|
||||
// NOTE: hack to workaround a limitation of the rustc API: see comment on
|
||||
// CodegenCx.structs_as_pointer
|
||||
val = val.dereference(self.location).to_rvalue();
|
||||
}
|
||||
|
||||
self.store_with_flags(val, ptr, align, MemFlags::empty())
|
||||
}
|
||||
|
||||
|
|
@ -1551,16 +1571,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
aggregate_value
|
||||
}
|
||||
|
||||
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
|
||||
fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
let personality = self.rvalue_as_function(_personality);
|
||||
self.current_func().set_personality_function(personality);
|
||||
}
|
||||
self.current_func().set_personality_function(_personality);
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
self.set_personality_fn(pers_fn);
|
||||
|
||||
// NOTE: insert the current block in a variable so that a later call to invoke knows to
|
||||
|
|
@ -1581,7 +1598,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "master"))]
|
||||
fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let value1 = self
|
||||
.current_func()
|
||||
.new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
|
||||
|
|
@ -1591,7 +1608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
(value1, value2)
|
||||
}
|
||||
|
||||
fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) {
|
||||
fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) {
|
||||
// TODO(antoyo): generate the correct landing pad
|
||||
self.cleanup_landing_pad(pers_fn);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,19 +234,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
|||
match cv {
|
||||
Scalar::Int(int) => {
|
||||
let data = int.to_bits(layout.size(self));
|
||||
|
||||
// FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
|
||||
// the paths for floating-point values.
|
||||
// TODO: Remove this code?
|
||||
/*if ty == self.float_type {
|
||||
return self
|
||||
.context
|
||||
.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
|
||||
}
|
||||
if ty == self.double_type {
|
||||
return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
|
||||
}*/
|
||||
|
||||
let value = self.const_uint_big(self.type_ix(bitsize), data);
|
||||
let bytesize = layout.size(self).bytes();
|
||||
if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {
|
||||
|
|
|
|||
|
|
@ -118,14 +118,15 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||
/// A counter that is used for generating local symbol names
|
||||
local_gen_sym_counter: Cell<usize>,
|
||||
|
||||
eh_personality: Cell<Option<RValue<'gcc>>>,
|
||||
eh_personality: Cell<Option<Function<'gcc>>>,
|
||||
#[cfg(feature = "master")]
|
||||
pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
|
||||
|
||||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||
|
||||
/// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such,
|
||||
/// `const_undef()` returns struct as pointer so that they can later be assigned a value.
|
||||
/// `const_undef()` returns struct as pointer so that they can later be assigned a value (in
|
||||
/// e.g. Builder::insert_value).
|
||||
/// As such, this set remembers which of these pointers were returned by this function so that
|
||||
/// they can be dereferenced later.
|
||||
/// FIXME(antoyo): fix the rustc API to avoid having this hack.
|
||||
|
|
@ -155,6 +156,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
|
||||
.unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
// For types with size 1, the alignment can be 1 and only 1
|
||||
// So, we can skip the call to ``get_aligned`.
|
||||
// In the future, we can add a GCC API to query the type align,
|
||||
// and call `get_aligned` if and only if that differs from Rust's expectations.
|
||||
if layout.size.bytes() == 1 {
|
||||
return context.new_c_type(ctype);
|
||||
}
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
context.new_c_type(ctype).get_aligned(align)
|
||||
|
|
@ -373,8 +381,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
|
||||
type Value = RValue<'gcc>;
|
||||
type Metadata = RValue<'gcc>;
|
||||
// TODO(antoyo): change to Function<'gcc>.
|
||||
type Function = RValue<'gcc>;
|
||||
type Function = Function<'gcc>;
|
||||
|
||||
type BasicBlock = Block<'gcc>;
|
||||
type Type = Type<'gcc>;
|
||||
|
|
@ -392,11 +399,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
&self.vtables
|
||||
}
|
||||
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> {
|
||||
let func = get_fn(self, instance);
|
||||
*self.current_func.borrow_mut() = Some(func);
|
||||
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
|
||||
unsafe { std::mem::transmute(func) }
|
||||
func
|
||||
}
|
||||
|
||||
fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
|
|
@ -420,7 +426,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
ptr
|
||||
}
|
||||
|
||||
fn eh_personality(&self) -> RValue<'gcc> {
|
||||
fn eh_personality(&self) -> Function<'gcc> {
|
||||
// The exception handling personality function.
|
||||
//
|
||||
// If our compilation unit has the `eh_personality` lang item somewhere
|
||||
|
|
@ -458,9 +464,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let symbol_name = tcx.symbol_name(instance).name;
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(FunctionType::Extern);
|
||||
let func = self.declare_fn(symbol_name, fn_abi);
|
||||
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
|
||||
func
|
||||
self.declare_fn(symbol_name, fn_abi)
|
||||
}
|
||||
_ => {
|
||||
let name = if wants_msvc_seh(self.sess()) {
|
||||
|
|
@ -468,8 +472,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
} else {
|
||||
"rust_eh_personality"
|
||||
};
|
||||
let func = self.declare_func(name, self.type_i32(), &[], true);
|
||||
unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) }
|
||||
self.declare_func(name, self.type_i32(), &[], true)
|
||||
}
|
||||
};
|
||||
// TODO(antoyo): apply target cpu attributes.
|
||||
|
|
@ -481,11 +484,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
self.tcx.sess
|
||||
}
|
||||
|
||||
fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
|
||||
fn set_frame_pointer_type(&self, _llfn: Function<'gcc>) {
|
||||
// TODO(antoyo)
|
||||
}
|
||||
|
||||
fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) {
|
||||
fn apply_target_cpu_attr(&self, _llfn: Function<'gcc>) {
|
||||
// TODO(antoyo)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use gccjit::{Location, RValue};
|
||||
use gccjit::{Function, Location, RValue};
|
||||
use rustc_abi::Size;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
|
||||
|
|
@ -221,7 +221,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
&self,
|
||||
instance: Instance<'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
llfn: RValue<'gcc>,
|
||||
llfn: Function<'gcc>,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
|
||||
if self.sess().opts.debuginfo == DebugInfo::None {
|
||||
|
|
@ -272,7 +272,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
&self,
|
||||
_instance: Instance<'tcx>,
|
||||
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
_maybe_definition_llfn: Option<RValue<'gcc>>,
|
||||
_maybe_definition_llfn: Option<Function<'gcc>>,
|
||||
) -> Self::DIScope {
|
||||
// TODO(antoyo): implement.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
_fn_type: Type<'gcc>,
|
||||
#[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
|
||||
#[cfg(not(feature = "master"))] callconv: Option<()>,
|
||||
) -> RValue<'gcc> {
|
||||
) -> Function<'gcc> {
|
||||
// TODO(antoyo): use the fn_type parameter.
|
||||
let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
|
||||
let return_type = self.type_i32();
|
||||
|
|
@ -111,8 +111,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
// NOTE: it is needed to set the current_func here as well, because get_fn() is not called
|
||||
// for the main function.
|
||||
*self.current_func.borrow_mut() = Some(func);
|
||||
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
|
||||
unsafe { std::mem::transmute(func) }
|
||||
func
|
||||
}
|
||||
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ mod simd;
|
|||
#[cfg(feature = "master")]
|
||||
use std::iter;
|
||||
|
||||
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::Type;
|
||||
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_abi::{BackendRepr, HasDataLayout};
|
||||
|
|
@ -300,6 +302,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
let fn_args = instance.args;
|
||||
|
||||
let simple = get_simple_intrinsic(self, name);
|
||||
// TODO(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when
|
||||
// it is the symbols for the supported f128 builtins.
|
||||
let simple_func = get_simple_function(self, name)
|
||||
.or_else(|| get_simple_function_f128(self, name))
|
||||
.or_else(|| get_simple_function_f128_2args(self, name));
|
||||
|
|
@ -441,7 +445,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
match int_type_width_signed(args[0].layout.ty, self) {
|
||||
Some((width, signed)) => match name {
|
||||
sym::ctlz | sym::cttz => {
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let func = self.current_func();
|
||||
let then_block = func.new_block("then");
|
||||
let else_block = func.new_block("else");
|
||||
let after_block = func.new_block("after");
|
||||
|
|
@ -1109,7 +1113,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
// for (int counter = 0; value != 0; counter++) {
|
||||
// value &= value - 1;
|
||||
// }
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let func = self.current_func();
|
||||
let loop_head = func.new_block("head");
|
||||
let loop_body = func.new_block("body");
|
||||
let loop_tail = func.new_block("tail");
|
||||
|
|
@ -1188,7 +1192,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let result_type = lhs.get_type();
|
||||
if signed {
|
||||
// Based on algorithm from: https://stackoverflow.com/a/56531252/389119
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let func = self.current_func();
|
||||
let res = func.new_local(self.location, result_type, "saturating_sum");
|
||||
let supports_native_type = self.is_native_int_type(result_type);
|
||||
let overflow = if supports_native_type {
|
||||
|
|
@ -1259,7 +1263,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let result_type = lhs.get_type();
|
||||
if signed {
|
||||
// Based on algorithm from: https://stackoverflow.com/a/56531252/389119
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let func = self.current_func();
|
||||
let res = func.new_local(self.location, result_type, "saturating_diff");
|
||||
let supports_native_type = self.is_native_int_type(result_type);
|
||||
let overflow = if supports_native_type {
|
||||
|
|
@ -1483,10 +1487,9 @@ fn gen_fn<'a, 'gcc, 'tcx>(
|
|||
// FIXME(eddyb) find a nicer way to do this.
|
||||
cx.linkage.set(FunctionType::Internal);
|
||||
let func = cx.declare_fn(name, fn_abi);
|
||||
let func_val = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) };
|
||||
cx.set_frame_pointer_type(func_val);
|
||||
cx.apply_target_cpu_attr(func_val);
|
||||
let block = Builder::append_block(cx, func_val, "entry-block");
|
||||
cx.set_frame_pointer_type(func);
|
||||
cx.apply_target_cpu_attr(func);
|
||||
let block = Builder::append_block(cx, func, "entry-block");
|
||||
let bx = Builder::build(cx, block);
|
||||
codegen(bx);
|
||||
(return_type, func)
|
||||
|
|
|
|||
|
|
@ -780,6 +780,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
sym::simd_fsin => "sin",
|
||||
sym::simd_fsqrt => "sqrt",
|
||||
sym::simd_round => "round",
|
||||
sym::simd_round_ties_even => "rint",
|
||||
sym::simd_trunc => "trunc",
|
||||
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
|
||||
};
|
||||
|
|
@ -827,6 +828,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
| sym::simd_fsin
|
||||
| sym::simd_fsqrt
|
||||
| sym::simd_round
|
||||
| sym::simd_round_ties_even
|
||||
| sym::simd_trunc
|
||||
) {
|
||||
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ tests/ui/iterators/iter-sum-overflow-debug.rs
|
|||
tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
|
||||
tests/ui/mir/mir_drop_order.rs
|
||||
tests/ui/mir/mir_let_chains_drop_order.rs
|
||||
tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
|
||||
tests/ui/oom_unwind.rs
|
||||
tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
|
||||
tests/ui/panic-runtime/abort.rs
|
||||
|
|
|
|||
|
|
@ -1537,6 +1537,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
sym::simd_fsin => "llvm.sin",
|
||||
sym::simd_fsqrt => "llvm.sqrt",
|
||||
sym::simd_round => "llvm.round",
|
||||
sym::simd_round_ties_even => "llvm.rint",
|
||||
sym::simd_trunc => "llvm.trunc",
|
||||
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
|
||||
};
|
||||
|
|
@ -1563,6 +1564,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
| sym::simd_fsqrt
|
||||
| sym::simd_relaxed_fma
|
||||
| sym::simd_round
|
||||
| sym::simd_round_ties_even
|
||||
| sym::simd_trunc
|
||||
) {
|
||||
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
|
||||
|
|
@ -2309,7 +2311,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// Unary integer intrinsics
|
||||
if matches!(
|
||||
name,
|
||||
sym::simd_bswap | sym::simd_bitreverse | sym::simd_ctlz | sym::simd_ctpop | sym::simd_cttz
|
||||
sym::simd_bswap
|
||||
| sym::simd_bitreverse
|
||||
| sym::simd_ctlz
|
||||
| sym::simd_ctpop
|
||||
| sym::simd_cttz
|
||||
| sym::simd_funnel_shl
|
||||
| sym::simd_funnel_shr
|
||||
) {
|
||||
let vec_ty = bx.cx.type_vector(
|
||||
match *in_elem.kind() {
|
||||
|
|
@ -2330,6 +2338,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
sym::simd_ctlz => "llvm.ctlz",
|
||||
sym::simd_ctpop => "llvm.ctpop",
|
||||
sym::simd_cttz => "llvm.cttz",
|
||||
sym::simd_funnel_shl => "llvm.fshl",
|
||||
sym::simd_funnel_shr => "llvm.fshr",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let int_size = in_elem.int_size_and_signed(bx.tcx()).0.bits();
|
||||
|
|
@ -2350,6 +2360,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// simple unary argument cases
|
||||
Ok(bx.call_intrinsic(llvm_intrinsic, &[vec_ty], &[args[0].immediate()]))
|
||||
}
|
||||
sym::simd_funnel_shl | sym::simd_funnel_shr => Ok(bx.call_intrinsic(
|
||||
llvm_intrinsic,
|
||||
&[vec_ty],
|
||||
&[args[0].immediate(), args[1].immediate(), args[2].immediate()],
|
||||
)),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1870,8 +1870,13 @@ pub(crate) fn linked_symbols(
|
|||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib | CrateType::Sdylib => (),
|
||||
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => {
|
||||
CrateType::Executable
|
||||
| CrateType::ProcMacro
|
||||
| CrateType::Cdylib
|
||||
| CrateType::Dylib
|
||||
| CrateType::Sdylib => (),
|
||||
CrateType::Staticlib | CrateType::Rlib => {
|
||||
// These are not linked, so no need to generate symbols.o for them.
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
}
|
||||
AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
|
||||
AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align),
|
||||
AttributeKind::LinkName { name, .. } => codegen_fn_attrs.link_name = Some(*name),
|
||||
AttributeKind::NoMangle(attr_span) => {
|
||||
if tcx.opt_item_name(did.to_def_id()).is_some() {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
|
|
@ -262,7 +263,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
}
|
||||
}
|
||||
}
|
||||
sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
|
||||
sym::link_ordinal => {
|
||||
link_ordinal_span = Some(attr.span());
|
||||
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
||||
|
|
|
|||
|
|
@ -479,17 +479,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
_ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)),
|
||||
};
|
||||
|
||||
// Layout ensures that we only get here for cases where the discriminant
|
||||
// `layout_sanity_check` ensures that we only get here for cases where the discriminant
|
||||
// value and the variant index match, since that's all `Niche` can encode.
|
||||
// But for emphasis and debugging, let's double-check one anyway.
|
||||
debug_assert_eq!(
|
||||
self.layout
|
||||
.ty
|
||||
.discriminant_for_variant(bx.tcx(), untagged_variant)
|
||||
.unwrap()
|
||||
.val,
|
||||
u128::from(untagged_variant.as_u32()),
|
||||
);
|
||||
|
||||
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#![doc(rust_logo)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ declare_features! (
|
|||
(accepted, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
|
||||
/// Allows `'a: { break 'a; }`.
|
||||
(accepted, label_break_value, "1.65.0", Some(48594)),
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
(accepted, let_chains, "1.88.0", Some(53667)),
|
||||
/// Allows `let...else` statements.
|
||||
(accepted, let_else, "1.65.0", Some(87335)),
|
||||
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
|
||||
|
|
@ -341,7 +343,7 @@ declare_features! (
|
|||
(accepted, pattern_parentheses, "1.31.0", Some(51087)),
|
||||
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
|
||||
(accepted, precise_capturing, "1.82.0", Some(123432)),
|
||||
/// Allows `use<..>` precise capturign on impl Trait in traits.
|
||||
/// Allows `use<..>` precise capturing on impl Trait in traits.
|
||||
(accepted, precise_capturing_in_traits, "1.87.0", Some(130044)),
|
||||
/// Allows procedural macros in `proc-macro` crates.
|
||||
(accepted, proc_macro, "1.29.0", Some(38356)),
|
||||
|
|
@ -388,7 +390,7 @@ declare_features! (
|
|||
(accepted, self_struct_ctor, "1.32.0", Some(51994)),
|
||||
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
|
||||
(accepted, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
|
||||
/// Shortern the tail expression lifetime
|
||||
/// Shorten the tail expression lifetime
|
||||
(accepted, shorter_tail_lifetimes, "1.84.0", Some(123739)),
|
||||
/// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
|
||||
(accepted, slice_patterns, "1.42.0", Some(62254)),
|
||||
|
|
|
|||
|
|
@ -552,8 +552,6 @@ declare_features! (
|
|||
(unstable, large_assignments, "1.52.0", Some(83518)),
|
||||
/// Allow to have type alias types for inter-crate use.
|
||||
(incomplete, lazy_type_alias, "1.72.0", Some(112792)),
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
(unstable, let_chains, "1.37.0", Some(53667)),
|
||||
/// Allows using `#[link(kind = "link-arg", name = "...")]`
|
||||
/// to pass custom arguments to the linker.
|
||||
(unstable, link_arg_attribute, "1.76.0", Some(99427)),
|
||||
|
|
|
|||
|
|
@ -594,8 +594,9 @@ pub(crate) fn check_intrinsic_type(
|
|||
| sym::simd_ceil
|
||||
| sym::simd_floor
|
||||
| sym::simd_round
|
||||
| sym::simd_round_ties_even
|
||||
| sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
|
||||
sym::simd_fma | sym::simd_relaxed_fma => {
|
||||
sym::simd_fma | sym::simd_relaxed_fma | sym::simd_funnel_shl | sym::simd_funnel_shr => {
|
||||
(1, 0, vec![param(0), param(0), param(0)], param(0))
|
||||
}
|
||||
sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ This API is completely unstable and subject to change.
|
|||
#![feature(debug_closure_helpers)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_abi::FIRST_VARIANT;
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -6,7 +7,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt};
|
||||
use rustc_session::declare_lint;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub};
|
||||
|
|
@ -182,7 +183,11 @@ fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> SymbolName {
|
|||
// information, we could have codegen_fn_attrs also give span information back for
|
||||
// where the attribute was defined. However, until this is found to be a
|
||||
// bottleneck, this does just fine.
|
||||
(overridden_link_name, tcx.get_attr(fi, sym::link_name).unwrap().span())
|
||||
(
|
||||
overridden_link_name,
|
||||
find_attr!(tcx.get_all_attrs(fi), AttributeKind::LinkName {span, ..} => *span)
|
||||
.unwrap(),
|
||||
)
|
||||
})
|
||||
{
|
||||
SymbolName::Link(overridden_link_name, overridden_link_name_span)
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
let mut op_warned = false;
|
||||
|
||||
if let Some(must_use_op) = must_use_op {
|
||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||
cx.emit_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
expr.span,
|
||||
|
|
@ -191,11 +192,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
label: expr.span,
|
||||
suggestion: if expr_is_from_block {
|
||||
UnusedOpSuggestion::BlockTailExpr {
|
||||
before_span: expr.span.shrink_to_lo(),
|
||||
after_span: expr.span.shrink_to_hi(),
|
||||
before_span: span.shrink_to_lo(),
|
||||
after_span: span.shrink_to_hi(),
|
||||
}
|
||||
} else {
|
||||
UnusedOpSuggestion::NormalExpr { span: expr.span.shrink_to_lo() }
|
||||
UnusedOpSuggestion::NormalExpr { span: span.shrink_to_lo() }
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
@ -508,9 +509,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
);
|
||||
}
|
||||
MustUsePath::Def(span, def_id, reason) => {
|
||||
let span = span.find_oldest_ancestor_in_same_ctxt();
|
||||
cx.emit_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
*span,
|
||||
span,
|
||||
UnusedDef {
|
||||
pre: descr_pre,
|
||||
post: descr_post,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#![feature(file_buffered)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
|
|
|
|||
|
|
@ -284,15 +284,15 @@ pub enum FakeBorrowKind {
|
|||
///
|
||||
/// This is used when lowering deref patterns, where shallow borrows wouldn't prevent something
|
||||
/// like:
|
||||
// ```compile_fail
|
||||
// let mut b = Box::new(false);
|
||||
// match b {
|
||||
// deref!(true) => {} // not reached because `*b == false`
|
||||
// _ if { *b = true; false } => {} // not reached because the guard is `false`
|
||||
// deref!(false) => {} // not reached because the guard changed it
|
||||
// // UB because we reached the unreachable.
|
||||
// }
|
||||
// ```
|
||||
/// ```compile_fail
|
||||
/// let mut b = Box::new(false);
|
||||
/// match b {
|
||||
/// deref!(true) => {} // not reached because `*b == false`
|
||||
/// _ if { *b = true; false } => {} // not reached because the guard is `false`
|
||||
/// deref!(false) => {} // not reached because the guard changed it
|
||||
/// // UB because we reached the unreachable.
|
||||
/// }
|
||||
/// ```
|
||||
Deep,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -512,6 +512,8 @@ parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
|
|||
parse_left_arrow_operator = unexpected token: `<-`
|
||||
.suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
|
||||
|
||||
parse_let_chain_pre_2024 = let chains are only allowed in Rust 2024 or later
|
||||
|
||||
parse_lifetime_after_mut = lifetime must precede `mut`
|
||||
.suggestion = place the lifetime before `mut`
|
||||
|
||||
|
|
|
|||
|
|
@ -1778,6 +1778,13 @@ pub(crate) struct AsyncBoundModifierIn2015 {
|
|||
pub help: HelpUseLatestEdition,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_let_chain_pre_2024)]
|
||||
pub(crate) struct LetChainPre2024 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_self_argument_pointer)]
|
||||
pub(crate) struct SelfArgumentPointer {
|
||||
|
|
|
|||
|
|
@ -4117,7 +4117,7 @@ impl MutVisitor for CondChecker<'_> {
|
|||
LetChainsPolicy::AlwaysAllowed => (),
|
||||
LetChainsPolicy::EditionDependent { current_edition } => {
|
||||
if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() {
|
||||
self.parser.psess.gated_spans.gate(sym::let_chains, span);
|
||||
self.parser.dcx().emit_err(errors::LetChainPre2024 { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1071,7 +1071,7 @@ impl<'a> Parser<'a> {
|
|||
&& self.look_ahead(1, |t| t.is_keyword(kw::Const))
|
||||
&& self.look_ahead(2, |t| *t == token::CloseBracket)
|
||||
{
|
||||
let start = self.prev_token.span;
|
||||
let start = self.token.span;
|
||||
self.bump();
|
||||
self.expect_keyword(exp!(Const)).unwrap();
|
||||
self.bump();
|
||||
|
|
|
|||
|
|
@ -302,6 +302,7 @@ fn emit_malformed_attribute(
|
|||
| sym::no_mangle
|
||||
| sym::must_use
|
||||
| sym::track_caller
|
||||
| sym::link_name
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,6 +191,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
|
||||
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => {
|
||||
self.check_link_name(hir_id, *attr_span, *name, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
|
||||
self.check_may_dangle(hir_id, *attr_span)
|
||||
}
|
||||
|
|
@ -283,7 +286,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target),
|
||||
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
|
||||
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
|
||||
[sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
|
||||
[sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target),
|
||||
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
|
||||
self.check_macro_use(hir_id, attr, target)
|
||||
|
|
@ -1604,7 +1606,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
|
||||
fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
|
||||
fn check_link_name(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr_span: Span,
|
||||
name: Symbol,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) {
|
||||
match target {
|
||||
Target::ForeignFn | Target::ForeignStatic => {}
|
||||
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
|
||||
|
|
@ -1612,27 +1621,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
// erroneously allowed it and some crates used it accidentally, to be compatible
|
||||
// with crates depending on them, we can't throw an error here.
|
||||
Target::Field | Target::Arm | Target::MacroDef => {
|
||||
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_name");
|
||||
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_name");
|
||||
}
|
||||
_ => {
|
||||
// FIXME: #[cold] was previously allowed on non-functions/statics and some crates
|
||||
// FIXME: #[link_name] was previously allowed on non-functions/statics and some crates
|
||||
// used this, so only emit a warning.
|
||||
let attr_span = matches!(target, Target::ForeignMod).then_some(attr.span());
|
||||
if let Some(s) = attr.value_str() {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::LinkName { span, attr_span, value: s.as_str() },
|
||||
);
|
||||
} else {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::LinkName { span, attr_span, value: "..." },
|
||||
);
|
||||
};
|
||||
let help_span = matches!(target, Target::ForeignMod).then_some(attr_span);
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr_span,
|
||||
errors::LinkName { span, help_span, value: name.as_str() },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ pub(crate) struct Link {
|
|||
#[warning]
|
||||
pub(crate) struct LinkName<'a> {
|
||||
#[help]
|
||||
pub attr_span: Option<Span>,
|
||||
pub help_span: Option<Span>,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub value: &'a str,
|
||||
|
|
|
|||
|
|
@ -174,7 +174,14 @@ pub(crate) struct ImportData<'ra> {
|
|||
|
||||
pub parent_scope: ParentScope<'ra>,
|
||||
pub module_path: Vec<Segment>,
|
||||
/// The resolution of `module_path`.
|
||||
/// The resolution of `module_path`:
|
||||
///
|
||||
/// | `module_path` | `imported_module` | remark |
|
||||
/// |-|-|-|
|
||||
/// |`use prefix::foo`| `ModuleOrUniformRoot::Module(prefix)` | - |
|
||||
/// |`use ::foo` | `ModuleOrUniformRoot::ExternPrelude` | 2018+ editions |
|
||||
/// |`use ::foo` | `ModuleOrUniformRoot::CrateRootAndExternPrelude` | a special case in 2015 edition |
|
||||
/// |`use foo` | `ModuleOrUniformRoot::CurrentScope` | - |
|
||||
pub imported_module: Cell<Option<ModuleOrUniformRoot<'ra>>>,
|
||||
pub vis: ty::Visibility,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1977,6 +1977,8 @@ symbols! {
|
|||
simd_fmin,
|
||||
simd_fsin,
|
||||
simd_fsqrt,
|
||||
simd_funnel_shl,
|
||||
simd_funnel_shr,
|
||||
simd_gather,
|
||||
simd_ge,
|
||||
simd_gt,
|
||||
|
|
@ -2004,6 +2006,7 @@ symbols! {
|
|||
simd_relaxed_fma,
|
||||
simd_rem,
|
||||
simd_round,
|
||||
simd_round_ties_even,
|
||||
simd_saturating_add,
|
||||
simd_saturating_sub,
|
||||
simd_scatter,
|
||||
|
|
|
|||
|
|
@ -277,6 +277,12 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
if !variant.is_uninhabited() {
|
||||
assert!(idx == *untagged_variant || niche_variants.contains(&idx));
|
||||
}
|
||||
|
||||
// Ensure that for niche encoded tags the discriminant coincides with the variant index.
|
||||
assert_eq!(
|
||||
layout.ty.discriminant_for_variant(tcx, idx).unwrap().val,
|
||||
u128::from(idx.as_u32()),
|
||||
);
|
||||
}
|
||||
}
|
||||
for variant in variants.iter() {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,40 @@ pub unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
|
|||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Funnel Shifts vector left elementwise, with UB on overflow.
|
||||
///
|
||||
/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
|
||||
/// creating a vector of the same length, but with each element being twice as
|
||||
/// wide. Then shift this vector left elementwise by `shift`, shifting in zeros,
|
||||
/// and extract the most significant half of each of the elements. If `a` and `b`
|
||||
/// are the same, this is equivalent to an elementwise rotate left operation.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Each element of `shift` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
|
||||
|
||||
/// Funnel Shifts vector right elementwise, with UB on overflow.
|
||||
///
|
||||
/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
|
||||
/// creating a vector of the same length, but with each element being twice as
|
||||
/// wide. Then shift this vector right elementwise by `shift`, shifting in zeros,
|
||||
/// and extract the least significant half of each of the elements. If `a` and `b`
|
||||
/// are the same, this is equivalent to an elementwise rotate right operation.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Each element of `shift` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
|
||||
|
||||
/// "Ands" vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
|
|
@ -678,6 +712,14 @@ pub unsafe fn simd_floor<T>(x: T) -> T;
|
|||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_round<T>(x: T) -> T;
|
||||
|
||||
/// Rounds each element to the closest integer-valued float.
|
||||
/// Ties are resolved by rounding to the number with an even least significant digit
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_round_ties_even<T>(x: T) -> T;
|
||||
|
||||
/// Returns the integer part of each element as an integer-valued float.
|
||||
/// In other words, non-integer values are truncated towards zero.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -408,24 +408,22 @@ pub trait OpenOptionsExt {
|
|||
/// Pass custom flags to the `flags` argument of `open`.
|
||||
///
|
||||
/// The bits that define the access mode are masked out with `O_ACCMODE`, to
|
||||
/// ensure they do not interfere with the access mode set by Rusts options.
|
||||
/// ensure they do not interfere with the access mode set by Rust's options.
|
||||
///
|
||||
/// Custom flags can only set flags, not remove flags set by Rusts options.
|
||||
/// This options overwrites any previously set custom flags.
|
||||
/// Custom flags can only set flags, not remove flags set by Rust's options.
|
||||
/// This function overwrites any previously-set custom flags.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![feature(rustc_private)]
|
||||
/// # mod libc { pub const O_NOFOLLOW: i32 = 0; }
|
||||
/// use std::fs::OpenOptions;
|
||||
/// use std::os::unix::fs::OpenOptionsExt;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut options = OpenOptions::new();
|
||||
/// options.write(true);
|
||||
/// if cfg!(unix) {
|
||||
/// options.custom_flags(libc::O_NOFOLLOW);
|
||||
/// }
|
||||
/// options.custom_flags(libc::O_NOFOLLOW);
|
||||
/// let file = options.open("foo.txt");
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -330,4 +330,105 @@ $
|
|||
|
||||
This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
|
||||
compiling your dependencies, so that if they have any warnings, they do not
|
||||
pollute the output of your build.
|
||||
pollute the output of your build. However, note that `--cap-lints allow` does **not** override lints marked as `force-warn`.
|
||||
|
||||
## Priority of lint level sources
|
||||
|
||||
Rust allows setting lint levels (`allow`, `warn`, `deny`, `forbid`, `force-warn`) through various sources:
|
||||
|
||||
- **Attributes**: `#[allow(...)]`, `#![deny(...)]`, etc.
|
||||
- **Command-line options**: `--cap-lints`, `--force-warn`, `-A`, `-W`, `-D`, `-F`
|
||||
|
||||
Here’s how these different lint controls interact:
|
||||
|
||||
1. [`--force-warn`](#force-warn) forces a lint to warning level, and takes precedence over attributes and all other CLI flags.
|
||||
|
||||
```rust,compile_fail
|
||||
#[forbid(unused_variables)]
|
||||
fn main() {
|
||||
let x = 42;
|
||||
}
|
||||
```
|
||||
|
||||
Compiled with:
|
||||
|
||||
```bash
|
||||
$ rustc --force-warn unused_variables lib.rs
|
||||
warning: unused variable: `x`
|
||||
--> lib.rs:3:9
|
||||
|
|
||||
3 | let x = 42;
|
||||
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
||||
|
|
||||
= note: requested on the command line with `--force-warn unused-variables`
|
||||
|
||||
warning: 1 warning emitted
|
||||
```
|
||||
|
||||
2. [`--cap-lints`](#capping-lints) sets the maximum level of a lint, and takes precedence over attributes as well as the `-D`, `-W`, and `-F` CLI flags.
|
||||
|
||||
```rust,compile_fail
|
||||
#[deny(unused_variables)]
|
||||
fn main() {
|
||||
let x = 42;
|
||||
}
|
||||
```
|
||||
|
||||
Compiled with:
|
||||
|
||||
```bash
|
||||
$ rustc --cap-lints=warn lib.rs
|
||||
warning: unused variable: `x`
|
||||
--> test1.rs:3:9
|
||||
|
|
||||
3 | let x = 42;
|
||||
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> test1.rs:1:8
|
||||
|
|
||||
1 | #[deny(unused_variables)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 1 warning emitted
|
||||
```
|
||||
|
||||
3. [CLI level flags](#via-compiler-flag) take precedence over attributes.
|
||||
|
||||
The order of the flags matter; flags on the right take precedence over earlier flags.
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let x = 42;
|
||||
}
|
||||
```
|
||||
|
||||
Compiled with:
|
||||
|
||||
```bash
|
||||
$ rustc -A unused_variables -D unused_variables lib.rs
|
||||
error: unused variable: `x`
|
||||
--> test1.rs:2:9
|
||||
|
|
||||
2 | let x = 42;
|
||||
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
||||
|
|
||||
= note: requested on the command line with `-D unused-variables`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
```
|
||||
|
||||
4. Within the source, [attributes](#via-an-attribute) at a lower-level in the syntax tree take precedence over attributes at a higher level, or from a previous attribute on the same entity as listed in left-to-right source order.
|
||||
|
||||
```rust
|
||||
#![deny(unused_variables)]
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn main() {
|
||||
let x = 42; // Allow wins
|
||||
}
|
||||
```
|
||||
|
||||
- The exception is once a lint is set to "forbid", it is an error to try to change its level except for `deny`, which is allowed inside a forbid context, but is ignored.
|
||||
|
||||
In terms of priority, [lint groups](groups.md) are treated as-if they are expanded to a list of all of the lints they contain. The exception is the `warnings` group which ignores attribute and CLI order and applies to all lints that would otherwise warn within the entity.
|
||||
|
|
|
|||
|
|
@ -8,23 +8,25 @@ build = "build.rs"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
|
||||
base64 = "0.21.7"
|
||||
itertools = "0.12"
|
||||
indexmap = "2"
|
||||
itertools = "0.12"
|
||||
minifier = { version = "0.3.5", default-features = false }
|
||||
pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
|
||||
regex = "1"
|
||||
rustdoc-json-types = { path = "../rustdoc-json-types" }
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
smallvec = "1.8.1"
|
||||
tempfile = "3"
|
||||
threadpool = "1.8.1"
|
||||
tracing = "0.1"
|
||||
tracing-tree = "0.3.0"
|
||||
threadpool = "1.8.1"
|
||||
unicode-segmentation = "1.9"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[dependencies.tracing-subscriber]
|
||||
version = "0.3.3"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// tidy-alphabetical-start
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
html_playground_url = "https://play.rust-lang.org/"
|
||||
)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(ascii_char_variants)]
|
||||
#![feature(assert_matches)]
|
||||
|
|
@ -11,18 +11,12 @@
|
|||
#![feature(file_buffered)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(never_type)]
|
||||
#![feature(round_char_boundary)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(test)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(type_ascription)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rustc::internal)]
|
||||
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
extern crate thin_vec;
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
8141c2265f5f2b26d89abe8df5fa67286f2425d4
|
||||
ed2d759783dc9de134bbb3f01085b1e6dbf539f3
|
||||
|
|
|
|||
|
|
@ -227,8 +227,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
|
|||
} else {
|
||||
let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, &config, None)
|
||||
.unwrap_or_else(|| {
|
||||
#[cfg(target_os = "linux")]
|
||||
miri::native_lib::register_retcode_sv(rustc_driver::EXIT_FAILURE);
|
||||
//#[cfg(target_os = "linux")]
|
||||
//miri::native_lib::register_retcode_sv(rustc_driver::EXIT_FAILURE);
|
||||
tcx.dcx().abort_if_errors();
|
||||
rustc_driver::EXIT_FAILURE
|
||||
});
|
||||
|
|
@ -804,7 +804,7 @@ fn main() {
|
|||
// thread in an async-signal-unsafe way such as by accessing shared
|
||||
// semaphores, etc.; the handler only calls `sleep()` and `exit()`, which
|
||||
// are async-signal-safe, as is accessing atomics
|
||||
let _ = unsafe { miri::native_lib::init_sv() };
|
||||
//let _ = unsafe { miri::native_lib::init_sv() };
|
||||
}
|
||||
run_compiler_and_exit(
|
||||
&rustc_args,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
| "ceil"
|
||||
| "floor"
|
||||
| "round"
|
||||
| "round_ties_even"
|
||||
| "trunc"
|
||||
| "fsqrt"
|
||||
| "fsin"
|
||||
|
|
@ -71,6 +72,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"ceil" => Op::Round(rustc_apfloat::Round::TowardPositive),
|
||||
"floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
|
||||
"round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
|
||||
"round_ties_even" => Op::Round(rustc_apfloat::Round::NearestTiesToEven),
|
||||
"trunc" => Op::Round(rustc_apfloat::Round::TowardZero),
|
||||
"ctlz" => Op::Numeric(sym::ctlz),
|
||||
"ctpop" => Op::Numeric(sym::ctpop),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#![feature(variant_count)]
|
||||
#![feature(yeet_expr)]
|
||||
#![feature(nonzero_ops)]
|
||||
#![cfg_attr(bootstrap, feature(nonnull_provenance))]
|
||||
#![feature(strict_overflow_ops)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
#![feature(ptr_metadata)]
|
||||
|
|
@ -99,10 +100,10 @@ pub use rustc_const_eval::interpret::{self, AllocMap, Provenance as _};
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use tracing::{info, trace};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod native_lib {
|
||||
pub use crate::shims::{init_sv, register_retcode_sv};
|
||||
}
|
||||
//#[cfg(target_os = "linux")]
|
||||
//pub mod native_lib {
|
||||
// pub use crate::shims::{init_sv, register_retcode_sv};
|
||||
//}
|
||||
|
||||
// Type aliases that set the provenance parameter.
|
||||
pub type Pointer = interpret::Pointer<Option<machine::Provenance>>;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ pub mod time;
|
|||
pub mod tls;
|
||||
|
||||
pub use self::files::FdTable;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub use self::native_lib::trace::{init_sv, register_retcode_sv};
|
||||
//#[cfg(target_os = "linux")]
|
||||
//pub use self::native_lib::trace::{init_sv, register_retcode_sv};
|
||||
pub use self::unix::{DirTable, EpollInterestTable};
|
||||
|
||||
/// What needs to be done after emulating an item (a shim or an intrinsic) is done.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
//! Implements calling functions from a native library.
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod trace;
|
||||
// FIXME: disabled since it fails to build on many targets.
|
||||
//#[cfg(target_os = "linux")]
|
||||
//pub mod trace;
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
|
|
@ -12,13 +13,13 @@ use rustc_middle::mir::interpret::Pointer;
|
|||
use rustc_middle::ty::{self as ty, IntTy, UintTy};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use self::trace::Supervisor;
|
||||
//#[cfg(target_os = "linux")]
|
||||
//use self::trace::Supervisor;
|
||||
use crate::*;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
//#[cfg(target_os = "linux")]
|
||||
//type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>;
|
||||
//#[cfg(not(target_os = "linux"))]
|
||||
type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<!>)>;
|
||||
|
||||
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
|
||||
|
|
@ -32,12 +33,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
libffi_args: Vec<libffi::high::Arg<'a>>,
|
||||
) -> CallResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
#[cfg(target_os = "linux")]
|
||||
let alloc = this.machine.allocator.as_ref().unwrap();
|
||||
//#[cfg(target_os = "linux")]
|
||||
//let alloc = this.machine.allocator.as_ref().unwrap();
|
||||
|
||||
// SAFETY: We don't touch the machine memory past this point.
|
||||
#[cfg(target_os = "linux")]
|
||||
let (guard, stack_ptr) = unsafe { Supervisor::start_ffi(alloc) };
|
||||
//#[cfg(target_os = "linux")]
|
||||
//let (guard, stack_ptr) = unsafe { Supervisor::start_ffi(alloc) };
|
||||
|
||||
// Call the function (`ptr`) with arguments `libffi_args`, and obtain the return value
|
||||
// as the specified primitive integer type
|
||||
|
|
@ -111,9 +112,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// SAFETY: We got the guard and stack pointer from start_ffi, and
|
||||
// the allocator is the same
|
||||
#[cfg(target_os = "linux")]
|
||||
let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) };
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
//#[cfg(target_os = "linux")]
|
||||
//let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) };
|
||||
//#[cfg(not(target_os = "linux"))]
|
||||
let events = None;
|
||||
|
||||
interp_ok((res?, events))
|
||||
|
|
@ -213,9 +214,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
if !this.machine.native_call_mem_warned.replace(true) {
|
||||
// Newly set, so first time we get here.
|
||||
this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem {
|
||||
#[cfg(target_os = "linux")]
|
||||
tracing: self::trace::Supervisor::is_enabled(),
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
//#[cfg(target_os = "linux")]
|
||||
//tracing: self::trace::Supervisor::is_enabled(),
|
||||
//#[cfg(not(target_os = "linux"))]
|
||||
tracing: false,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,14 +20,11 @@ const ARCH_MAX_ACCESS_SIZE: usize = 64;
|
|||
/// The largest arm64 simd instruction operates on 16 bytes.
|
||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||
const ARCH_MAX_ACCESS_SIZE: usize = 16;
|
||||
/// The max riscv vector instruction can access 8 consecutive 32-bit values.
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
const ARCH_MAX_ACCESS_SIZE: usize = 32;
|
||||
|
||||
/// The default word size on a given platform, in bytes.
|
||||
#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "riscv32"))]
|
||||
#[cfg(any(target_arch = "x86", target_arch = "arm"))]
|
||||
const ARCH_WORD_SIZE: usize = 4;
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))]
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
const ARCH_WORD_SIZE: usize = 8;
|
||||
|
||||
/// The address of the page set to be edited, initialised to a sentinel null
|
||||
|
|
@ -91,18 +88,6 @@ impl ArchIndependentRegs for libc::user_regs_struct {
|
|||
fn set_sp(&mut self, sp: usize) { self.sp = sp as _ }
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
#[expect(clippy::as_conversions)]
|
||||
#[rustfmt::skip]
|
||||
impl ArchIndependentRegs for libc::user_regs_struct {
|
||||
#[inline]
|
||||
fn ip(&self) -> usize { self.pc as _ }
|
||||
#[inline]
|
||||
fn set_ip(&mut self, ip: usize) { self.pc = ip as _ }
|
||||
#[inline]
|
||||
fn set_sp(&mut self, sp: usize) { self.sp = sp as _ }
|
||||
}
|
||||
|
||||
/// A unified event representing something happening on the child process. Wraps
|
||||
/// `nix`'s `WaitStatus` and our custom signals so it can all be done with one
|
||||
/// `match` statement.
|
||||
|
|
@ -341,10 +326,6 @@ fn get_disasm() -> capstone::Capstone {
|
|||
{cs_pre.arm64().mode(arch::arm64::ArchMode::Arm)}
|
||||
#[cfg(target_arch = "arm")]
|
||||
{cs_pre.arm().mode(arch::arm::ArchMode::Arm)}
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{cs_pre.riscv().mode(arch::riscv::ArchMode::RiscV64)}
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
{cs_pre.riscv().mode(arch::riscv::ArchMode::RiscV32)}
|
||||
}
|
||||
.detail(true)
|
||||
.build()
|
||||
|
|
@ -501,18 +482,6 @@ fn handle_segfault(
|
|||
}
|
||||
_ => (),
|
||||
},
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
arch::ArchOperand::RiscVOperand(risc_voperand) => {
|
||||
match risc_voperand {
|
||||
arch::riscv::RiscVOperand::Mem(_) => {
|
||||
// We get basically no info here.
|
||||
let push = addr..addr.strict_add(size);
|
||||
acc_events.push(AccessEvent::Read(push.clone()));
|
||||
acc_events.push(AccessEvent::Write(push));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -569,6 +569,10 @@ fn simd_round() {
|
|||
f32x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
|
||||
f32x4::from_array([1.0, 1.0, 2.0, -5.0])
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { intrinsics::simd_round_ties_even(f32x4::from_array([0.9, 1.001, 2.0, -4.5])) },
|
||||
f32x4::from_array([1.0, 1.0, 2.0, -4.0])
|
||||
);
|
||||
assert_eq!(
|
||||
f32x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
|
||||
f32x4::from_array([0.0, 1.0, 2.0, -4.0])
|
||||
|
|
@ -586,6 +590,10 @@ fn simd_round() {
|
|||
f64x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
|
||||
f64x4::from_array([1.0, 1.0, 2.0, -5.0])
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { intrinsics::simd_round_ties_even(f64x4::from_array([0.9, 1.001, 2.0, -4.5])) },
|
||||
f64x4::from_array([1.0, 1.0, 2.0, -4.0])
|
||||
);
|
||||
assert_eq!(
|
||||
f64x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
|
||||
f64x4::from_array([0.0, 1.0, 2.0, -4.0])
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// rustfmt-edition: 2024
|
||||
|
||||
fn main() {
|
||||
if let x = x && x {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// rustfmt-edition: 2024
|
||||
|
||||
fn main() {
|
||||
if let x = x
|
||||
&& x
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
LL| |#![feature(coverage_attribute, let_chains)]
|
||||
LL| |//@ edition: 2021
|
||||
LL| |#![feature(coverage_attribute)]
|
||||
LL| |//@ edition: 2024
|
||||
LL| |//@ compile-flags: -Zcoverage-options=branch
|
||||
LL| |//@ llvm-cov-flags: --show-branches=count
|
||||
LL| |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#![feature(coverage_attribute, let_chains)]
|
||||
//@ edition: 2021
|
||||
#![feature(coverage_attribute)]
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Zcoverage-options=branch
|
||||
//@ llvm-cov-flags: --show-branches=count
|
||||
|
||||
|
|
|
|||
4
tests/run-make/used-proc-macro/dep.rs
Normal file
4
tests/run-make/used-proc-macro/dep.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#![crate_type = "lib"]
|
||||
|
||||
#[used]
|
||||
static VERY_IMPORTANT_SYMBOL: u32 = 12345;
|
||||
3
tests/run-make/used-proc-macro/proc_macro.rs
Normal file
3
tests/run-make/used-proc-macro/proc_macro.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate dep as _;
|
||||
18
tests/run-make/used-proc-macro/rmake.rs
Normal file
18
tests/run-make/used-proc-macro/rmake.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Test that #[used] statics are included in the final dylib for proc-macros too.
|
||||
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-windows llvm-readobj --all doesn't show local symbols on Windows
|
||||
//@ needs-crate-type: proc-macro
|
||||
//@ ignore-musl (FIXME: can't find `-lunwind`)
|
||||
|
||||
use run_make_support::{dynamic_lib_name, llvm_readobj, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("dep.rs").run();
|
||||
rustc().input("proc_macro.rs").run();
|
||||
llvm_readobj()
|
||||
.input(dynamic_lib_name("proc_macro"))
|
||||
.arg("--all")
|
||||
.run()
|
||||
.assert_stdout_contains("VERY_IMPORTANT_SYMBOL");
|
||||
}
|
||||
23
tests/rustdoc/intra-doc/deps.rs
Normal file
23
tests/rustdoc/intra-doc/deps.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Checks that links to crates are correctly generated and only existing crates
|
||||
// have a link generated.
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/137857>.
|
||||
|
||||
//@ compile-flags: --document-private-items -Z unstable-options
|
||||
//@ compile-flags: --extern-html-root-url=empty=https://empty.example/
|
||||
// This one is to ensure that we don't link to any item we see which has
|
||||
// an external html root URL unless it actually exists.
|
||||
//@ compile-flags: --extern-html-root-url=non_existant=https://non-existant.example/
|
||||
//@ aux-build: empty.rs
|
||||
|
||||
#![crate_name = "foo"]
|
||||
#![expect(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//a[@href="https://empty.example/empty/index.html"]' 'empty'
|
||||
// There should only be one intra doc links, we should not link `non_existant`.
|
||||
//@ count - '//*[@class="docblock"]//a' 1
|
||||
//! [`empty`]
|
||||
//!
|
||||
//! [`non_existant`]
|
||||
|
||||
extern crate empty;
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
//! Check that the default global Rust allocator produces non-null Box allocations for ZSTs.
|
||||
//!
|
||||
//! See https://github.com/rust-lang/rust/issues/11998
|
||||
|
||||
//@ run-pass
|
||||
|
||||
pub fn main() {
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
//! Regression test for issue #22077
|
||||
//! lifetime parameters must be constrained in associated type definitions
|
||||
|
||||
trait Fun {
|
||||
type Output;
|
||||
fn call<'x>(&'x self) -> Self::Output;
|
||||
}
|
||||
|
||||
struct Holder {
|
||||
x: String,
|
||||
}
|
||||
|
||||
impl<'a> Fun for Holder {
|
||||
//~^ ERROR E0207
|
||||
type Output = &'a str;
|
||||
fn call<'b>(&'b self) -> &'b str {
|
||||
&self.x[..]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/impl-unused-rps-in-assoc-type.rs:11:6
|
||||
--> $DIR/unconstrained-lifetime-assoc-type.rs:13:6
|
||||
|
|
||||
LL | impl<'a> Fun for Holder {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
//! Test that #[inline] attribute cannot be applied to enum variants
|
||||
|
||||
enum Foo {
|
||||
#[inline]
|
||||
//~^ ERROR attribute should be applied
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/inline-disallow-on-variant.rs:2:5
|
||||
--> $DIR/inline-attribute-enum-variant-error.rs:4:5
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
6
tests/ui/attributes/inline-main.rs
Normal file
6
tests/ui/attributes/inline-main.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//! Test that #[inline(always)] can be applied to main function
|
||||
|
||||
//@ run-pass
|
||||
|
||||
#[inline(always)]
|
||||
fn main() {}
|
||||
|
|
@ -5,145 +5,145 @@ LL | #![feature(const_fn_trait_ref_impls)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:14:6
|
||||
--> $DIR/fn_trait_refs.rs:14:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:14:6
|
||||
--> $DIR/fn_trait_refs.rs:14:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:14:6
|
||||
--> $DIR/fn_trait_refs.rs:14:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:21:6
|
||||
--> $DIR/fn_trait_refs.rs:21:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:21:6
|
||||
--> $DIR/fn_trait_refs.rs:21:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:21:6
|
||||
--> $DIR/fn_trait_refs.rs:21:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:28:6
|
||||
--> $DIR/fn_trait_refs.rs:28:8
|
||||
|
|
||||
LL | T: [const] FnOnce<()>,
|
||||
| ^^^^^^^^^ can't be applied to `FnOnce`
|
||||
| ^^^^^^^ can't be applied to `FnOnce`
|
||||
|
|
||||
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:28:6
|
||||
--> $DIR/fn_trait_refs.rs:28:8
|
||||
|
|
||||
LL | T: [const] FnOnce<()>,
|
||||
| ^^^^^^^^^ can't be applied to `FnOnce`
|
||||
| ^^^^^^^ can't be applied to `FnOnce`
|
||||
|
|
||||
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:28:6
|
||||
--> $DIR/fn_trait_refs.rs:28:8
|
||||
|
|
||||
LL | T: [const] FnOnce<()>,
|
||||
| ^^^^^^^^^ can't be applied to `FnOnce`
|
||||
| ^^^^^^^ can't be applied to `FnOnce`
|
||||
|
|
||||
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:35:6
|
||||
--> $DIR/fn_trait_refs.rs:35:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:35:6
|
||||
--> $DIR/fn_trait_refs.rs:35:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:35:6
|
||||
--> $DIR/fn_trait_refs.rs:35:8
|
||||
|
|
||||
LL | T: [const] Fn<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:49:6
|
||||
--> $DIR/fn_trait_refs.rs:49:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:49:6
|
||||
--> $DIR/fn_trait_refs.rs:49:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:49:6
|
||||
--> $DIR/fn_trait_refs.rs:49:8
|
||||
|
|
||||
LL | T: [const] FnMut<()> + [const] Destruct,
|
||||
| ^^^^^^^^^ can't be applied to `FnMut`
|
||||
| ^^^^^^^ can't be applied to `FnMut`
|
||||
|
|
||||
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:30
|
||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:32
|
||||
|
|
||||
LL | const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
|
||||
| ^^^^^^^^^ can't be applied to `FnOnce`
|
||||
| ^^^^^^^ can't be applied to `FnOnce`
|
||||
|
|
||||
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:30
|
||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:32
|
||||
|
|
||||
LL | const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
|
||||
| ^^^^^^^^^ can't be applied to `FnOnce`
|
||||
| ^^^^^^^ can't be applied to `FnOnce`
|
||||
|
|
||||
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
fn assert_sizeof() -> ! {
|
||||
unsafe {
|
||||
::std::mem::transmute::<f64, [u8; 8]>(panic!())
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
145
tests/ui/drop/drop-order-comparisons-let-chains.rs
Normal file
145
tests/ui/drop/drop-order-comparisons-let-chains.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
// See drop-order-comparisons.rs
|
||||
|
||||
//@ edition: 2024
|
||||
//@ run-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
fn t_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() {
|
||||
e.mark(3);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn t_guard_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() => {
|
||||
e.mark(3);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn t_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) {} else {
|
||||
e.mark(9);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn t_guard_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) => {}
|
||||
_ => {
|
||||
e.mark(9);
|
||||
}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
t_if_let_chains_then();
|
||||
t_guard_if_let_chains_then();
|
||||
t_if_let_chains_then_else();
|
||||
t_guard_if_let_chains_then_else();
|
||||
}
|
||||
|
||||
// # Test scaffolding
|
||||
|
||||
use core::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// A buffer to track the order of events.
|
||||
///
|
||||
/// First, numbered events are logged into this buffer.
|
||||
///
|
||||
/// Then, `assert` is called to verify that the correct number of
|
||||
/// events were logged, and that they were logged in the expected
|
||||
/// order.
|
||||
struct Events(RefCell<Option<Vec<u64>>>);
|
||||
|
||||
impl Events {
|
||||
const fn new() -> Self {
|
||||
Self(RefCell::new(Some(Vec::new())))
|
||||
}
|
||||
#[track_caller]
|
||||
fn assert(&self, max: u64) {
|
||||
let buf = &self.0;
|
||||
let v1 = buf.borrow().as_ref().unwrap().clone();
|
||||
let mut v2 = buf.borrow().as_ref().unwrap().clone();
|
||||
*buf.borrow_mut() = None;
|
||||
v2.sort();
|
||||
let uniq_len = v2.iter().collect::<HashSet<_>>().len();
|
||||
// Check that the sequence is sorted.
|
||||
assert_eq!(v1, v2);
|
||||
// Check that there are no duplicates.
|
||||
assert_eq!(v2.len(), uniq_len);
|
||||
// Check that the length is the expected one.
|
||||
assert_eq!(max, uniq_len as u64);
|
||||
// Check that the last marker is the expected one.
|
||||
assert_eq!(v2.last().unwrap(), &max);
|
||||
}
|
||||
/// Return an `Ok` value that logs its drop.
|
||||
fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
|
||||
Ok(LogDrop(self, m))
|
||||
}
|
||||
/// Return an `Err` value that logs its drop.
|
||||
fn err(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
|
||||
Err(LogDrop(self, m))
|
||||
}
|
||||
/// Log an event.
|
||||
fn mark(&self, m: u64) {
|
||||
self.0.borrow_mut().as_mut().unwrap().push(m);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Events {
|
||||
fn drop(&mut self) {
|
||||
if self.0.borrow().is_some() {
|
||||
panic!("failed to call `Events::assert()`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type that logs its drop events.
|
||||
struct LogDrop<'b>(&'b Events, u64);
|
||||
|
||||
impl<'b> Drop for LogDrop<'b> {
|
||||
fn drop(&mut self) {
|
||||
self.0.mark(self.1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// N.B. drop-order-comparisons-let-chains.rs is part of this test.
|
||||
// It is separate because let chains cannot be parsed before Rust 2024.
|
||||
//
|
||||
// This tests various aspects of the drop order with a focus on:
|
||||
//
|
||||
// - The lifetime of temporaries with the `if let` construct (and with
|
||||
|
|
@ -25,7 +28,6 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![cfg_attr(e2021, feature(let_chains))]
|
||||
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
|
||||
|
||||
fn t_bindings() {
|
||||
|
|
@ -311,59 +313,6 @@ fn t_let_else_chained_then() {
|
|||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.ok(6).as_ref() {
|
||||
e.mark(3);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2024)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() {
|
||||
e.mark(3);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn t_guard_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() => {
|
||||
e.mark(3);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_nested_else() {
|
||||
|
|
@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() {
|
|||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(3)
|
||||
&& let Ok(_) = e.err(6) {} else {
|
||||
e.mark(5);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2024)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) {} else {
|
||||
e.mark(9);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn t_guard_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) => {}
|
||||
_ => {
|
||||
e.mark(9);
|
||||
}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
t_bindings();
|
||||
t_tuples();
|
||||
|
|
@ -540,13 +436,9 @@ fn main() {
|
|||
t_if_let_else_tailexpr();
|
||||
t_if_let_nested_then();
|
||||
t_let_else_chained_then();
|
||||
t_if_let_chains_then();
|
||||
t_guard_if_let_chains_then();
|
||||
t_if_let_nested_else();
|
||||
t_if_let_nested_then_else();
|
||||
t_let_else_chained_then_else();
|
||||
t_if_let_chains_then_else();
|
||||
t_guard_if_let_chains_then_else();
|
||||
}
|
||||
|
||||
// # Test scaffolding
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
warning: relative drop order changing in Rust 2024
|
||||
--> $DIR/drop-order-comparisons.rs:77:9
|
||||
--> $DIR/drop-order-comparisons.rs:79:9
|
||||
|
|
||||
LL | _ = ({
|
||||
| _________-
|
||||
|
|
@ -29,35 +29,35 @@ LL | | }, e.mark(3), e.ok(4));
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||
note: `#3` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#1` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `_v` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#2` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
|
||||
note: the lint level is defined here
|
||||
--> $DIR/drop-order-comparisons.rs:29:25
|
||||
--> $DIR/drop-order-comparisons.rs:31:25
|
||||
|
|
||||
LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]`
|
||||
|
||||
warning: relative drop order changing in Rust 2024
|
||||
--> $DIR/drop-order-comparisons.rs:101:45
|
||||
--> $DIR/drop-order-comparisons.rs:103:45
|
||||
|
|
||||
LL | _ = ({
|
||||
| _________-
|
||||
|
|
@ -77,19 +77,19 @@ LL | | }, e.mark(1), e.ok(4));
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||
note: `#2` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#1` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
|
||||
|
||||
warning: relative drop order changing in Rust 2024
|
||||
--> $DIR/drop-order-comparisons.rs:101:19
|
||||
--> $DIR/drop-order-comparisons.rs:103:19
|
||||
|
|
||||
LL | _ = ({
|
||||
| _________-
|
||||
|
|
@ -109,19 +109,19 @@ LL | | }, e.mark(1), e.ok(4));
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||
note: `#2` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#1` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
|
||||
|
||||
warning: relative drop order changing in Rust 2024
|
||||
--> $DIR/drop-order-comparisons.rs:222:24
|
||||
--> $DIR/drop-order-comparisons.rs:224:24
|
||||
|
|
||||
LL | _ = ({
|
||||
| _________-
|
||||
|
|
@ -141,19 +141,19 @@ LL | | }, e.mark(2), e.ok(3));
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||
note: `#2` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#1` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
|
||||
|
||||
warning: relative drop order changing in Rust 2024
|
||||
--> $DIR/drop-order-comparisons.rs:248:24
|
||||
--> $DIR/drop-order-comparisons.rs:250:24
|
||||
|
|
||||
LL | _ = ({
|
||||
| _________-
|
||||
|
|
@ -173,19 +173,19 @@ LL | | }, e.mark(2), e.ok(3));
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||
note: `#2` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: `#1` invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:124:13
|
||||
--> $DIR/drop-order-comparisons.rs:126:13
|
||||
|
|
||||
LL | _ = (if let Ok(_) = e.ok(4).as_ref() {
|
||||
| ^^^^^^^^^^^^-------^^^^^^^^^
|
||||
|
|
@ -195,12 +195,12 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:128:5
|
||||
--> $DIR/drop-order-comparisons.rs:130:5
|
||||
|
|
||||
LL | }, e.mark(2), e.ok(3));
|
||||
| ^
|
||||
|
|
@ -215,7 +215,7 @@ LL ~ } _ => {}}, e.mark(2), e.ok(3));
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:146:13
|
||||
--> $DIR/drop-order-comparisons.rs:148:13
|
||||
|
|
||||
LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^^^^^^^^^^^^--------^^^^^^^^^
|
||||
|
|
@ -225,12 +225,12 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:146:44
|
||||
--> $DIR/drop-order-comparisons.rs:148:44
|
||||
|
|
||||
LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^
|
||||
|
|
@ -244,7 +244,7 @@ LL ~ }}, e.mark(2), e.ok(3));
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:248:12
|
||||
--> $DIR/drop-order-comparisons.rs:250:12
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^^^^^^^^^^^^--------^^^^^^^^^
|
||||
|
|
@ -254,12 +254,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:248:43
|
||||
--> $DIR/drop-order-comparisons.rs:250:43
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^
|
||||
|
|
@ -273,7 +273,7 @@ LL ~ }}
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:372:12
|
||||
--> $DIR/drop-order-comparisons.rs:321:12
|
||||
|
|
||||
LL | if let true = e.err(9).is_ok() {} else {
|
||||
| ^^^^^^^^^^^--------^^^^^^^^
|
||||
|
|
@ -283,12 +283,12 @@ LL | if let true = e.err(9).is_ok() {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:372:41
|
||||
--> $DIR/drop-order-comparisons.rs:321:41
|
||||
|
|
||||
LL | if let true = e.err(9).is_ok() {} else {
|
||||
| ^
|
||||
|
|
@ -302,7 +302,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:375:12
|
||||
--> $DIR/drop-order-comparisons.rs:324:12
|
||||
|
|
||||
LL | if let Ok(_v) = e.err(8) {} else {
|
||||
| ^^^^^^^^^^^^^--------
|
||||
|
|
@ -312,12 +312,12 @@ LL | if let Ok(_v) = e.err(8) {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:375:35
|
||||
--> $DIR/drop-order-comparisons.rs:324:35
|
||||
|
|
||||
LL | if let Ok(_v) = e.err(8) {} else {
|
||||
| ^
|
||||
|
|
@ -331,7 +331,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:378:12
|
||||
--> $DIR/drop-order-comparisons.rs:327:12
|
||||
|
|
||||
LL | if let Ok(_) = e.err(7) {} else {
|
||||
| ^^^^^^^^^^^^--------
|
||||
|
|
@ -341,12 +341,12 @@ LL | if let Ok(_) = e.err(7) {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:378:34
|
||||
--> $DIR/drop-order-comparisons.rs:327:34
|
||||
|
|
||||
LL | if let Ok(_) = e.err(7) {} else {
|
||||
| ^
|
||||
|
|
@ -360,7 +360,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:381:12
|
||||
--> $DIR/drop-order-comparisons.rs:330:12
|
||||
|
|
||||
LL | if let Ok(_) = e.err(6).as_ref() {} else {
|
||||
| ^^^^^^^^^^^^--------^^^^^^^^^
|
||||
|
|
@ -370,12 +370,12 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:381:43
|
||||
--> $DIR/drop-order-comparisons.rs:330:43
|
||||
|
|
||||
LL | if let Ok(_) = e.err(6).as_ref() {} else {
|
||||
| ^
|
||||
|
|
@ -389,7 +389,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:385:12
|
||||
--> $DIR/drop-order-comparisons.rs:334:12
|
||||
|
|
||||
LL | if let Ok(_v) = e.err(5) {} else {
|
||||
| ^^^^^^^^^^^^^--------
|
||||
|
|
@ -399,12 +399,12 @@ LL | if let Ok(_v) = e.err(5) {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:385:35
|
||||
--> $DIR/drop-order-comparisons.rs:334:35
|
||||
|
|
||||
LL | if let Ok(_v) = e.err(5) {} else {
|
||||
| ^
|
||||
|
|
@ -418,7 +418,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:388:12
|
||||
--> $DIR/drop-order-comparisons.rs:337:12
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4) {} else {
|
||||
| ^^^^^^^^^^^^--------
|
||||
|
|
@ -428,12 +428,12 @@ LL | if let Ok(_) = e.err(4) {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:388:34
|
||||
--> $DIR/drop-order-comparisons.rs:337:34
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4) {} else {
|
||||
| ^
|
||||
|
|
@ -447,7 +447,7 @@ LL ~ }}}}}}}}};
|
|||
|
|
||||
|
||||
warning: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:424:12
|
||||
--> $DIR/drop-order-comparisons.rs:373:12
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^^^^^^^^^^^^--------^^^^^^^^^
|
||||
|
|
@ -457,12 +457,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
|||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
note: value invokes this custom destructor
|
||||
--> $DIR/drop-order-comparisons.rs:612:1
|
||||
--> $DIR/drop-order-comparisons.rs:504:1
|
||||
|
|
||||
LL | impl<'b> Drop for LogDrop<'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/drop-order-comparisons.rs:424:43
|
||||
--> $DIR/drop-order-comparisons.rs:373:43
|
||||
|
|
||||
LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||
| ^
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// N.B. drop-order-comparisons-let-chains.rs is part of this test.
|
||||
// It is separate because let chains cannot be parsed before Rust 2024.
|
||||
//
|
||||
// This tests various aspects of the drop order with a focus on:
|
||||
//
|
||||
// - The lifetime of temporaries with the `if let` construct (and with
|
||||
|
|
@ -25,7 +28,6 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![cfg_attr(e2021, feature(let_chains))]
|
||||
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
|
||||
|
||||
fn t_bindings() {
|
||||
|
|
@ -311,59 +313,6 @@ fn t_let_else_chained_then() {
|
|||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.ok(6).as_ref() {
|
||||
e.mark(3);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2024)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() {
|
||||
e.mark(3);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn t_guard_if_let_chains_then() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(5)
|
||||
&& let Ok(_) = e.ok(4).as_ref() => {
|
||||
e.mark(3);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_nested_else() {
|
||||
|
|
@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() {
|
|||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2021)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(9).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.ok(8)
|
||||
&& let Ok(_) = e.ok(7).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(3)
|
||||
&& let Ok(_) = e.err(6) {} else {
|
||||
e.mark(5);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[cfg(e2024)]
|
||||
#[rustfmt::skip]
|
||||
fn t_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) {} else {
|
||||
e.mark(9);
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn t_guard_if_let_chains_then_else() {
|
||||
let e = Events::new();
|
||||
_ = match () {
|
||||
() if e.ok(1).is_ok()
|
||||
&& let true = e.ok(8).is_ok()
|
||||
&& let Ok(_v) = e.ok(7)
|
||||
&& let Ok(_) = e.ok(6)
|
||||
&& let Ok(_) = e.ok(5).as_ref()
|
||||
&& e.ok(2).is_ok()
|
||||
&& let Ok(_v) = e.ok(4)
|
||||
&& let Ok(_) = e.err(3) => {}
|
||||
_ => {
|
||||
e.mark(9);
|
||||
}
|
||||
};
|
||||
e.assert(9);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
t_bindings();
|
||||
t_tuples();
|
||||
|
|
@ -540,13 +436,9 @@ fn main() {
|
|||
t_if_let_else_tailexpr();
|
||||
t_if_let_nested_then();
|
||||
t_let_else_chained_then();
|
||||
t_if_let_chains_then();
|
||||
t_guard_if_let_chains_then();
|
||||
t_if_let_nested_else();
|
||||
t_if_let_nested_then_else();
|
||||
t_let_else_chained_then_else();
|
||||
t_if_let_chains_then_else();
|
||||
t_guard_if_let_chains_then_else();
|
||||
}
|
||||
|
||||
// # Test scaffolding
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
//@ [edition2024] compile-flags: -Z lint-mir
|
||||
//@ [edition2024] edition: 2024
|
||||
|
||||
#![cfg_attr(edition2021, feature(let_chains))]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryInto;
|
||||
|
||||
|
|
@ -210,68 +208,6 @@ impl DropOrderCollector {
|
|||
}
|
||||
}
|
||||
|
||||
fn let_chain(&self) {
|
||||
// take the "then" branch
|
||||
if self.option_loud_drop(1).is_some() // 1
|
||||
&& self.option_loud_drop(2).is_some() // 2
|
||||
&& let Some(_d) = self.option_loud_drop(4) { // 4
|
||||
self.print(3); // 3
|
||||
}
|
||||
|
||||
#[cfg(edition2021)]
|
||||
// take the "else" branch
|
||||
if self.option_loud_drop(5).is_some() // 1
|
||||
&& self.option_loud_drop(6).is_some() // 2
|
||||
&& let None = self.option_loud_drop(8) { // 4
|
||||
unreachable!();
|
||||
} else {
|
||||
self.print(7); // 3
|
||||
}
|
||||
#[cfg(edition2024)]
|
||||
// take the "else" branch
|
||||
if self.option_loud_drop(5).is_some() // 1
|
||||
&& self.option_loud_drop(6).is_some() // 2
|
||||
&& let None = self.option_loud_drop(7) { // 4
|
||||
unreachable!();
|
||||
} else {
|
||||
self.print(8); // 3
|
||||
}
|
||||
|
||||
// let exprs interspersed
|
||||
if self.option_loud_drop(9).is_some() // 1
|
||||
&& let Some(_d) = self.option_loud_drop(13) // 5
|
||||
&& self.option_loud_drop(10).is_some() // 2
|
||||
&& let Some(_e) = self.option_loud_drop(12) { // 4
|
||||
self.print(11); // 3
|
||||
}
|
||||
|
||||
// let exprs first
|
||||
if let Some(_d) = self.option_loud_drop(18) // 5
|
||||
&& let Some(_e) = self.option_loud_drop(17) // 4
|
||||
&& self.option_loud_drop(14).is_some() // 1
|
||||
&& self.option_loud_drop(15).is_some() { // 2
|
||||
self.print(16); // 3
|
||||
}
|
||||
|
||||
// let exprs last
|
||||
if self.option_loud_drop(19).is_some() // 1
|
||||
&& self.option_loud_drop(20).is_some() // 2
|
||||
&& let Some(_d) = self.option_loud_drop(23) // 5
|
||||
&& let Some(_e) = self.option_loud_drop(22) { // 4
|
||||
self.print(21); // 3
|
||||
}
|
||||
}
|
||||
|
||||
fn while_(&self) {
|
||||
let mut v = self.option_loud_drop(4);
|
||||
while let Some(_d) = v
|
||||
&& self.option_loud_drop(1).is_some()
|
||||
&& self.option_loud_drop(2).is_some() {
|
||||
self.print(3);
|
||||
v = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_sorted(self) {
|
||||
assert!(
|
||||
self.0
|
||||
|
|
@ -313,14 +249,4 @@ fn main() {
|
|||
let collector = DropOrderCollector::default();
|
||||
collector.match_();
|
||||
collector.assert_sorted();
|
||||
|
||||
println!("-- let chain --");
|
||||
let collector = DropOrderCollector::default();
|
||||
collector.let_chain();
|
||||
collector.assert_sorted();
|
||||
|
||||
println!("-- while --");
|
||||
let collector = DropOrderCollector::default();
|
||||
collector.while_();
|
||||
collector.assert_sorted();
|
||||
}
|
||||
|
|
|
|||
103
tests/ui/drop/drop_order_let_chain.rs
Normal file
103
tests/ui/drop/drop_order_let_chain.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
//@ run-pass
|
||||
//@ compile-flags: -Z validate-mir
|
||||
//@ edition: 2024
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Default)]
|
||||
struct DropOrderCollector(RefCell<Vec<u32>>);
|
||||
|
||||
struct LoudDrop<'a>(&'a DropOrderCollector, u32);
|
||||
|
||||
impl Drop for LoudDrop<'_> {
|
||||
fn drop(&mut self) {
|
||||
println!("{}", self.1);
|
||||
self.0.0.borrow_mut().push(self.1);
|
||||
}
|
||||
}
|
||||
|
||||
impl DropOrderCollector {
|
||||
fn option_loud_drop(&self, n: u32) -> Option<LoudDrop<'_>> {
|
||||
Some(LoudDrop(self, n))
|
||||
}
|
||||
|
||||
fn print(&self, n: u32) {
|
||||
println!("{}", n);
|
||||
self.0.borrow_mut().push(n)
|
||||
}
|
||||
|
||||
fn let_chain(&self) {
|
||||
// take the "then" branch
|
||||
if self.option_loud_drop(1).is_some() // 1
|
||||
&& self.option_loud_drop(2).is_some() // 2
|
||||
&& let Some(_d) = self.option_loud_drop(4) { // 4
|
||||
self.print(3); // 3
|
||||
}
|
||||
|
||||
// take the "else" branch
|
||||
if self.option_loud_drop(5).is_some() // 1
|
||||
&& self.option_loud_drop(6).is_some() // 2
|
||||
&& let None = self.option_loud_drop(7) { // 4
|
||||
unreachable!();
|
||||
} else {
|
||||
self.print(8); // 3
|
||||
}
|
||||
|
||||
// let exprs interspersed
|
||||
if self.option_loud_drop(9).is_some() // 1
|
||||
&& let Some(_d) = self.option_loud_drop(13) // 5
|
||||
&& self.option_loud_drop(10).is_some() // 2
|
||||
&& let Some(_e) = self.option_loud_drop(12) { // 4
|
||||
self.print(11); // 3
|
||||
}
|
||||
|
||||
// let exprs first
|
||||
if let Some(_d) = self.option_loud_drop(18) // 5
|
||||
&& let Some(_e) = self.option_loud_drop(17) // 4
|
||||
&& self.option_loud_drop(14).is_some() // 1
|
||||
&& self.option_loud_drop(15).is_some() { // 2
|
||||
self.print(16); // 3
|
||||
}
|
||||
|
||||
// let exprs last
|
||||
if self.option_loud_drop(19).is_some() // 1
|
||||
&& self.option_loud_drop(20).is_some() // 2
|
||||
&& let Some(_d) = self.option_loud_drop(23) // 5
|
||||
&& let Some(_e) = self.option_loud_drop(22) { // 4
|
||||
self.print(21); // 3
|
||||
}
|
||||
}
|
||||
|
||||
fn while_(&self) {
|
||||
let mut v = self.option_loud_drop(4);
|
||||
while let Some(_d) = v
|
||||
&& self.option_loud_drop(1).is_some()
|
||||
&& self.option_loud_drop(2).is_some() {
|
||||
self.print(3);
|
||||
v = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_sorted(self) {
|
||||
assert!(
|
||||
self.0
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.all(|(idx, item)| idx + 1 == item.try_into().unwrap())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("-- let chain --");
|
||||
let collector = DropOrderCollector::default();
|
||||
collector.let_chain();
|
||||
collector.assert_sorted();
|
||||
|
||||
println!("-- while --");
|
||||
let collector = DropOrderCollector::default();
|
||||
collector.while_();
|
||||
collector.assert_sorted();
|
||||
}
|
||||
|
|
@ -1,11 +1,6 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: -Z validate-mir
|
||||
//@ revisions: edition2021 edition2024
|
||||
//@ [edition2021] edition: 2021
|
||||
//@ [edition2024] compile-flags: -Z lint-mir
|
||||
//@ [edition2024] edition: 2024
|
||||
|
||||
#![cfg_attr(edition2021, feature(let_chains))]
|
||||
//@ compile-flags: -Z lint-mir -Z validate-mir
|
||||
//@ edition: 2024
|
||||
|
||||
fn let_chains(entry: std::io::Result<std::fs::DirEntry>) {
|
||||
if let Ok(entry) = entry
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
fn wsucc<T:Add<Output=T> + Copy>(n: T) -> T { n + { return n } }
|
||||
|
||||
pub fn main() { }
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// Hide irrelevant E0277 errors (#50333)
|
||||
|
||||
trait T {}
|
||||
|
||||
struct A;
|
||||
impl T for A {}
|
||||
impl A {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
|
||||
//~^ ERROR mismatched types
|
||||
let ts: Vec<&dyn T> = vec![&a, &b, &c];
|
||||
// There is no E0277 error above, as `a`, `b` and `c` are `TyErr`
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
// Since we're not compiling a test runner this function should be elided
|
||||
// and the build will fail because main doesn't exist
|
||||
#[test]
|
||||
fn main() {
|
||||
} //~ ERROR `main` function not found in crate `elided_test`
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
error[E0601]: `main` function not found in crate `elided_test`
|
||||
--> $DIR/elided-test.rs:5:2
|
||||
|
|
||||
LL | }
|
||||
| ^ consider adding a `main` function to `$DIR/elided-test.rs`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0601`.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
pub fn main() {
|
||||
if 1 == 2 {
|
||||
assert!((false));
|
||||
} else if 2 == 3 {
|
||||
assert!((false));
|
||||
} else if 3 == 4 { assert!((false)); } else { assert!((true)); }
|
||||
if 1 == 2 { assert!((false)); } else if 2 == 2 { assert!((true)); }
|
||||
if 1 == 2 {
|
||||
assert!((false));
|
||||
} else if 2 == 2 {
|
||||
if 1 == 1 {
|
||||
assert!((true));
|
||||
} else { if 2 == 1 { assert!((false)); } else { assert!((false)); } }
|
||||
}
|
||||
if 1 == 2 {
|
||||
assert!((false));
|
||||
} else { if 1 == 2 { assert!((false)); } else { assert!((true)); } }
|
||||
}
|
||||
19
tests/ui/expr/early-return-in-binop.rs
Normal file
19
tests/ui/expr/early-return-in-binop.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//! Test early return within binary operation expressions
|
||||
|
||||
//@ run-pass
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
/// Function that performs addition with an early return in the right operand
|
||||
fn add_with_early_return<T: Add<Output = T> + Copy>(n: T) -> T {
|
||||
n + { return n }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// Test with different numeric types to ensure generic behavior works
|
||||
let _result1 = add_with_early_return(42i32);
|
||||
let _result2 = add_with_early_return(3.14f64);
|
||||
}
|
||||
5
tests/ui/extern/issue-47725.rs
vendored
5
tests/ui/extern/issue-47725.rs
vendored
|
|
@ -17,12 +17,9 @@ extern "C" {
|
|||
#[link_name]
|
||||
//~^ ERROR malformed `link_name` attribute input
|
||||
//~| HELP must be of the form
|
||||
//~| WARN attribute should be applied to a foreign function or static [unused_attributes]
|
||||
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
//~| HELP try `#[link(name = "...")]` instead
|
||||
//~| NOTE expected this to be of the form `link_name = "..."
|
||||
extern "C" {
|
||||
fn bar() -> u32;
|
||||
}
|
||||
//~^^^ NOTE not a foreign function or static
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
28
tests/ui/extern/issue-47725.stderr
vendored
28
tests/ui/extern/issue-47725.stderr
vendored
|
|
@ -1,8 +1,11 @@
|
|||
error: malformed `link_name` attribute input
|
||||
error[E0539]: malformed `link_name` attribute input
|
||||
--> $DIR/issue-47725.rs:17:1
|
||||
|
|
||||
LL | #[link_name]
|
||||
| ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]`
|
||||
| ^^^^^^^^^^^^
|
||||
| |
|
||||
| expected this to be of the form `link_name = "..."`
|
||||
| help: must be of the form: `#[link_name = "name"]`
|
||||
|
||||
warning: attribute should be applied to a foreign function or static
|
||||
--> $DIR/issue-47725.rs:3:1
|
||||
|
|
@ -38,23 +41,6 @@ help: try `#[link(name = "foobar")]` instead
|
|||
LL | #[link_name = "foobar"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: attribute should be applied to a foreign function or static
|
||||
--> $DIR/issue-47725.rs:17:1
|
||||
|
|
||||
LL | #[link_name]
|
||||
| ^^^^^^^^^^^^
|
||||
...
|
||||
LL | / extern "C" {
|
||||
LL | | fn bar() -> u32;
|
||||
LL | | }
|
||||
| |_- not a foreign function or static
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
help: try `#[link(name = "...")]` instead
|
||||
--> $DIR/issue-47725.rs:17:1
|
||||
|
|
||||
LL | #[link_name]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error; 3 warnings emitted
|
||||
error: aborting due to 1 previous error; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
|
|
@ -387,14 +387,6 @@ LL | #![link()]
|
|||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to a foreign function or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
||||
|
|
||||
LL | #![link_name = "1900"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to a function or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
|
||||
|
|
||||
|
|
@ -411,6 +403,14 @@ LL | #![cold]
|
|||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to a foreign function or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
||||
|
|
||||
LL | #![link_name = "1900"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: `#[must_use]` has no effect when applied to a module
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
|
||||
|
|
||||
|
|
|
|||
32
tests/ui/generics/unconstrained-type-params-inherent-impl.rs
Normal file
32
tests/ui/generics/unconstrained-type-params-inherent-impl.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//! Test for unconstrained type parameters in inherent implementations
|
||||
|
||||
struct MyType;
|
||||
|
||||
struct MyType1<T>(T);
|
||||
|
||||
trait Bar {
|
||||
type Out;
|
||||
}
|
||||
|
||||
impl<T> MyType {
|
||||
//~^ ERROR the type parameter `T` is not constrained
|
||||
// T is completely unused - this should fail
|
||||
}
|
||||
|
||||
impl<T> MyType1<T> {
|
||||
// OK: T is used in the self type `MyType1<T>`
|
||||
}
|
||||
|
||||
impl<T, U> MyType1<T> {
|
||||
//~^ ERROR the type parameter `U` is not constrained
|
||||
// T is used in self type, but U is unconstrained - this should fail
|
||||
}
|
||||
|
||||
impl<T, U> MyType1<T>
|
||||
where
|
||||
T: Bar<Out = U>,
|
||||
{
|
||||
// OK: T is used in self type, U is constrained through the where clause
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/impl-unused-tps-inherent.rs:9:6
|
||||
--> $DIR/unconstrained-type-params-inherent-impl.rs:11:6
|
||||
|
|
||||
LL | impl<T> MyType {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/impl-unused-tps-inherent.rs:17:8
|
||||
--> $DIR/unconstrained-type-params-inherent-impl.rs:20:9
|
||||
|
|
||||
LL | impl<T,U> MyType1<T> {
|
||||
| ^ unconstrained type parameter
|
||||
LL | impl<T, U> MyType1<T> {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/normalize-tait-in-const.rs:27:33
|
||||
--> $DIR/normalize-tait-in-const.rs:27:35
|
||||
|
|
||||
LL | const fn with_positive<F: for<'a> [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) {
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
||||
error: `[const]` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/normalize-tait-in-const.rs:27:33
|
||||
--> $DIR/normalize-tait-in-const.rs:27:35
|
||||
|
|
||||
LL | const fn with_positive<F: for<'a> [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) {
|
||||
| ^^^^^^^^^ can't be applied to `Fn`
|
||||
| ^^^^^^^ can't be applied to `Fn`
|
||||
|
|
||||
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
// Test that lifetime parameters must be constrained if they appear in
|
||||
// an associated type def'n. Issue #22077.
|
||||
|
||||
trait Fun {
|
||||
type Output;
|
||||
fn call<'x>(&'x self) -> Self::Output;
|
||||
}
|
||||
|
||||
struct Holder { x: String }
|
||||
|
||||
impl<'a> Fun for Holder { //~ ERROR E0207
|
||||
type Output = &'a str;
|
||||
fn call<'b>(&'b self) -> &'b str {
|
||||
&self.x[..]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
struct MyType;
|
||||
|
||||
struct MyType1<T>(T);
|
||||
|
||||
trait Bar {
|
||||
type Out;
|
||||
}
|
||||
|
||||
impl<T> MyType {
|
||||
//~^ ERROR the type parameter `T` is not constrained
|
||||
}
|
||||
|
||||
impl<T> MyType1<T> {
|
||||
// OK, T is used in `Foo<T>`.
|
||||
}
|
||||
|
||||
impl<T,U> MyType1<T> {
|
||||
//~^ ERROR the type parameter `U` is not constrained
|
||||
}
|
||||
|
||||
impl<T,U> MyType1<T> where T: Bar<Out=U> {
|
||||
// OK, T is used in `Foo<T>`.
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
let _f = 10i32.abs; //~ ERROR attempted to take value of method
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
error[E0615]: attempted to take value of method `abs` on type `i32`
|
||||
--> $DIR/implicit-method-bind.rs:2:20
|
||||
|
|
||||
LL | let _f = 10i32.abs;
|
||||
| ^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
LL | let _f = 10i32.abs();
|
||||
| ++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0615`.
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
//! Test that duplicate use bindings in same namespace produce error
|
||||
|
||||
mod foo {
|
||||
pub use self::bar::X;
|
||||
use self::bar::X;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue