diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2024-06-23 05:01:42 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2024-06-23 05:01:42 +0000 |
| commit | d5feca99d6d165233cfb52339ec0560a01f72413 (patch) | |
| tree | cd43d510453fa46d8d7ec0fd38b93bbd22fa6400 | |
| parent | f91411b5ff5335601aa5acde43302ddfce8d4b82 (diff) | |
| parent | dd545e148c0c1680be1555efcb02ece0a16ee3ef (diff) | |
| download | rust-d5feca99d6d165233cfb52339ec0560a01f72413.tar.gz rust-d5feca99d6d165233cfb52339ec0560a01f72413.zip | |
Merge from rustc
493 files changed, 8185 insertions, 2258 deletions
diff --git a/Cargo.lock b/Cargo.lock index 6c378cd7406..9d1481ec768 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,7 +638,7 @@ dependencies = [ "filetime", "futures", "if_chain", - "itertools 0.12.1", + "itertools", "parking_lot", "quote", "regex", @@ -670,7 +670,7 @@ dependencies = [ "aho-corasick", "clap", "indoc", - "itertools 0.12.1", + "itertools", "opener 0.6.1", "shell-escape", "walkdir", @@ -685,7 +685,7 @@ dependencies = [ "clippy_config", "clippy_utils", "declare_clippy_lint", - "itertools 0.12.1", + "itertools", "quine-mc_cluskey", "regex", "regex-syntax 0.8.4", @@ -707,7 +707,7 @@ version = "0.1.81" dependencies = [ "arrayvec", "clippy_config", - "itertools 0.12.1", + "itertools", "rustc-semver", "rustc_apfloat", ] @@ -1026,7 +1026,7 @@ dependencies = [ name = "declare_clippy_lint" version = "0.1.81" dependencies = [ - "itertools 0.12.1", + "itertools", "quote", "syn 2.0.66", ] @@ -1133,16 +1133,16 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys 0.4.1", + "dirs-sys", ] [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.3.7", + "dirs-sys", ] [[package]] @@ -1157,17 +1157,6 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dirs-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" @@ -2078,15 +2067,6 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" @@ -2227,7 +2207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -3665,7 +3645,7 @@ dependencies = [ name = "rustc_ast_passes" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_ast", "rustc_ast_pretty", "rustc_attr", @@ -3685,7 +3665,7 @@ dependencies = [ name = "rustc_ast_pretty" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_ast", "rustc_lexer", "rustc_span", @@ -3726,7 +3706,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "either", - "itertools 0.12.1", + "itertools", "polonius-engine", "rustc_data_structures", "rustc_errors", @@ -3779,7 +3759,7 @@ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ "bitflags 2.5.0", - "itertools 0.12.1", + "itertools", "libc", "measureme", "object 0.32.2", @@ -3818,7 +3798,7 @@ dependencies = [ "bitflags 2.5.0", "cc", "either", - "itertools 0.12.1", + "itertools", "jobserver", "libc", "object 0.32.2", @@ -4098,7 +4078,7 @@ dependencies = [ name = "rustc_hir_analysis" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_arena", "rustc_ast", "rustc_attr", @@ -4137,7 +4117,7 @@ dependencies = [ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4421,7 +4401,7 @@ dependencies = [ name = "rustc_mir_build" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4468,7 +4448,7 @@ name = "rustc_mir_transform" version = "0.0.0" dependencies = [ "either", - "itertools 0.12.1", + "itertools", "rustc_arena", "rustc_ast", "rustc_attr", @@ -4762,6 +4742,7 @@ dependencies = [ name = "rustc_span" version = "0.0.0" dependencies = [ + "derivative", "indexmap", "itoa", "md-5", @@ -4823,7 +4804,7 @@ version = "0.0.0" dependencies = [ "bitflags 2.5.0", "derivative", - "itertools 0.12.1", + "itertools", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4866,7 +4847,7 @@ dependencies = [ name = "rustc_transmute" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_ast_ir", "rustc_data_structures", "rustc_hir", @@ -4882,7 +4863,7 @@ dependencies = [ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ - "itertools 0.12.1", + "itertools", "rustc_ast_ir", "rustc_data_structures", "rustc_errors", @@ -4946,7 +4927,7 @@ dependencies = [ "base64", "expect-test", "indexmap", - "itertools 0.12.1", + "itertools", "minifier", "regex", "rustdoc-json-types", @@ -5027,20 +5008,19 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.7.0" +version = "1.7.1" dependencies = [ "annotate-snippets 0.9.2", "anyhow", "bytecount", - "cargo_metadata 0.15.4", + "cargo_metadata 0.18.1", "clap", "clap-cargo", "diff", "dirs", "getopts", "ignore", - "itertools 0.11.0", - "lazy_static", + "itertools", "regex", "rustfmt-config_proc_macro", "serde", @@ -5699,6 +5679,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo_metadata 0.15.4", + "fluent-syntax", "ignore", "miropt-test-tools", "regex", diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 7d81e45d314..52164d6ef16 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -78,7 +78,7 @@ ast_lowering_inline_asm_unsupported_target = ast_lowering_invalid_abi = invalid ABI: found `{$abi}` .label = invalid ABI - .note = invoke `{$command}` for a full list of supported calling conventions. + .note = invoke `{$command}` for a full list of supported calling conventions ast_lowering_invalid_abi_clobber_abi = invalid ABI for `clobber_abi` diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 2626631d800..fff1bcd72bc 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -30,6 +30,9 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic +ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier + .suggestion = remove safe from this item + ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body .invalid = the invalid body @@ -167,6 +170,9 @@ ast_passes_invalid_unnamed_field_ty = unnamed fields can only have struct or union types .label = not a struct or union +ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier + .suggestion = remove safe from this item + ast_passes_item_underscore = `{$kind}` items in this context need a name .label = `_` is not a valid name for this `{$kind}` item diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index cad1fc79d7f..e89b412687d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -456,15 +456,29 @@ impl<'a> AstValidator<'a> { } } - fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) { - if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) - && (self.extern_mod_safety == Some(Safety::Default) - || !self.features.unsafe_extern_blocks) - { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span, - block: self.current_extern_span(), - }); + fn check_item_safety(&self, span: Span, safety: Safety) { + match self.extern_mod_safety { + Some(extern_safety) => { + if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) + && (extern_safety == Safety::Default || !self.features.unsafe_extern_blocks) + { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span: span, + block: self.current_extern_span(), + }); + } + } + None => { + if matches!(safety, Safety::Safe(_)) { + self.dcx().emit_err(errors::InvalidSafetyOnItem { span }); + } + } + } + } + + fn check_bare_fn_safety(&self, span: Span, safety: Safety) { + if matches!(safety, Safety::Safe(_)) { + self.dcx().emit_err(errors::InvalidSafetyOnBareFn { span }); } } @@ -746,6 +760,7 @@ impl<'a> AstValidator<'a> { fn visit_ty_common(&mut self, ty: &'a Ty) { match &ty.kind { TyKind::BareFn(bfty) => { + self.check_bare_fn_safety(bfty.decl_span, bfty.safety); self.check_fn_decl(&bfty.decl, SelfSemantic::No); Self::check_decl_no_pat(&bfty.decl, |span, _, _| { self.dcx().emit_err(errors::PatternFnPointer { span }); @@ -1174,11 +1189,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } } - ItemKind::Static(box StaticItem { expr: None, .. }) => { - self.dcx().emit_err(errors::StaticWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); + ItemKind::Static(box StaticItem { expr, safety, .. }) => { + self.check_item_safety(item.span, *safety); + + if expr.is_none() { + self.dcx().emit_err(errors::StaticWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } ItemKind::TyAlias( ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. }, @@ -1212,7 +1231,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match &fi.kind { ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => { - self.check_foreign_item_safety(fi.span, sig.header.safety); self.check_defaultness(fi.span, *defaultness); self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); @@ -1233,7 +1251,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => { - self.check_foreign_item_safety(fi.span, *safety); + self.check_item_safety(fi.span, *safety); self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); } @@ -1453,6 +1471,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }; self.check_fn_decl(fk.decl(), self_semantic); + if let Some(&FnHeader { safety, .. }) = fk.header() { + self.check_item_safety(span, safety); + } + self.check_c_variadic_type(fk); // Functions cannot both be `const async` or `const gen` diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 601910ded20..96c476b271c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -226,6 +226,20 @@ pub struct InvalidSafetyOnExtern { } #[derive(Diagnostic)] +#[diag(ast_passes_item_invalid_safety)] +pub struct InvalidSafetyOnItem { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_bare_fn_invalid_safety)] +pub struct InvalidSafetyOnBareFn { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(ast_passes_bound_in_context)] pub struct BoundInContext<'a> { #[primary_span] diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 40b58500598..bf1c1b1433e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1110,7 +1110,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, } impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for OpaqueFolder<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 60e63b956db..597ebd97365 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug, ty::Instance}; -use rustc_span::{Pos, Span}; +use rustc_span::{sym, Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; use tracing::debug; @@ -64,7 +64,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let mut layout = None; let ty = if let Some(ref place) = place { layout = Some(&place.layout); - llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout) + llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout, instance) } else if matches!( reg.reg_class(), InlineAsmRegClass::X86( @@ -112,7 +112,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // so we just use the type of the input. &in_value.layout }; - let ty = llvm_fixup_output_type(self.cx, reg.reg_class(), layout); + let ty = llvm_fixup_output_type(self.cx, reg.reg_class(), layout, instance); output_types.push(ty); op_idx.insert(idx, constraints.len()); let prefix = if late { "=" } else { "=&" }; @@ -127,8 +127,13 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { for (idx, op) in operands.iter().enumerate() { match *op { InlineAsmOperandRef::In { reg, value } => { - let llval = - llvm_fixup_input(self, value.immediate(), reg.reg_class(), &value.layout); + let llval = llvm_fixup_input( + self, + value.immediate(), + reg.reg_class(), + &value.layout, + instance, + ); inputs.push(llval); op_idx.insert(idx, constraints.len()); constraints.push(reg_to_llvm(reg, Some(&value.layout))); @@ -139,6 +144,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { in_value.immediate(), reg.reg_class(), &in_value.layout, + instance, ); inputs.push(value); @@ -341,7 +347,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } else { self.extract_value(result, op_idx[&idx] as u64) }; - let value = llvm_fixup_output(self, value, reg.reg_class(), &place.layout); + let value = + llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); OperandValue::Immediate(value).store(self, place); } } @@ -913,12 +920,22 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty } } +fn any_target_feature_enabled( + cx: &CodegenCx<'_, '_>, + instance: Instance<'_>, + features: &[Symbol], +) -> bool { + let enabled = cx.tcx.asm_target_features(instance.def_id()); + features.iter().any(|feat| enabled.contains(feat)) +} + /// Fix up an input value to work around LLVM bugs. fn llvm_fixup_input<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, + instance: Instance<'_>, ) -> &'ll Value { let dl = &bx.tcx.data_layout; match (reg, layout.abi) { @@ -1020,6 +1037,19 @@ fn llvm_fixup_input<'ll, 'tcx>( value } } + ( + InlineAsmRegClass::Arm( + ArmInlineAsmRegClass::dreg + | ArmInlineAsmRegClass::dreg_low8 + | ArmInlineAsmRegClass::dreg_low16 + | ArmInlineAsmRegClass::qreg + | ArmInlineAsmRegClass::qreg_low4 + | ArmInlineAsmRegClass::qreg_low8, + ), + Abi::Vector { element, count: count @ (4 | 8) }, + ) if element.primitive() == Primitive::Float(Float::F16) => { + bx.bitcast(value, bx.type_vector(bx.type_i16(), count)) + } (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. @@ -1029,6 +1059,16 @@ fn llvm_fixup_input<'ll, 'tcx>( _ => value, } } + (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) + && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) => + { + // Smaller floats are always "NaN-boxed" inside larger floats on RISC-V. + let value = bx.bitcast(value, bx.type_i16()); + let value = bx.zext(value, bx.type_i32()); + let value = bx.or(value, bx.const_u32(0xFFFF_0000)); + bx.bitcast(value, bx.type_f32()) + } _ => value, } } @@ -1039,6 +1079,7 @@ fn llvm_fixup_output<'ll, 'tcx>( mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, + instance: Instance<'_>, ) -> &'ll Value { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { @@ -1130,6 +1171,19 @@ fn llvm_fixup_output<'ll, 'tcx>( value } } + ( + InlineAsmRegClass::Arm( + ArmInlineAsmRegClass::dreg + | ArmInlineAsmRegClass::dreg_low8 + | ArmInlineAsmRegClass::dreg_low16 + | ArmInlineAsmRegClass::qreg + | ArmInlineAsmRegClass::qreg_low4 + | ArmInlineAsmRegClass::qreg_low8, + ), + Abi::Vector { element, count: count @ (4 | 8) }, + ) if element.primitive() == Primitive::Float(Float::F16) => { + bx.bitcast(value, bx.type_vector(bx.type_f16(), count)) + } (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. @@ -1140,6 +1194,14 @@ fn llvm_fixup_output<'ll, 'tcx>( _ => value, } } + (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) + && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) => + { + let value = bx.bitcast(value, bx.type_i32()); + let value = bx.trunc(value, bx.type_i16()); + bx.bitcast(value, bx.type_f16()) + } _ => value, } } @@ -1149,6 +1211,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, + instance: Instance<'_>, ) -> &'ll Type { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { @@ -1233,6 +1296,19 @@ fn llvm_fixup_output_type<'ll, 'tcx>( layout.llvm_type(cx) } } + ( + InlineAsmRegClass::Arm( + ArmInlineAsmRegClass::dreg + | ArmInlineAsmRegClass::dreg_low8 + | ArmInlineAsmRegClass::dreg_low16 + | ArmInlineAsmRegClass::qreg + | ArmInlineAsmRegClass::qreg_low4 + | ArmInlineAsmRegClass::qreg_low8, + ), + Abi::Vector { element, count: count @ (4 | 8) }, + ) if element.primitive() == Primitive::Float(Float::F16) => { + cx.type_vector(cx.type_i16(), count) + } (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. @@ -1242,6 +1318,12 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } + (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) + && !any_target_feature_enabled(cx, instance, &[sym::zfhmin, sym::zfh]) => + { + cx.type_f32() + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 1a7e5bd7092..1476fe285ef 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -341,8 +341,7 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in const_eval_unallowed_heap_allocations = allocations are not allowed in {const_eval_const_context}s .label = allocation not allowed in {const_eval_const_context}s - .teach_note = - The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + .teach_note = The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. const_eval_unallowed_inline_asm = inline assembly is not allowed in {const_eval_const_context}s diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 9a26ac04b85..9d0c4908225 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -630,6 +630,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } + /// Gives raw, immutable access to the `Allocation` address, without bounds or alignment checks. + /// The caller is responsible for calling the access hooks! + pub fn get_alloc_bytes_unchecked_raw(&self, id: AllocId) -> InterpResult<'tcx, *const u8> { + let alloc = self.get_alloc_raw(id)?; + Ok(alloc.get_bytes_unchecked_raw()) + } + /// Bounds-checked *but not align-checked* allocation access. pub fn get_ptr_alloc<'a>( &'a self, @@ -713,6 +720,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok((alloc, &mut self.machine)) } + /// Gives raw, mutable access to the `Allocation` address, without bounds or alignment checks. + /// The caller is responsible for calling the access hooks! + pub fn get_alloc_bytes_unchecked_raw_mut( + &mut self, + id: AllocId, + ) -> InterpResult<'tcx, *mut u8> { + let alloc = self.get_alloc_raw_mut(id)?.0; + Ok(alloc.get_bytes_unchecked_raw_mut()) + } + /// Bounds-checked *but not align-checked* allocation access. pub fn get_ptr_alloc_mut<'a>( &'a mut self, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 08d3165867c..baaee67e787 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -441,7 +441,7 @@ where /// Take an operand, representing a pointer, and dereference it to a place. /// Corresponds to the `*` operator in Rust. - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] pub fn deref_pointer( &self, src: &impl Readable<'tcx, M::Provenance>, @@ -533,7 +533,7 @@ where /// Computes a place. You should only use this if you intend to write into this /// place; for reading, a more efficient alternative is `eval_place_to_op`. - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] pub fn eval_place( &self, mir_place: mir::Place<'tcx>, @@ -570,7 +570,7 @@ where /// Write an immediate to a place #[inline(always)] - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] pub fn write_immediate( &mut self, src: Immediate<M::Provenance>, @@ -808,7 +808,7 @@ where /// Copies the data from an operand to a place. /// `allow_transmute` indicates whether the layouts may disagree. #[inline(always)] - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn copy_op_inner( &mut self, src: &impl Readable<'tcx, M::Provenance>, @@ -837,7 +837,7 @@ where /// `allow_transmute` indicates whether the layouts may disagree. /// Also, if you use this you are responsible for validating that things get copied at the /// right type. - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] fn copy_op_no_validate( &mut self, src: &impl Readable<'tcx, M::Provenance>, @@ -914,7 +914,7 @@ where /// If the place currently refers to a local that doesn't yet have a matching allocation, /// create such an allocation. /// This is essentially `force_to_memplace`. - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "trace")] pub fn force_allocation( &mut self, place: &PlaceTy<'tcx, M::Provenance>, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 245deda50d5..7405705dd33 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1905,7 +1905,7 @@ impl HumanEmitter { // // LL | this line was highlighted // LL | this line is just for context - // ... + // ... // LL | this line is just for context // LL | this line was highlighted _ => { @@ -1926,7 +1926,7 @@ impl HumanEmitter { ) } - buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); + buffer.puts(row_num, 0, "...", Style::LineNumber); row_num += 1; if let Some((p, l)) = last_line { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c165620f657..9e2756f07ed 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1089,6 +1089,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[custom_mir]` attribute is just used for the Rust test suite", ), rustc_attr!( + TEST, rustc_dump_item_bounds, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), + rustc_attr!( + TEST, rustc_dump_predicates, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), + rustc_attr!( TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No ), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 45527bec2f2..fbd67657e3b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -449,7 +449,7 @@ declare_features! ( /// Allows `dyn* Trait` objects. (incomplete, dyn_star, "1.65.0", Some(102425)), /// Uses generic effect parameters for ~const bounds - (unstable, effects, "1.72.0", Some(102090)), + (incomplete, effects, "1.72.0", Some(102090)), /// Allows exhaustive pattern matching on types that contain uninhabited types. (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 8c740d87e95..7ed32fb9d9f 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -194,7 +194,7 @@ hir_analysis_inherent_ty_outside = cannot define inherent `impl` for a type outs .span_help = alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items hir_analysis_inherent_ty_outside_new = cannot define inherent `impl` for a type outside of the crate where the type is defined - .label = impl for type defined outside of crate. + .label = impl for type defined outside of crate .note = define and implement a trait or new type instead hir_analysis_inherent_ty_outside_primitive = cannot define inherent `impl` for primitive types outside of `core` @@ -510,7 +510,7 @@ hir_analysis_ty_param_some = type parameter `{$param}` must be used as the type .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local .only_note = only traits defined in the current crate can be implemented for a type parameter -hir_analysis_type_of = {$type_of} +hir_analysis_type_of = {$ty} hir_analysis_typeof_reserved_keyword_used = `typeof` is a reserved keyword but unimplemented @@ -544,7 +544,7 @@ hir_analysis_unrecognized_intrinsic_function = hir_analysis_unused_associated_type_bounds = unnecessary associated type bound for not object safe associated type - .note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + .note = this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` .suggestion = remove this bound hir_analysis_unused_generic_parameter = @@ -566,7 +566,7 @@ hir_analysis_value_of_associated_struct_already_specified = hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions} .label = C-variadic function must have a compatible calling convention -hir_analysis_variances_of = {$variances_of} +hir_analysis_variances_of = {$variances} hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause .label = `main` cannot have a `where` clause diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 82b57cdd106..550f38af8b5 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -397,7 +397,7 @@ struct RemapLateBound<'a, 'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -790,13 +790,13 @@ impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E where E: 'tcx, { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.ocx.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { if let ty::Alias(ty::Projection, proj) = ty.kind() - && self.interner().is_impl_trait_in_trait(proj.def_id) + && self.cx().is_impl_trait_in_trait(proj.def_id) { if let Some((ty, _)) = self.types.get(&proj.def_id) { return *ty; @@ -810,9 +810,9 @@ where self.types.insert(proj.def_id, (infer_ty, proj.args)); // Recurse into bounds for (pred, pred_span) in self - .interner() + .cx() .explicit_item_bounds(proj.def_id) - .iter_instantiated_copied(self.interner(), proj.args) + .iter_instantiated_copied(self.cx(), proj.args) { let pred = pred.fold_with(self); let pred = self.ocx.normalize( @@ -822,7 +822,7 @@ where ); self.ocx.register_obligation(traits::Obligation::new( - self.interner(), + self.cx(), ObligationCause::new( self.span, self.body_id, @@ -853,7 +853,7 @@ struct RemapHiddenTyRegions<'tcx> { impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { type Error = ErrorGuaranteed; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -2072,7 +2072,7 @@ struct ReplaceTy<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 10b097a1060..6cdbd692f73 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -322,7 +322,7 @@ struct Anonymize<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Anonymize<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 13180fa2673..683709f43f2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -429,17 +429,17 @@ pub fn check_intrinsic_type( sym::ptr_guaranteed_cmp => ( 1, - 1, + 0, vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))], tcx.types.u8, ), sym::const_allocate => { - (0, 1, vec![tcx.types.usize, tcx.types.usize], Ty::new_mut_ptr(tcx, tcx.types.u8)) + (0, 0, vec![tcx.types.usize, tcx.types.usize], Ty::new_mut_ptr(tcx, tcx.types.u8)) } sym::const_deallocate => ( 0, - 1, + 0, vec![Ty::new_mut_ptr(tcx, tcx.types.u8), tcx.types.usize, tcx.types.usize], tcx.types.unit, ), @@ -478,16 +478,16 @@ pub fn check_intrinsic_type( | sym::frem_algebraic => (1, 0, vec![param(0), param(0)], param(0)), sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), - sym::assume => (0, 1, vec![tcx.types.bool], tcx.types.unit), - sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool), - sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool), + sym::assume => (0, 0, vec![tcx.types.bool], tcx.types.unit), + sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool), + sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool), sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), sym::write_via_move => { (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) } - sym::typed_swap => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit), + sym::typed_swap => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit), sym::discriminant_value => { let assoc_items = tcx.associated_item_def_ids( @@ -566,9 +566,9 @@ pub fn check_intrinsic_type( sym::black_box => (1, 0, vec![param(0)], param(0)), - sym::is_val_statically_known => (1, 1, vec![param(0)], tcx.types.bool), + sym::is_val_statically_known => (1, 0, vec![param(0)], tcx.types.bool), - sym::const_eval_select => (4, 1, vec![param(0), param(1), param(2)], param(3)), + sym::const_eval_select => (4, 0, vec![param(0), param(1), param(2)], param(3)), sym::vtable_size | sym::vtable_align => { (0, 0, vec![Ty::new_imm_ptr(tcx, tcx.types.unit)], tcx.types.usize) @@ -576,10 +576,10 @@ pub fn check_intrinsic_type( // This type check is not particularly useful, but the `where` bounds // on the definition in `core` do the heavy lifting for checking it. - sym::aggregate_raw_ptr => (3, 1, vec![param(1), param(2)], param(0)), - sym::ptr_metadata => (2, 1, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)), + sym::aggregate_raw_ptr => (3, 0, vec![param(1), param(2)], param(0)), + sym::ptr_metadata => (2, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)), - sym::ub_checks => (0, 1, Vec::new(), tcx.types.bool), + sym::ub_checks => (0, 0, Vec::new(), tcx.types.bool), sym::simd_eq | sym::simd_ne diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 9421269e51e..5cb91603fd0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -539,7 +539,7 @@ struct TyVarReplacer<'cx, 'tcx> { } impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c6e8759327f..e5bd147352d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -45,8 +45,8 @@ use std::ops::Bound; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; -pub use type_of::test_opaque_hidden_types; +pub(crate) mod dump; mod generics_of; mod item_bounds; mod predicates_of; diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs new file mode 100644 index 00000000000..85e1c600d6d --- /dev/null +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -0,0 +1,43 @@ +use rustc_hir::def::DefKind; +use rustc_hir::def_id::CRATE_DEF_ID; +use rustc_middle::ty::TyCtxt; +use rustc_span::sym; + +pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { + if !tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { + return; + } + + for id in tcx.hir().items() { + let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue }; + + let ty = tcx.type_of(id.owner_id).instantiate_identity(); + + tcx.dcx().emit_err(crate::errors::TypeOf { span: tcx.def_span(id.owner_id), ty }); + } +} + +pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { + for id in tcx.hir_crate_items(()).owners() { + if tcx.has_attr(id, sym::rustc_dump_predicates) { + let preds = tcx.predicates_of(id).instantiate_identity(tcx).predicates; + let span = tcx.def_span(id); + + let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_predicates.as_str()); + for pred in preds { + diag.note(format!("{pred:?}")); + } + diag.emit(); + } + if tcx.has_attr(id, sym::rustc_dump_item_bounds) { + let bounds = tcx.item_bounds(id).instantiate_identity(); + let span = tcx.def_span(id); + + let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_item_bounds.as_str()); + for bound in bounds { + diag.note(format!("{bound:?}")); + } + diag.emit(); + } + } +} diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 94d6e13d751..9f198933dee 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -203,7 +203,7 @@ struct AssocTyToOpaque<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTyToOpaque<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 2684467a438..1e2b0c43233 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -15,7 +15,6 @@ use crate::errors::TypeofReservedKeywordUsed; use super::bad_placeholder; use super::ItemCtxt; -pub use opaque::test_opaque_hidden_types; mod opaque; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 2b2f07001d2..d1048b742a0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -1,28 +1,14 @@ use rustc_errors::StashKey; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; +use rustc_span::DUMMY_SP; -use crate::errors::{TaitForwardCompat, TaitForwardCompat2, TypeOf, UnconstrainedOpaqueType}; - -pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { - let mut res = Ok(()); - if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { - for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { - let type_of = tcx.type_of(id.owner_id).instantiate_identity(); - - res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of })); - } - } - } - res -} +use crate::errors::{TaitForwardCompat, TaitForwardCompat2, UnconstrainedOpaqueType}; /// Checks "defining uses" of opaque `impl Trait` in associated types. /// These can only be defined by associated items of the same trait. diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index cff8d5a5ea5..44025c3cd61 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -682,7 +682,7 @@ pub(crate) enum CannotCaptureLateBound { pub(crate) struct VariancesOf { #[primary_span] pub span: Span, - pub variances_of: String, + pub variances: String, } #[derive(Diagnostic)] @@ -690,7 +690,7 @@ pub(crate) struct VariancesOf { pub(crate) struct TypeOf<'tcx> { #[primary_span] pub span: Span, - pub type_of: Ty<'tcx>, + pub ty: Ty<'tcx>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1927359421d..0428abcdf24 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -151,10 +151,6 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate(tcx: TyCtxt<'_>) { let _prof_timer = tcx.sess.timer("type_check_crate"); - if tcx.features().rustc_attrs { - let _ = tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); - } - tcx.sess.time("coherence_checking", || { tcx.hir().par_for_each_module(|module| { let _ = tcx.ensure().check_mod_type_wf(module); @@ -169,11 +165,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { }); if tcx.features().rustc_attrs { - let _ = tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); - } - - if tcx.features().rustc_attrs { - let _ = collect::test_opaque_hidden_types(tcx); + tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx)); + tcx.sess.time("variance_dumping", || variance::dump::variances(tcx)); + collect::dump::opaque_hidden_types(tcx); + collect::dump::predicates_and_item_bounds(tcx); } // Make sure we evaluate all static and (non-associated) const items, even if unused. diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs new file mode 100644 index 00000000000..ab50d9e86ef --- /dev/null +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -0,0 +1,29 @@ +use rustc_middle::bug; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::sym; + +pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { + for id in tcx.hir().items() { + if !tcx.has_attr(id.owner_id, sym::rustc_outlives) { + continue; + } + + let preds = tcx.inferred_outlives_of(id.owner_id); + let mut preds: Vec<_> = preds + .iter() + .map(|(pred, _)| match pred.kind().skip_binder() { + ty::ClauseKind::RegionOutlives(p) => p.to_string(), + ty::ClauseKind::TypeOutlives(p) => p.to_string(), + err => bug!("unexpected clause {:?}", err), + }) + .collect(); + preds.sort(); + + let span = tcx.def_span(id.owner_id); + let mut err = tcx.dcx().struct_span_err(span, sym::rustc_outlives.as_str()); + for pred in preds { + err.note(pred); + } + err.emit(); + } +} diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 97fd7731b1e..1f74ebf99f1 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -5,10 +5,9 @@ use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt, Upcast}; use rustc_span::Span; +pub(crate) mod dump; mod explicit; mod implicit_infer; -/// Code to write unit test for outlives. -pub mod test; mod utils; pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs deleted file mode 100644 index e9b6c679bd5..00000000000 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ /dev/null @@ -1,31 +0,0 @@ -use rustc_middle::bug; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::{symbol::sym, ErrorGuaranteed}; - -pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { - let mut res = Ok(()); - for id in tcx.hir().items() { - // For unit testing: check for a special "rustc_outlives" - // attribute and report an error with various results if found. - if tcx.has_attr(id.owner_id, sym::rustc_outlives) { - let predicates = tcx.inferred_outlives_of(id.owner_id); - let mut pred: Vec<String> = predicates - .iter() - .map(|(out_pred, _)| match out_pred.kind().skip_binder() { - ty::ClauseKind::RegionOutlives(p) => p.to_string(), - ty::ClauseKind::TypeOutlives(p) => p.to_string(), - err => bug!("unexpected clause {:?}", err), - }) - .collect(); - pred.sort(); - - let span = tcx.def_span(id.owner_id); - let mut err = tcx.dcx().struct_span_err(span, "rustc_outlives"); - for p in pred { - err.note(p); - } - res = Err(err.emit()); - } - } - res -} diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs new file mode 100644 index 00000000000..1a17dabb677 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -0,0 +1,32 @@ +use rustc_hir::def::DefKind; +use rustc_hir::def_id::CRATE_DEF_ID; +use rustc_middle::ty::TyCtxt; +use rustc_span::symbol::sym; + +pub(crate) fn variances(tcx: TyCtxt<'_>) { + if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { + for id in tcx.hir().items() { + let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue }; + + let variances = tcx.variances_of(id.owner_id); + + tcx.dcx().emit_err(crate::errors::VariancesOf { + span: tcx.def_span(id.owner_id), + variances: format!("{variances:?}"), + }); + } + } + + for id in tcx.hir().items() { + if !tcx.has_attr(id.owner_id, sym::rustc_variance) { + continue; + } + + let variances = tcx.variances_of(id.owner_id); + + tcx.dcx().emit_err(crate::errors::VariancesOf { + span: tcx.def_span(id.owner_id), + variances: format!("{variances:?}"), + }); + } +} diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 1977451f39e..29f96e27b64 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -22,8 +22,7 @@ mod constraints; /// Code to solve constraints and write out the results. mod solve; -/// Code to write unit tests of variance. -pub mod test; +pub(crate) mod dump; /// Code for transforming variances. mod xform; diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs deleted file mode 100644 index c211e1af046..00000000000 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ /dev/null @@ -1,37 +0,0 @@ -use rustc_hir::def::DefKind; -use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::sym; -use rustc_span::ErrorGuaranteed; - -use crate::errors; - -pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { - let mut res = Ok(()); - if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { - for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { - let variances_of = tcx.variances_of(id.owner_id); - - res = Err(tcx.dcx().emit_err(errors::VariancesOf { - span: tcx.def_span(id.owner_id), - variances_of: format!("{variances_of:?}"), - })); - } - } - } - - // For unit testing: check for a special "rustc_variance" - // attribute and report an error with various results if found. - for id in tcx.hir().items() { - if tcx.has_attr(id.owner_id, sym::rustc_variance) { - let variances_of = tcx.variances_of(id.owner_id); - - res = Err(tcx.dcx().emit_err(errors::VariancesOf { - span: tcx.def_span(id.owner_id), - variances_of: format!("{variances_of:?}"), - })); - } - } - res -} diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 2714be1f9b4..aea0114167e 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -847,7 +847,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.fcx.tcx } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index bc2592b43f3..1659f3d0493 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -304,7 +304,7 @@ struct Canonicalizer<'cx, 'tcx> { } impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -773,7 +773,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); let br = ty::BoundRegion { var, kind: ty::BrAnon }; - ty::Region::new_bound(self.interner(), self.binder_index, br) + ty::Region::new_bound(self.cx(), self.binder_index, br) } /// Given a type variable `ty_var` of the given kind, first check diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index cb0e13652e8..d7349abc44c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -158,7 +158,7 @@ struct ClosureEraser<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 50526c964ed..de4267f7cea 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -118,7 +118,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> { | ty::RePlaceholder(..) | ty::ReStatic | ty::ReError(_) - | ty::ReErased => self.interner().lifetimes.re_erased, + | ty::ReErased => self.cx().lifetimes.re_erased, } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4d6ddd7ba66..a3cf588da1c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1719,7 +1719,7 @@ struct InferenceLiteralEraser<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1859,7 +1859,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceParamAndInferWithPlaceholder<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 830d79f52b9..ed75fd183f2 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -24,7 +24,7 @@ impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -66,7 +66,7 @@ impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -85,7 +85,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(TypeFolder::interner(self), vid), + .opportunistic_resolve_var(TypeFolder::cx(self), vid), _ => r, } } @@ -121,7 +121,7 @@ struct FullTypeResolver<'a, 'tcx> { impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> { type Error = FixupError; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index a086c82c92e..f15bd0babee 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -183,7 +183,7 @@ pub struct InferenceFudger<'a, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 468673f05c1..fdedf2c2e6d 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -75,7 +75,7 @@ lint_builtin_deprecated_attr_default_suggestion = remove this attribute lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link} .msg_suggestion = {$msg} .default_suggestion = remove this attribute -lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used. +lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used lint_builtin_deref_nullptr = dereferencing a null pointer .label = this code causes undefined behavior when executed @@ -213,7 +213,7 @@ lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better pe lint_default_source = `forbid` lint level is the default for {$id} lint_deprecated_lint_name = - lint name `{$name}` is deprecated and may not have an effect in the future. + lint name `{$name}` is deprecated and may not have an effect in the future .suggestion = change it to .help = change it to {$replace} @@ -244,11 +244,11 @@ lint_duplicate_matcher_binding = duplicate matcher binding lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type - .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum. + .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum lint_enum_intrinsics_mem_variant = the return value of `mem::variant_count` is unspecified when called with a non-enum type - .note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum. + .note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 24dd337e699..300dac442d5 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -390,7 +390,7 @@ struct ReplaceLocalTypesWithInfer<'a, 'tcx, F: FnMut(DefId) -> bool> { impl<'a, 'tcx, F: FnMut(DefId) -> bool> TypeFolder<TyCtxt<'tcx>> for ReplaceLocalTypesWithInfer<'a, 'tcx, F> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 932603cd6b2..415399ed06c 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -248,13 +248,13 @@ metadata_rustc_lib_required = .help = try adding `extern crate rustc_driver;` at the top level of this crate metadata_stable_crate_id_collision = - found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values. + found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values metadata_std_required = `std` is required by `{$current_crate}` because it does not declare `#![no_std]` metadata_symbol_conflicts_current = - the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two metadata_target_no_std_support = the `{$locator_triple}` target may not support the standard library diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 2fc466c0e7e..cac3bf948a0 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -40,9 +40,16 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Targe /// Gives direct access to the raw underlying storage. /// /// Crucially this pointer is compatible with: - /// - other pointers retunred by this method, and + /// - other pointers returned by this method, and /// - references returned from `deref()`, as long as there was no write. fn as_mut_ptr(&mut self) -> *mut u8; + + /// Gives direct access to the raw underlying storage. + /// + /// Crucially this pointer is compatible with: + /// - other pointers returned by this method, and + /// - references returned from `deref()`, as long as there was no write. + fn as_ptr(&self) -> *const u8; } /// Default `bytes` for `Allocation` is a `Box<u8>`. @@ -62,6 +69,11 @@ impl AllocBytes for Box<[u8]> { // Carefully avoiding any intermediate references. ptr::addr_of_mut!(**self).cast() } + + fn as_ptr(&self) -> *const u8 { + // Carefully avoiding any intermediate references. + ptr::addr_of!(**self).cast() + } } /// This type represents an Allocation in the Miri/CTFE core engine. @@ -490,19 +502,27 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> self.provenance.clear(range, cx)?; assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check - // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. + // Crucially, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); let len = range.end().bytes_usize() - range.start.bytes_usize(); Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len)) } /// This gives direct mutable access to the entire buffer, just exposing their internal state - /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if + /// without resetting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if /// `OFFSET_IS_ADDR` is true. pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 { assert!(Prov::OFFSET_IS_ADDR); self.bytes.as_mut_ptr() } + + /// This gives direct immutable access to the entire buffer, just exposing their internal state + /// without resetting anything. Directly exposes `AllocBytes::as_ptr`. Only works if + /// `OFFSET_IS_ADDR` is true. + pub fn get_bytes_unchecked_raw(&self) -> *const u8 { + assert!(Prov::OFFSET_IS_ADDR); + self.bytes.as_ptr() + } } /// Reading and writing. diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 126387db1d9..412cfc1fc7a 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -289,19 +289,7 @@ impl<'tcx> UnOp { pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { match self { UnOp::Not | UnOp::Neg => arg_ty, - UnOp::PtrMetadata => { - let pointee_ty = arg_ty - .builtin_deref(true) - .unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}")); - if pointee_ty.is_trivially_sized(tcx) { - tcx.types.unit - } else { - let Some(metadata_def_id) = tcx.lang_items().metadata_type() else { - bug!("No metadata_type lang item while looking at {arg_ty:?}") - }; - Ty::new_projection(tcx, metadata_def_id, [pointee_ty]) - } - } + UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx), } } } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 90f80f90767..7bc4c60f102 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -53,7 +53,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> { self, folder: &mut F, ) -> Result<Self, F::Error> { - Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData { + Ok(FallibleTypeFolder::cx(folder).mk_external_constraints(ExternalConstraintsData { region_constraints: self.region_constraints.clone().try_fold_with(folder)?, opaque_types: self .opaque_types @@ -68,7 +68,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> { } fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self { - TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData { + TypeFolder::cx(folder).mk_external_constraints(ExternalConstraintsData { region_constraints: self.region_constraints.clone().fold_with(folder), opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), normalization_nested_goals: self.normalization_nested_goals.clone().fold_with(folder), @@ -94,19 +94,17 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> { self, folder: &mut F, ) -> Result<Self, F::Error> { - Ok(FallibleTypeFolder::interner(folder).mk_predefined_opaques_in_body( - PredefinedOpaquesData { - opaque_types: self - .opaque_types - .iter() - .map(|opaque| opaque.try_fold_with(folder)) - .collect::<Result<_, F::Error>>()?, - }, - )) + Ok(FallibleTypeFolder::cx(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData { + opaque_types: self + .opaque_types + .iter() + .map(|opaque| opaque.try_fold_with(folder)) + .collect::<Result<_, F::Error>>()?, + })) } fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self { - TypeFolder::interner(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData { + TypeFolder::cx(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), }) } diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index fa44fbaa059..3aa01fbef2f 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -41,7 +41,7 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Expander<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8c3ee6955f5..4bf22337991 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -579,7 +579,7 @@ pub struct MakeSuggestableFolder<'tcx> { impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { type Error = (); - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index cd6e7df31f7..9d5481f3df3 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -37,7 +37,7 @@ struct RegionEraserVisitor<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 9b5b1430c27..81ea8738e72 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -28,7 +28,7 @@ where G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>, H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>, { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -99,7 +99,7 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -176,7 +176,7 @@ impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D> where D: BoundVarReplacerDelegate<'tcx>, { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 83d45ca78d9..5ac3168196a 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -591,7 +591,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> { match self.len() { 1 => { let param0 = self[0].try_fold_with(folder)?; - if param0 == self[0] { Ok(self) } else { Ok(folder.interner().mk_args(&[param0])) } + if param0 == self[0] { Ok(self) } else { Ok(folder.cx().mk_args(&[param0])) } } 2 => { let param0 = self[0].try_fold_with(folder)?; @@ -599,7 +599,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> { if param0 == self[0] && param1 == self[1] { Ok(self) } else { - Ok(folder.interner().mk_args(&[param0, param1])) + Ok(folder.cx().mk_args(&[param0, param1])) } } 0 => Ok(self), @@ -635,7 +635,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> { if param0 == self[0] && param1 == self[1] { Ok(self) } else { - Ok(folder.interner().mk_type_list(&[param0, param1])) + Ok(folder.cx().mk_type_list(&[param0, param1])) } } _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index efaf9c7231b..1ba8820e0e1 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -873,7 +873,7 @@ fn polymorphize<'tcx>( } impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for PolymorphizationFolder<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index fb16cf5bd36..96f00e1d306 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -173,7 +173,7 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for NormalizeAfterErasingRegionsFolder<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -211,7 +211,7 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for TryNormalizeAfterErasingRegionsFolder<'tcx> { type Error = NormalizationError<'tcx>; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 08b2f9e8920..70a54e96d36 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -95,7 +95,7 @@ impl<'tcx> ReverseMapper<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -144,7 +144,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { ) .emit(); - ty::Region::new_error(self.interner(), e) + ty::Region::new_error(self.cx(), e) } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 72cb3e13402..19700353f59 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2529,7 +2529,7 @@ struct RegionFolder<'a, 'tcx> { } impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 71e2e3e9f99..a9dca47ab43 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -335,7 +335,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Pattern<'tcx> { folder: &mut F, ) -> Result<Self, F::Error> { let pat = (*self).clone().try_fold_with(folder)?; - Ok(if pat == *self { self } else { folder.interner().mk_pat(pat) }) + Ok(if pat == *self { self } else { folder.cx().mk_pat(pat) }) } } @@ -407,7 +407,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> { | ty::Foreign(..) => return Ok(self), }; - Ok(if *self.kind() == kind { self } else { folder.interner().mk_ty_from_kind(kind) }) + Ok(if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }) } } @@ -512,7 +512,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { folder: &mut F, ) -> Result<Self, F::Error> { let new = self.kind().try_fold_with(folder)?; - Ok(folder.interner().reuse_or_mk_predicate(self, new)) + Ok(folder.cx().reuse_or_mk_predicate(self, new)) } } @@ -577,7 +577,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> { ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), }; - if kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind)) } else { Ok(self) } + if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9c8a3484aa5..709c5fe2305 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1638,6 +1638,34 @@ impl<'tcx> Ty<'tcx> { } } + /// Given a pointer or reference type, returns the type of the *pointee*'s + /// metadata. If it can't be determined exactly (perhaps due to still + /// being generic) then a projection through `ptr::Pointee` will be returned. + /// + /// This is particularly useful for getting the type of the result of + /// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata). + /// + /// Panics if `self` is not dereferencable. + #[track_caller] + pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let Some(pointee_ty) = self.builtin_deref(true) else { + bug!("Type {self:?} is not a pointer or reference type") + }; + if pointee_ty.is_trivially_sized(tcx) { + tcx.types.unit + } else { + match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) { + Ok(metadata_ty) => metadata_ty, + Err(tail_ty) => { + let Some(metadata_def_id) = tcx.lang_items().metadata_type() else { + bug!("No metadata_type lang item while looking at {self:?}") + }; + Ty::new_projection(tcx, metadata_def_id, [tail_ty]) + } + } + } + } + /// When we create a closure, we record its kind (i.e., what trait /// it implements, constrained by how it uses its borrows) into its /// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b079ed521d3..1b5efcee903 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1083,7 +1083,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1130,7 +1130,7 @@ struct WeakAliasTypeExpander<'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1795,7 +1795,7 @@ where for t in iter { new_list.push(t.try_fold_with(folder)?) } - Ok(intern(folder.interner(), &new_list)) + Ok(intern(folder.cx(), &new_list)) } Some((_, Err(err))) => { return Err(err); diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 1ee8777c274..0c277811fda 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -103,7 +103,7 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior .label = dereference of raw pointer -mir_build_exceeds_mcdc_condition_limit = Number of conditions in decision ({$num_conditions}) exceeds limit ({$max_conditions}). MC/DC analysis will not count this expression. +mir_build_exceeds_mcdc_condition_limit = number of conditions in decision ({$num_conditions}) exceeds limit ({$max_conditions}), so MC/DC analysis will not count this expression mir_build_extern_static_requires_unsafe = use of extern static is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 32c0d27f635..7e401b5482f 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -60,7 +60,15 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, _location: Location) { match rvalue { - Rvalue::NullaryOp(NullOp::UbChecks, ..) if !self.tcx.sess.ub_checks() => { + Rvalue::NullaryOp(NullOp::UbChecks, ..) + if !self + .tcx + .sess + .opts + .unstable_opts + .inline_mir_preserve_debug + .unwrap_or(self.tcx.sess.ub_checks()) => + { // If this is in optimized MIR it's because it's used later, // so if we don't need UB checks this session, give a bonus // here to offset the cost of the call later. @@ -111,12 +119,19 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } TerminatorKind::Assert { unwind, msg, .. } => { - self.penalty += - if msg.is_optional_overflow_check() && !self.tcx.sess.overflow_checks() { - INSTR_COST - } else { - CALL_PENALTY - }; + self.penalty += if msg.is_optional_overflow_check() + && !self + .tcx + .sess + .opts + .unstable_opts + .inline_mir_preserve_debug + .unwrap_or(self.tcx.sess.overflow_checks()) + { + INSTR_COST + } else { + CALL_PENALTY + }; if let UnwindAction::Cleanup(_) = unwind { self.penalty += LANDINGPAD_PENALTY; } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bfdefd5a7d6..936a7e2d9de 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -823,18 +823,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return self.simplify_cast(kind, value, to, location); } Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => { - let ty = lhs.ty(self.local_decls, self.tcx); - let lhs = self.simplify_operand(lhs, location); - let rhs = self.simplify_operand(rhs, location); - // Only short-circuit options after we called `simplify_operand` - // on both operands for side effect. - let lhs = lhs?; - let rhs = rhs?; - - if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) { - return Some(value); - } - Value::BinaryOp(op, lhs, rhs) + return self.simplify_binary(op, lhs, rhs, location); } Rvalue::UnaryOp(op, ref mut arg_op) => { return self.simplify_unary(op, arg_op, location); @@ -987,23 +976,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // `*const [T]` -> `*const T` which remove metadata. // We run on potentially-generic MIR, though, so unlike codegen // we can't always know exactly what the metadata are. - // Thankfully, equality on `ptr_metadata_ty_or_tail` gives us - // what we need: `Ok(meta_ty)` if the metadata is known, or - // `Err(tail_ty)` if not. Matching metadata is ok, but if - // that's not known, then matching tail types is also ok, - // allowing things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`. - // FIXME: Would it be worth trying to normalize, rather than - // passing the identity closure? Or are the types in the - // Cast realistically about as normalized as we can get anyway? + // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`, + // it's fine to get a projection as the type. Value::Cast { kind: CastKind::PtrToPtr, value: inner, from, to } - if from - .builtin_deref(true) - .unwrap() - .ptr_metadata_ty_or_tail(self.tcx, |t| t) - == to - .builtin_deref(true) - .unwrap() - .ptr_metadata_ty_or_tail(self.tcx, |t| t) => + if self.pointers_have_same_metadata(*from, *to) => { arg_index = *inner; was_updated = true; @@ -1070,6 +1046,52 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn simplify_binary( &mut self, op: BinOp, + lhs_operand: &mut Operand<'tcx>, + rhs_operand: &mut Operand<'tcx>, + location: Location, + ) -> Option<VnIndex> { + let lhs = self.simplify_operand(lhs_operand, location); + let rhs = self.simplify_operand(rhs_operand, location); + // Only short-circuit options after we called `simplify_operand` + // on both operands for side effect. + let mut lhs = lhs?; + let mut rhs = rhs?; + + let lhs_ty = lhs_operand.ty(self.local_decls, self.tcx); + + // If we're comparing pointers, remove `PtrToPtr` casts if the from + // types of both casts and the metadata all match. + if let BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge = op + && lhs_ty.is_any_ptr() + && let Value::Cast { + kind: CastKind::PtrToPtr, value: lhs_value, from: lhs_from, .. + } = self.get(lhs) + && let Value::Cast { + kind: CastKind::PtrToPtr, value: rhs_value, from: rhs_from, .. + } = self.get(rhs) + && lhs_from == rhs_from + && self.pointers_have_same_metadata(*lhs_from, lhs_ty) + { + lhs = *lhs_value; + rhs = *rhs_value; + if let Some(op) = self.try_as_operand(lhs, location) { + *lhs_operand = op; + } + if let Some(op) = self.try_as_operand(rhs, location) { + *rhs_operand = op; + } + } + + if let Some(value) = self.simplify_binary_inner(op, lhs_ty, lhs, rhs) { + return Some(value); + } + let value = Value::BinaryOp(op, lhs, rhs); + Some(self.insert(value)) + } + + fn simplify_binary_inner( + &mut self, + op: BinOp, lhs_ty: Ty<'tcx>, lhs: VnIndex, rhs: VnIndex, @@ -1228,6 +1250,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } + // PtrToPtr-then-PtrToPtr can skip the intermediate step if let PtrToPtr = kind && let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } = *self.get(value) @@ -1235,7 +1258,25 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { { from = inner_from; value = inner_value; - *kind = PtrToPtr; + was_updated = true; + if inner_from == to { + return Some(inner_value); + } + } + + // PtrToPtr-then-Transmute can just transmute the original, so long as the + // PtrToPtr didn't change metadata (and thus the size of the pointer) + if let Transmute = kind + && let Value::Cast { + kind: PtrToPtr, + value: inner_value, + from: inner_from, + to: inner_to, + } = *self.get(value) + && self.pointers_have_same_metadata(inner_from, inner_to) + { + from = inner_from; + value = inner_value; was_updated = true; if inner_from == to { return Some(inner_value); @@ -1289,6 +1330,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Fallback: a symbolic `Len`. Some(self.insert(Value::Len(inner))) } + + fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool { + let left_meta_ty = left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); + let right_meta_ty = right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); + if left_meta_ty == right_meta_ty { + true + } else if let Ok(left) = + self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty) + && let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty) + { + left == right + } else { + false + } + } } fn op_to_prop_const<'tcx>( diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index ecdca8292b4..3f4d2b65ff2 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -60,7 +60,7 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { let ccx = ConstCx::new(tcx, body); let (mut temps, all_candidates) = collect_temps_and_candidates(&ccx); - let promotable_candidates = validate_candidates(&ccx, &mut temps, &all_candidates); + let promotable_candidates = validate_candidates(&ccx, &mut temps, all_candidates); let promoted = promote_candidates(body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); @@ -98,8 +98,8 @@ struct Collector<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { + #[instrument(level = "debug", skip(self))] fn visit_local(&mut self, index: Local, context: PlaceContext, location: Location) { - debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location); // We're only interested in temporaries and the return place match self.ccx.body.local_kind(index) { LocalKind::Arg => return, @@ -111,20 +111,15 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { // then it's constant and thus drop is noop. // Non-uses are also irrelevant. if context.is_drop() || !context.is_use() { - debug!( - "visit_local: context.is_drop={:?} context.is_use={:?}", - context.is_drop(), - context.is_use(), - ); + debug!(is_drop = context.is_drop(), is_use = context.is_use()); return; } let temp = &mut self.temps[index]; - debug!("visit_local: temp={:?}", temp); + debug!(?temp); *temp = match *temp { TempState::Undefined => match context { - PlaceContext::MutatingUse(MutatingUseContext::Store) - | PlaceContext::MutatingUse(MutatingUseContext::Call) => { + PlaceContext::MutatingUse(MutatingUseContext::Store | MutatingUseContext::Call) => { TempState::Defined { location, uses: 0, valid: Err(()) } } _ => TempState::Unpromotable, @@ -137,7 +132,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { | PlaceContext::NonMutatingUse(_) => true, PlaceContext::MutatingUse(_) | PlaceContext::NonUse(_) => false, }; - debug!("visit_local: allowed_use={:?}", allowed_use); + debug!(?allowed_use); if allowed_use { *uses += 1; return; @@ -146,6 +141,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { } TempState::Unpromotable | TempState::PromotedOut => TempState::Unpromotable, }; + debug!(?temp); } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { @@ -695,15 +691,12 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_candidates( ccx: &ConstCx<'_, '_>, temps: &mut IndexSlice<Local, TempState>, - candidates: &[Candidate], + mut candidates: Vec<Candidate>, ) -> Vec<Candidate> { let mut validator = Validator { ccx, temps, promotion_safe_blocks: None }; + candidates.retain(|&candidate| validator.validate_candidate(candidate).is_ok()); candidates - .iter() - .copied() - .filter(|&candidate| validator.validate_candidate(candidate).is_ok()) - .collect() } struct Promoter<'a, 'tcx> { @@ -972,7 +965,12 @@ fn promote_candidates<'tcx>( candidates: Vec<Candidate>, ) -> IndexVec<Promoted, Body<'tcx>> { // Visit candidates in reverse, in case they're nested. - debug!("promote_candidates({:?})", candidates); + debug!(promote_candidates = ?candidates); + + // eagerly fail fast + if candidates.is_empty() { + return IndexVec::new(); + } let mut promotions = IndexVec::new(); diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index a81fd03d034..695d02705ab 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -7,7 +7,7 @@ use rustc_type_ir::{ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Interner, }; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; /// Whether we're canonicalizing a query input or the query response. /// @@ -38,8 +38,8 @@ pub enum CanonicalizeMode { }, } -pub struct Canonicalizer<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> { - infcx: &'a Infcx, +pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> { + delegate: &'a D, canonicalize_mode: CanonicalizeMode, variables: &'a mut Vec<I::GenericArg>, @@ -47,15 +47,15 @@ pub struct Canonicalizer<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> { binder_index: ty::DebruijnIndex, } -impl<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, Infcx, I> { +impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> { pub fn canonicalize<T: TypeFoldable<I>>( - infcx: &'a Infcx, + delegate: &'a D, canonicalize_mode: CanonicalizeMode, variables: &'a mut Vec<I::GenericArg>, value: T, ) -> ty::Canonical<I, T> { let mut canonicalizer = Canonicalizer { - infcx, + delegate, canonicalize_mode, variables, @@ -70,7 +70,7 @@ impl<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, Inf let (max_universe, variables) = canonicalizer.finalize(); - let defining_opaque_types = infcx.defining_opaque_types(); + let defining_opaque_types = delegate.defining_opaque_types(); Canonical { defining_opaque_types, max_universe, variables, value } } @@ -102,7 +102,7 @@ impl<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, Inf .max() .unwrap_or(ty::UniverseIndex::ROOT); - let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos); + let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos); return (max_universe, var_infos); } } @@ -206,16 +206,14 @@ impl<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, Inf } } - let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos); + let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos); (curr_compressed_uv, var_infos) } } -impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> - for Canonicalizer<'_, Infcx, I> -{ - fn interner(&self) -> I { - self.infcx.interner() +impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicalizer<'_, D, I> { + fn cx(&self) -> I { + self.delegate.cx() } fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> @@ -267,14 +265,14 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> ty::ReVar(vid) => { assert_eq!( - self.infcx.opportunistic_resolve_lt_var(vid), + self.delegate.opportunistic_resolve_lt_var(vid), r, "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Region(self.infcx.universe_of_lt(vid).unwrap()) + CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) } } } @@ -294,7 +292,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> var }); - Region::new_anon_bound(self.interner(), self.binder_index, var) + Region::new_anon_bound(self.cx(), self.binder_index, var) } fn fold_ty(&mut self, t: I::Ty) -> I::Ty { @@ -302,20 +300,20 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> ty::Infer(i) => match i { ty::TyVar(vid) => { assert_eq!( - self.infcx.opportunistic_resolve_ty_var(vid), + self.delegate.opportunistic_resolve_ty_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); CanonicalVarKind::Ty(CanonicalTyVarKind::General( - self.infcx + self.delegate .universe_of_ty(vid) .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), )) } ty::IntVar(vid) => { assert_eq!( - self.infcx.opportunistic_resolve_int_var(vid), + self.delegate.opportunistic_resolve_int_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); @@ -323,7 +321,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> } ty::FloatVar(vid) => { assert_eq!( - self.infcx.opportunistic_resolve_float_var(vid), + self.delegate.opportunistic_resolve_float_var(vid), t, "ty vid should have been resolved fully before canonicalization" ); @@ -383,7 +381,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> }), ); - Ty::new_anon_bound(self.interner(), self.binder_index, var) + Ty::new_anon_bound(self.cx(), self.binder_index, var) } fn fold_const(&mut self, c: I::Const) -> I::Const { @@ -391,11 +389,11 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> ty::ConstKind::Infer(i) => match i { ty::InferConst::Var(vid) => { assert_eq!( - self.infcx.opportunistic_resolve_ct_var(vid), + self.delegate.opportunistic_resolve_ct_var(vid), c, "const vid should have been resolved fully before canonicalization" ); - CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap()) + CanonicalVarKind::Const(self.delegate.universe_of_ct(vid).unwrap()) } ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect, ty::InferConst::Fresh(_) => todo!(), @@ -431,6 +429,6 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> }), ); - Const::new_anon_bound(self.interner(), self.binder_index, var) + Const::new_anon_bound(self.cx(), self.binder_index, var) } } diff --git a/compiler/rustc_next_trait_solver/src/infcx.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index c249eb94cf6..6626acfe963 100644 --- a/compiler/rustc_next_trait_solver/src/infcx.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -7,14 +7,14 @@ use rustc_type_ir::{self as ty, Interner}; pub trait SolverDelegate: Sized { type Interner: Interner; - fn interner(&self) -> Self::Interner; + fn cx(&self) -> Self::Interner; type Span: Copy; fn solver_mode(&self) -> SolverMode; fn build_with_canonical<V>( - interner: Self::Interner, + cx: Self::Interner, solver_mode: SolverMode, canonical: &ty::Canonical<Self::Interner, V>, ) -> (Self, V, ty::CanonicalVarValues<Self::Interner>) @@ -102,7 +102,7 @@ pub trait SolverDelegate: Sized { // FIXME: This is only here because elaboration lives in `rustc_infer`! fn elaborate_supertraits( - interner: Self::Interner, + cx: Self::Interner, trait_ref: ty::Binder<Self::Interner, ty::TraitRef<Self::Interner>>, ) -> impl Iterator<Item = ty::Binder<Self::Interner, ty::TraitRef<Self::Interner>>>; diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index ea3e18872fa..a6a9c01faaa 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -5,6 +5,6 @@ //! So if you got to this crate from the old solver, it's totally normal. pub mod canonicalizer; -pub mod infcx; +pub mod delegate; pub mod resolve; pub mod solve; diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 3d8d957eaae..6ed58d0e4fb 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -1,4 +1,4 @@ -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::visit::TypeVisitableExt; @@ -8,37 +8,37 @@ use rustc_type_ir::{self as ty, Interner}; // EAGER RESOLUTION /// Resolves ty, region, and const vars to their inferred values or their root vars. -pub struct EagerResolver<'a, Infcx, I = <Infcx as SolverDelegate>::Interner> +pub struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - infcx: &'a Infcx, + delegate: &'a D, } -impl<'a, Infcx: SolverDelegate> EagerResolver<'a, Infcx> { - pub fn new(infcx: &'a Infcx) -> Self { - EagerResolver { infcx } +impl<'a, D: SolverDelegate> EagerResolver<'a, D> { + pub fn new(delegate: &'a D) -> Self { + EagerResolver { delegate } } } -impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> { - fn interner(&self) -> I { - self.infcx.interner() +impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, D> { + fn cx(&self) -> I { + self.delegate.cx() } fn fold_ty(&mut self, t: I::Ty) -> I::Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { - let resolved = self.infcx.opportunistic_resolve_ty_var(vid); + let resolved = self.delegate.opportunistic_resolve_ty_var(vid); if t != resolved && resolved.has_infer() { resolved.fold_with(self) } else { resolved } } - ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid), - ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid), + ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid), + ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid), _ => { if t.has_infer() { t.super_fold_with(self) @@ -51,7 +51,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerRe fn fold_region(&mut self, r: I::Region) -> I::Region { match r.kind() { - ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), + ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid), _ => r, } } @@ -59,7 +59,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerRe fn fold_const(&mut self, c: I::Const) -> I::Const { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - let resolved = self.infcx.opportunistic_resolve_ct_var(vid); + let resolved = self.delegate.opportunistic_resolve_ct_var(vid); if c != resolved && resolved.has_infer() { resolved.fold_with(self) } else { @@ -67,7 +67,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerRe } } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { - self.infcx.opportunistic_resolve_effect_var(vid) + self.delegate.opportunistic_resolve_effect_var(vid) } _ => { if c.has_infer() { diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index fbc8ac1d5d5..5a95f4edf19 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -19,12 +19,12 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner}; use tracing::{instrument, trace}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { #[instrument(level = "trace", skip(self), ret)] @@ -32,7 +32,7 @@ where &mut self, goal: Goal<I, (I::Term, I::Term, ty::AliasRelationDirection)>, ) -> QueryResult<I> { - let tcx = self.interner(); + let tcx = self.cx(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 9a1537d2606..cae9c5c8567 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -9,7 +9,7 @@ use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, Upcast as _}; use tracing::{debug, instrument}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, @@ -28,10 +28,10 @@ pub(super) struct Candidate<I: Interner> { } /// Methods used to assemble candidates for either trait or projection goals. -pub(super) trait GoalKind<Infcx, I = <Infcx as SolverDelegate>::Interner>: +pub(super) trait GoalKind<D, I = <D as SolverDelegate>::Interner>: TypeFoldable<I> + Copy + Eq + std::fmt::Display where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { fn self_ty(self) -> I::Ty; @@ -47,18 +47,18 @@ where /// work, then produce a response (typically by executing /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, ) -> Result<Candidate<I>, NoSolution>; /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. fn probe_and_consider_implied_clause( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, parent_source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, @@ -76,13 +76,13 @@ where /// additionally checking all of the supertraits and object bounds to hold, /// since they're not implied by the well-formedness of the object type. fn probe_and_consider_object_bound_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, ) -> Result<Candidate<I>, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; @@ -100,7 +100,7 @@ where } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, impl_def_id: I::DefId, ) -> Result<Candidate<I>, NoSolution>; @@ -112,7 +112,7 @@ where /// Trait goals always hold while projection goals never do. This is a bit arbitrary /// but prevents incorrect normalization while hiding any trait errors. fn consider_error_guaranteed_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, guar: I::ErrorGuaranteed, ) -> Result<Candidate<I>, NoSolution>; @@ -121,13 +121,13 @@ where /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`]. fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// A trait alias holds if the RHS traits and `where` clauses hold. fn consider_trait_alias_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -136,7 +136,7 @@ where /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`]. fn consider_builtin_sized_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -145,27 +145,27 @@ where /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`]. fn consider_builtin_copy_clone_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// A type is `PointerLike` if we can compute its layout, and that layout /// matches the layout of `usize`. fn consider_builtin_pointer_like_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// A type is a `FnPtr` if it is of `FnPtr` type. fn consider_builtin_fn_ptr_trait_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>` /// family of traits where `A` is given by the signature of the type. fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution>; @@ -173,7 +173,7 @@ where /// An async closure is known to implement the `AsyncFn<A>` family of traits /// where `A` is given by the signature of the type. fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution>; @@ -182,13 +182,13 @@ where /// is used internally to delay computation for async closures until after /// upvar analysis is performed in HIR typeck. fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -198,7 +198,7 @@ where /// the built-in types. For structs, the metadata type is given by the struct /// tail. fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -206,7 +206,7 @@ where /// `Future<Output = O>`, where `O` is given by the coroutine's return type /// that was computed during type-checking. fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -214,19 +214,19 @@ where /// `Iterator<Item = O>`, where `O` is given by the generator's yield type /// that was computed during type-checking. fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; /// A coroutine (that comes from a `gen` desugaring) is known to implement /// `FusedIterator` fn consider_builtin_fused_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -234,27 +234,27 @@ where /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield, /// and return types of the coroutine computed during type-checking. fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; fn consider_builtin_destruct_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; fn consider_builtin_transmute_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution>; @@ -266,17 +266,17 @@ where /// otherwise recompute this for codegen. This is a bit of a mess but the /// easiest way to maintain the existing behavior for now. fn consider_structural_builtin_unsize_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Vec<Candidate<I>>; } -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<Infcx>>( + pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, ) -> Vec<Candidate<I>> { @@ -291,10 +291,8 @@ where return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } - let goal: Goal<I, G> = goal.with( - self.interner(), - goal.predicate.with_self_ty(self.interner(), normalized_self_ty), - ); + let goal: Goal<I, G> = + goal.with(self.cx(), goal.predicate.with_self_ty(self.cx(), normalized_self_ty)); // Vars that show up in the rest of the goal substs may have been constrained by // normalizing the self type as well, since type variables are not uniquified. let goal = self.resolve_vars_if_possible(goal); @@ -337,12 +335,12 @@ where } #[instrument(level = "trace", skip_all)] - fn assemble_impl_candidates<G: GoalKind<Infcx>>( + fn assemble_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - let tcx = self.interner(); + let tcx = self.cx(); tcx.for_each_relevant_impl( goal.predicate.trait_def_id(tcx), goal.predicate.self_ty(), @@ -363,12 +361,12 @@ where } #[instrument(level = "trace", skip_all)] - fn assemble_builtin_impl_candidates<G: GoalKind<Infcx>>( + fn assemble_builtin_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - let tcx = self.interner(); + let tcx = self.cx(); let trait_def_id = goal.predicate.trait_def_id(tcx); // N.B. When assembling built-in candidates for lang items that are also @@ -394,9 +392,9 @@ where G::consider_builtin_pointer_like_candidate(self, goal) } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) { G::consider_builtin_fn_ptr_trait_candidate(self, goal) - } else if let Some(kind) = self.interner().fn_trait_kind_from_def_id(trait_def_id) { + } else if let Some(kind) = self.cx().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) - } else if let Some(kind) = self.interner().async_fn_trait_kind_from_def_id(trait_def_id) { + } else if let Some(kind) = self.cx().async_fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_async_fn_trait_candidates(self, goal, kind) } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) { G::consider_builtin_async_fn_kind_helper_candidate(self, goal) @@ -436,7 +434,7 @@ where } #[instrument(level = "trace", skip_all)] - fn assemble_param_env_candidates<G: GoalKind<Infcx>>( + fn assemble_param_env_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, @@ -453,7 +451,7 @@ where } #[instrument(level = "trace", skip_all)] - fn assemble_alias_bound_candidates<G: GoalKind<Infcx>>( + fn assemble_alias_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, @@ -472,7 +470,7 @@ where /// If so, continue searching by recursively calling after normalization. // FIXME: This may recurse infinitely, but I can't seem to trigger it without // hitting another overflow error something. Add a depth parameter needed later. - fn assemble_alias_bound_candidates_recur<G: GoalKind<Infcx>>( + fn assemble_alias_bound_candidates_recur<G: GoalKind<D>>( &mut self, self_ty: I::Ty, goal: Goal<I, G>, @@ -523,15 +521,13 @@ where ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), ty::Alias(ty::Inherent | ty::Weak, _) => { - self.interner().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); + self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); return; } }; - for assumption in self - .interner() - .item_bounds(alias_ty.def_id) - .iter_instantiated(self.interner(), &alias_ty.args) + for assumption in + self.cx().item_bounds(alias_ty.def_id).iter_instantiated(self.cx(), &alias_ty.args) { candidates.extend(G::probe_and_consider_implied_clause( self, @@ -556,12 +552,12 @@ where } #[instrument(level = "trace", skip_all)] - fn assemble_object_bound_candidates<G: GoalKind<Infcx>>( + fn assemble_object_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - let tcx = self.interner(); + let tcx = self.cx(); if !tcx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(tcx)) { return; } @@ -629,8 +625,7 @@ where // a projection goal. if let Some(principal) = bounds.principal() { let principal_trait_ref = principal.with_self_ty(tcx, self_ty); - for (idx, assumption) in - Infcx::elaborate_supertraits(tcx, principal_trait_ref).enumerate() + for (idx, assumption) in D::elaborate_supertraits(tcx, principal_trait_ref).enumerate() { candidates.extend(G::probe_and_consider_object_bound_candidate( self, @@ -649,12 +644,12 @@ where /// To do so we add an ambiguous candidate in case such an unknown impl could /// apply to the current goal. #[instrument(level = "trace", skip_all)] - fn assemble_coherence_unknowable_candidates<G: GoalKind<Infcx>>( + fn assemble_coherence_unknowable_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - let tcx = self.interner(); + let tcx = self.cx(); candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( |ecx| { @@ -678,12 +673,12 @@ where // to improve this however. However, this should make it fairly straightforward to refine // the filtering going forward, so it seems alright-ish for now. #[instrument(level = "debug", skip(self, goal))] - fn discard_impls_shadowed_by_env<G: GoalKind<Infcx>>( + fn discard_impls_shadowed_by_env<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - let tcx = self.interner(); + let tcx = self.cx(); let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(tcx, goal.predicate.trait_ref(tcx)); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index dbe3dfd4a1b..b10be5a9ba7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -10,20 +10,20 @@ use rustc_type_ir::{self as ty, Interner, Upcast as _}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{EvalCtxt, Goal, NoSolution}; // Calculates the constituent types of a type for `auto trait` purposes. #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<Infcx, I>( - ecx: &EvalCtxt<'_, Infcx>, +pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>( + ecx: &EvalCtxt<'_, D>, ty: I::Ty, ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - let tcx = ecx.interner(); + let tcx = ecx.cx(); match ty.kind() { ty::Uint(_) | ty::Int(_) @@ -76,7 +76,7 @@ where } ty::CoroutineWitness(def_id, args) => Ok(ecx - .interner() + .cx() .bound_coroutine_hidden_types(def_id) .into_iter() .map(|bty| bty.instantiate(tcx, &args)) @@ -101,12 +101,12 @@ where } #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<Infcx, I>( - ecx: &EvalCtxt<'_, Infcx>, +pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>( + ecx: &EvalCtxt<'_, D>, ty: I::Ty, ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { match ty.kind() { @@ -159,8 +159,8 @@ where // "best effort" optimization and `sized_constraint` may return `Some`, even // if the ADT is sized for all possible args. ty::Adt(def, args) => { - if let Some(sized_crit) = def.sized_constraint(ecx.interner()) { - Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), &args))]) + if let Some(sized_crit) = def.sized_constraint(ecx.cx()) { + Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), &args))]) } else { Ok(vec![]) } @@ -169,12 +169,12 @@ where } #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<Infcx, I>( - ecx: &EvalCtxt<'_, Infcx>, +pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>( + ecx: &EvalCtxt<'_, D>, ty: I::Ty, ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { match ty.kind() { @@ -222,10 +222,10 @@ where // only when `coroutine_clone` is enabled and the coroutine is movable // impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses) - ty::Coroutine(def_id, args) => match ecx.interner().coroutine_movability(def_id) { + ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) { Movability::Static => Err(NoSolution), Movability::Movable => { - if ecx.interner().features().coroutine_clone() { + if ecx.cx().features().coroutine_clone() { let coroutine = args.as_coroutine(); Ok(vec![ ty::Binder::dummy(coroutine.tupled_upvars_ty()), @@ -239,10 +239,10 @@ where // impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types ty::CoroutineWitness(def_id, args) => Ok(ecx - .interner() + .cx() .bound_coroutine_hidden_types(def_id) .into_iter() - .map(|bty| bty.instantiate(ecx.interner(), &args)) + .map(|bty| bty.instantiate(ecx.cx(), &args)) .collect()), } } @@ -656,17 +656,17 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>( // This is unsound in general and once that is fixed, we don't need to // normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9 // for more details. -pub(in crate::solve) fn predicates_for_object_candidate<Infcx, I>( - ecx: &EvalCtxt<'_, Infcx>, +pub(in crate::solve) fn predicates_for_object_candidate<D, I>( + ecx: &EvalCtxt<'_, D>, param_env: I::ParamEnv, trait_ref: ty::TraitRef<I>, object_bounds: I::BoundExistentialPredicates, ) -> Vec<Goal<I, I::Predicate>> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let mut requirements = vec![]; requirements .extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args)); @@ -712,18 +712,18 @@ where .collect() } -struct ReplaceProjectionWith<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> { - ecx: &'a EvalCtxt<'a, Infcx>, +struct ReplaceProjectionWith<'a, D: SolverDelegate<Interner = I>, I: Interner> { + ecx: &'a EvalCtxt<'a, D>, param_env: I::ParamEnv, mapping: HashMap<I::DefId, ty::Binder<I, ty::ProjectionPredicate<I>>>, nested: Vec<Goal<I, I::Predicate>>, } -impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> - for ReplaceProjectionWith<'_, Infcx, I> +impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> + for ReplaceProjectionWith<'_, D, I> { - fn interner(&self) -> I { - self.ecx.interner() + fn cx(&self) -> I { + self.ecx.cx() } fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { @@ -739,7 +739,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> .eq_and_get_goals( self.param_env, alias_ty, - proj.projection_term.expect_ty(self.ecx.interner()), + proj.projection_term.expect_ty(self.ecx.cx()), ) .expect( "expected to be able to unify goal projection with dyn's projection", diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index c6611285a3b..f1d4864a84b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -18,7 +18,7 @@ use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, Interner}; use tracing::{instrument, trace}; use crate::canonicalizer::{CanonicalizeMode, Canonicalizer}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::resolve::EagerResolver; use crate::solve::eval_ctxt::NestedGoals; use crate::solve::inspect; @@ -44,9 +44,9 @@ impl<I: Interner, T> ResponseT<I> for inspect::State<I, T> { } } -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// Canonicalizes the goal remembering the original values @@ -55,19 +55,19 @@ where &self, goal: Goal<I, T>, ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) { - let opaque_types = self.infcx.clone_opaque_types_for_query_response(); + let opaque_types = self.delegate.clone_opaque_types_for_query_response(); let (goal, opaque_types) = - (goal, opaque_types).fold_with(&mut EagerResolver::new(self.infcx)); + (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); let mut orig_values = Default::default(); let canonical_goal = Canonicalizer::canonicalize( - self.infcx, + self.delegate, CanonicalizeMode::Input, &mut orig_values, QueryInput { goal, predefined_opaques_in_body: self - .interner() + .cx() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), }, ); @@ -97,7 +97,7 @@ where // We only check for leaks from universes which were entered inside // of the query. - self.infcx.leak_check(self.max_input_universe).map_err(|NoSolution| { + self.delegate.leak_check(self.max_input_universe).map_err(|NoSolution| { trace!("failed the leak check"); NoSolution })?; @@ -125,21 +125,21 @@ where let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); - let (var_values, mut external_constraints) = - (self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx)); + let (var_values, mut external_constraints) = (self.var_values, external_constraints) + .fold_with(&mut EagerResolver::new(self.delegate)); // Remove any trivial region constraints once we've resolved regions external_constraints .region_constraints .retain(|outlives| outlives.0.as_region().map_or(true, |re| re != outlives.1)); let canonical = Canonicalizer::canonicalize( - self.infcx, + self.delegate, CanonicalizeMode::Response { max_input_universe: self.max_input_universe }, &mut Default::default(), Response { var_values, certainty, - external_constraints: self.interner().mk_external_constraints(external_constraints), + external_constraints: self.cx().mk_external_constraints(external_constraints), }, ); @@ -155,7 +155,7 @@ where maybe_cause: MaybeCause, ) -> CanonicalResponse<I> { response_no_constraints_raw( - self.interner(), + self.cx(), self.max_input_universe, self.variables, Certainty::Maybe(maybe_cause), @@ -184,7 +184,7 @@ where // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`. let region_constraints = if certainty == Certainty::Yes { - self.infcx.make_deduplicated_outlives_constraints() + self.delegate.make_deduplicated_outlives_constraints() } else { Default::default() }; @@ -192,7 +192,7 @@ where ExternalConstraintsData { region_constraints, opaque_types: self - .infcx + .delegate .clone_opaque_types_for_query_response() .into_iter() // Only return *newly defined* opaque types. @@ -219,15 +219,15 @@ where response: CanonicalResponse<I>, ) -> (NestedNormalizationGoals<I>, Certainty) { let instantiation = Self::compute_query_response_instantiation_values( - self.infcx, + self.delegate, &original_values, &response, ); let Response { var_values, external_constraints, certainty } = - self.infcx.instantiate_canonical(response, instantiation); + self.delegate.instantiate_canonical(response, instantiation); - Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values); + Self::unify_query_var_values(self.delegate, param_env, &original_values, var_values); let ExternalConstraintsData { region_constraints, @@ -243,17 +243,17 @@ where /// the canonical response. This depends on the `original_values` for the /// bound variables. fn compute_query_response_instantiation_values<T: ResponseT<I>>( - infcx: &Infcx, + delegate: &D, original_values: &[I::GenericArg], response: &Canonical<I, T>, ) -> CanonicalVarValues<I> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. - let prev_universe = infcx.universe(); + let prev_universe = delegate.universe(); let universes_created_in_query = response.max_universe.index(); for _ in 0..universes_created_in_query { - infcx.create_next_universe(); + delegate.create_next_universe(); } let var_values = response.value.var_values(); @@ -290,13 +290,13 @@ where } } - let var_values = infcx.interner().mk_args_from_iter( + let var_values = delegate.cx().mk_args_from_iter( response.variables.into_iter().enumerate().map(|(index, info)| { if info.universe() != ty::UniverseIndex::ROOT { // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - infcx.instantiate_canonical_var_with_infer(info, |idx| { + delegate.instantiate_canonical_var_with_infer(info, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -310,7 +310,7 @@ where if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] { v } else { - infcx.instantiate_canonical_var_with_infer(info, |_| prev_universe) + delegate.instantiate_canonical_var_with_infer(info, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this @@ -335,9 +335,9 @@ where /// whether an alias is rigid by using the trait solver. When instantiating a response /// from the solver we assume that the solver correctly handled aliases and therefore /// always relate them structurally here. - #[instrument(level = "trace", skip(infcx))] + #[instrument(level = "trace", skip(delegate))] fn unify_query_var_values( - infcx: &Infcx, + delegate: &D, param_env: I::ParamEnv, original_values: &[I::GenericArg], var_values: CanonicalVarValues<I>, @@ -345,7 +345,8 @@ where assert_eq!(original_values.len(), var_values.len()); for (&orig, response) in iter::zip(original_values, var_values.var_values) { - let goals = infcx.eq_structurally_relating_aliases(param_env, orig, response).unwrap(); + let goals = + delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap(); assert!(goals.is_empty()); } } @@ -365,7 +366,7 @@ where fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) { for &(key, ty) in opaque_types { - self.infcx.inject_new_hidden_type_unchecked(key, ty); + self.delegate.inject_new_hidden_type_unchecked(key, ty); } } } @@ -374,22 +375,22 @@ where /// evaluating a goal. The `var_values` not only include the bound variables /// of the query input, but also contain all unconstrained inference vars /// created while evaluating this goal. -pub(in crate::solve) fn make_canonical_state<Infcx, T, I>( - infcx: &Infcx, +pub(in crate::solve) fn make_canonical_state<D, T, I>( + delegate: &D, var_values: &[I::GenericArg], max_input_universe: ty::UniverseIndex, data: T, ) -> inspect::CanonicalState<I, T> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, T: TypeFoldable<I>, { - let var_values = CanonicalVarValues { var_values: infcx.interner().mk_args(var_values) }; + let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; - let state = state.fold_with(&mut EagerResolver::new(infcx)); + let state = state.fold_with(&mut EagerResolver::new(delegate)); Canonicalizer::canonicalize( - infcx, + delegate, CanonicalizeMode::Response { max_input_universe }, &mut vec![], state, @@ -398,15 +399,15 @@ where // FIXME: needs to be pub to be accessed by downstream // `rustc_trait_selection::solve::inspect::analyse`. -pub fn instantiate_canonical_state<Infcx, I, T: TypeFoldable<I>>( - infcx: &Infcx, - span: Infcx::Span, +pub fn instantiate_canonical_state<D, I, T: TypeFoldable<I>>( + delegate: &D, + span: D::Span, param_env: I::ParamEnv, orig_values: &mut Vec<I::GenericArg>, state: inspect::CanonicalState<I, T>, ) -> T where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { // In case any fresh inference variables have been created between `state` @@ -415,15 +416,15 @@ where for &arg in &state.value.var_values.var_values[orig_values.len()..state.value.var_values.len()] { // FIXME: This is so ugly. - let unconstrained = infcx.fresh_var_for_kind_with_span(arg, span); + let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span); orig_values.push(unconstrained); } let instantiation = - EvalCtxt::compute_query_response_instantiation_values(infcx, orig_values, &state); + EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state); - let inspect::State { var_values, data } = infcx.instantiate_canonical(state, instantiation); + let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation); - EvalCtxt::unify_query_var_values(infcx, param_env, orig_values, var_values); + EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values); data } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 8548c647b6b..6644fff2140 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -11,7 +11,7 @@ use rustc_type_ir::{self as ty, CanonicalVarValues, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::{instrument, trace}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ @@ -23,9 +23,9 @@ use crate::solve::{ pub(super) mod canonical; mod probe; -pub struct EvalCtxt<'a, Infcx, I = <Infcx as SolverDelegate>::Interner> +pub struct EvalCtxt<'a, D, I = <D as SolverDelegate>::Interner> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// The inference context that backs (mostly) inference and placeholder terms @@ -43,7 +43,7 @@ where /// If some `InferCtxt` method is missing, please first think defensively about /// the method's compatibility with this solver, or if an existing one does /// the job already. - infcx: &'a Infcx, + delegate: &'a D, /// The variable info for the `var_values`, only used to make an ambiguous response /// with no constraints. @@ -83,7 +83,7 @@ where // evaluation code. tainted: Result<(), NoSolution>, - pub(super) inspect: ProofTreeBuilder<Infcx>, + pub(super) inspect: ProofTreeBuilder<D>, } #[derive(derivative::Derivative)] @@ -143,9 +143,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate { ); } -impl<Infcx, I> SolverDelegateEvalExt for Infcx +impl<D, I> SolverDelegateEvalExt for D where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// Evaluates a goal from **outside** of the trait solver. @@ -178,9 +178,9 @@ where } } -impl<'a, Infcx, I> EvalCtxt<'a, Infcx> +impl<'a, D, I> EvalCtxt<'a, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { pub(super) fn solver_mode(&self) -> SolverMode { @@ -195,22 +195,22 @@ where /// used from outside of any evaluation, and other methods should be preferred /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]). pub(super) fn enter_root<R>( - infcx: &Infcx, + delegate: &D, generate_proof_tree: GenerateProofTree, - f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> R, + f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option<inspect::GoalEvaluation<I>>) { - let mut search_graph = search_graph::SearchGraph::new(infcx.solver_mode()); + let mut search_graph = search_graph::SearchGraph::new(delegate.solver_mode()); let mut ecx = EvalCtxt { - infcx, + delegate, search_graph: &mut search_graph, nested_goals: NestedGoals::new(), inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree), // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. - predefined_opaques_in_body: infcx - .interner() + predefined_opaques_in_body: delegate + .cx() .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()), max_input_universe: ty::UniverseIndex::ROOT, variables: Default::default(), @@ -242,14 +242,14 @@ where tcx: I, search_graph: &'a mut search_graph::SearchGraph<I>, canonical_input: CanonicalInput<I>, - canonical_goal_evaluation: &mut ProofTreeBuilder<Infcx>, - f: impl FnOnce(&mut EvalCtxt<'_, Infcx>, Goal<I, I::Predicate>) -> R, + canonical_goal_evaluation: &mut ProofTreeBuilder<D>, + f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R, ) -> R { - let (ref infcx, input, var_values) = + let (ref delegate, input, var_values) = SolverDelegate::build_with_canonical(tcx, search_graph.solver_mode(), &canonical_input); let mut ecx = EvalCtxt { - infcx, + delegate, variables: canonical_input.variables, var_values, is_normalizes_to_goal: false, @@ -262,7 +262,7 @@ where }; for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - ecx.infcx.inject_new_hidden_type_unchecked(key, ty); + ecx.delegate.inject_new_hidden_type_unchecked(key, ty); } if !ecx.nested_goals.is_empty() { @@ -270,7 +270,7 @@ where } let result = f(&mut ecx, input.goal); - ecx.inspect.probe_final_state(ecx.infcx, ecx.max_input_universe); + ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe); canonical_goal_evaluation.goal_evaluation_step(ecx.inspect); // When creating a query response we clone the opaque type constraints @@ -278,7 +278,7 @@ where // assertions against dropping an `InferCtxt` without taking opaques. // FIXME: Once we remove support for the old impl we can remove this. // FIXME: Could we make `build_with_canonical` into `enter_with_canonical` and call this at the end? - infcx.reset_opaque_types(); + delegate.reset_opaque_types(); result } @@ -297,7 +297,7 @@ where tcx: I, search_graph: &'a mut search_graph::SearchGraph<I>, canonical_input: CanonicalInput<I>, - goal_evaluation: &mut ProofTreeBuilder<Infcx>, + goal_evaluation: &mut ProofTreeBuilder<D>, ) -> QueryResult<I> { let mut canonical_goal_evaluation = goal_evaluation.new_canonical_goal_evaluation(canonical_input); @@ -364,7 +364,7 @@ where let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); let canonical_response = EvalCtxt::evaluate_canonical_goal( - self.interner(), + self.cx(), self.search_graph, canonical_goal, &mut goal_evaluation, @@ -466,8 +466,8 @@ where } } } else { - self.infcx.enter_forall(kind, |kind| { - let goal = goal.with(self.interner(), ty::Binder::dummy(kind)); + self.delegate.enter_forall(kind, |kind| { + let goal = goal.with(self.cx(), ty::Binder::dummy(kind)); self.add_goal(GoalSource::InstantiateHigherRanked, goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -506,7 +506,7 @@ where /// /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> { - let tcx = self.interner(); + let tcx = self.cx(); let mut goals = core::mem::take(&mut self.nested_goals); // If this loop did not result in any progress, what's our final certainty. @@ -588,11 +588,11 @@ where /// Record impl args in the proof tree for later access by `InspectCandidate`. pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs) { - self.inspect.record_impl_args(self.infcx, self.max_input_universe, impl_args) + self.inspect.record_impl_args(self.delegate, self.max_input_universe, impl_args) } - pub(super) fn interner(&self) -> I { - self.infcx.interner() + pub(super) fn cx(&self) -> I { + self.delegate.cx() } #[instrument(level = "trace", skip(self))] @@ -600,7 +600,7 @@ where goal.predicate = goal .predicate .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); - self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal); + self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal); self.nested_goals.normalizes_to_goals.push(goal); } @@ -609,7 +609,7 @@ where goal.predicate = goal .predicate .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); - self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal); + self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); self.nested_goals.goals.push((source, goal)); } @@ -625,13 +625,13 @@ where } pub(super) fn next_ty_infer(&mut self) -> I::Ty { - let ty = self.infcx.next_ty_infer(); + let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); ty } pub(super) fn next_const_infer(&mut self) -> I::Const { - let ct = self.infcx.next_const_infer(); + let ct = self.delegate.next_const_infer(); self.inspect.add_var_value(ct); ct } @@ -654,27 +654,27 @@ where let universe_of_term = match goal.predicate.term.kind() { ty::TermKind::Ty(ty) => { if let ty::Infer(ty::TyVar(vid)) = ty.kind() { - self.infcx.universe_of_ty(vid).unwrap() + self.delegate.universe_of_ty(vid).unwrap() } else { return false; } } ty::TermKind::Const(ct) => { if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { - self.infcx.universe_of_ct(vid).unwrap() + self.delegate.universe_of_ct(vid).unwrap() } else { return false; } } }; - struct ContainsTermOrNotNameable<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> { + struct ContainsTermOrNotNameable<'a, D: SolverDelegate<Interner = I>, I: Interner> { term: I::Term, universe_of_term: ty::UniverseIndex, - infcx: &'a Infcx, + delegate: &'a D, } - impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> { + impl<D: SolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, D, I> { fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> { if self.universe_of_term.can_name(universe) { ControlFlow::Continue(()) @@ -684,8 +684,8 @@ where } } - impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeVisitor<I> - for ContainsTermOrNotNameable<'_, Infcx, I> + impl<D: SolverDelegate<Interner = I>, I: Interner> TypeVisitor<I> + for ContainsTermOrNotNameable<'_, D, I> { type Result = ControlFlow<()>; fn visit_ty(&mut self, t: I::Ty) -> Self::Result { @@ -693,13 +693,15 @@ where ty::Infer(ty::TyVar(vid)) => { if let ty::TermKind::Ty(term) = self.term.kind() { if let ty::Infer(ty::TyVar(term_vid)) = term.kind() { - if self.infcx.root_ty_var(vid) == self.infcx.root_ty_var(term_vid) { + if self.delegate.root_ty_var(vid) + == self.delegate.root_ty_var(term_vid) + { return ControlFlow::Break(()); } } } - self.check_nameable(self.infcx.universe_of_ty(vid).unwrap()) + self.check_nameable(self.delegate.universe_of_ty(vid).unwrap()) } ty::Placeholder(p) => self.check_nameable(p.universe()), _ => { @@ -718,15 +720,15 @@ where if let ty::TermKind::Const(term) = self.term.kind() { if let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() { - if self.infcx.root_const_var(vid) - == self.infcx.root_const_var(term_vid) + if self.delegate.root_const_var(vid) + == self.delegate.root_const_var(term_vid) { return ControlFlow::Break(()); } } } - self.check_nameable(self.infcx.universe_of_ct(vid).unwrap()) + self.check_nameable(self.delegate.universe_of_ct(vid).unwrap()) } ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), _ => { @@ -741,7 +743,7 @@ where } let mut visitor = ContainsTermOrNotNameable { - infcx: self.infcx, + delegate: self.delegate, universe_of_term, term: goal.predicate.term, }; @@ -775,7 +777,7 @@ where // NOTE: this check is purely an optimization, the structural eq would // always fail if the term is not an inference variable. if term.is_infer() { - let tcx = self.interner(); + let tcx = self.cx(); // We need to relate `alias` to `term` treating only the outermost // constructor as rigid, relating any contained generic arguments as // normal. We do this by first structurally equating the `term` @@ -788,7 +790,7 @@ where let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args); let ctor_term = rigid_ctor.to_term(tcx); let obligations = - self.infcx.eq_structurally_relating_aliases(param_env, term, ctor_term)?; + self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?; debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { @@ -806,7 +808,7 @@ where lhs: T, rhs: T, ) -> Result<(), NoSolution> { - let result = self.infcx.eq_structurally_relating_aliases(param_env, lhs, rhs)?; + let result = self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs)?; assert_eq!(result, vec![]); Ok(()) } @@ -829,7 +831,7 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolution> { - let goals = self.infcx.relate(param_env, lhs, variance, rhs)?; + let goals = self.delegate.relate(param_env, lhs, variance, rhs)?; self.add_goals(GoalSource::Misc, goals); Ok(()) } @@ -846,14 +848,14 @@ where lhs: T, rhs: T, ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> { - self.infcx.relate(param_env, lhs, ty::Variance::Invariant, rhs) + self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs) } pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>( &self, value: ty::Binder<I, T>, ) -> T { - self.infcx.instantiate_binder_with_infer(value) + self.delegate.instantiate_binder_with_infer(value) } pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>( @@ -861,18 +863,18 @@ where value: ty::Binder<I, T>, f: impl FnOnce(T) -> U, ) -> U { - self.infcx.enter_forall(value, f) + self.delegate.enter_forall(value, f) } pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T where T: TypeFoldable<I>, { - self.infcx.resolve_vars_if_possible(value) + self.delegate.resolve_vars_if_possible(value) } pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { - let args = self.infcx.fresh_args_for_item(def_id); + let args = self.delegate.fresh_args_for_item(def_id); for arg in args { self.inspect.add_var_value(arg); } @@ -880,12 +882,12 @@ where } pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { - self.infcx.register_ty_outlives(ty, lt); + self.delegate.register_ty_outlives(ty, lt); } pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) { // `b : a` ==> `a <= b` - self.infcx.sub_regions(b, a); + self.delegate.sub_regions(b, a); } /// Computes the list of goals required for `arg` to be well-formed @@ -894,7 +896,7 @@ where param_env: I::ParamEnv, arg: I::GenericArg, ) -> Option<Vec<Goal<I, I::Predicate>>> { - self.infcx.well_formed_goals(param_env, arg) + self.delegate.well_formed_goals(param_env, arg) } pub(super) fn trait_ref_is_knowable( @@ -902,9 +904,9 @@ where param_env: I::ParamEnv, trait_ref: ty::TraitRef<I>, ) -> Result<bool, NoSolution> { - let infcx = self.infcx; + let delegate = self.delegate; let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty); - infcx.trait_ref_is_knowable(trait_ref, lazily_normalize_ty) + delegate.trait_ref_is_knowable(trait_ref, lazily_normalize_ty) } pub(super) fn fetch_eligible_assoc_item( @@ -914,7 +916,7 @@ where trait_assoc_def_id: I::DefId, impl_def_id: I::DefId, ) -> Result<Option<I::DefId>, NoSolution> { - self.infcx.fetch_eligible_assoc_item( + self.delegate.fetch_eligible_assoc_item( param_env, goal_trait_ref, trait_assoc_def_id, @@ -923,7 +925,7 @@ where } pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool { - self.infcx.defining_opaque_types().contains(&def_id) + self.delegate.defining_opaque_types().contains(&def_id) } pub(super) fn insert_hidden_type( @@ -933,7 +935,7 @@ where hidden_ty: I::Ty, ) -> Result<(), NoSolution> { let mut goals = Vec::new(); - self.infcx.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?; + self.delegate.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?; self.add_goals(GoalSource::Misc, goals); Ok(()) } @@ -946,7 +948,7 @@ where hidden_ty: I::Ty, ) { let mut goals = Vec::new(); - self.infcx.add_item_bounds_for_hidden_type( + self.delegate.add_item_bounds_for_hidden_type( opaque_def_id, opaque_args, param_env, @@ -965,7 +967,7 @@ where ty: I::Ty, ) -> Vec<CanonicalResponse<I>> { // FIXME: Super inefficient to be cloning this... - let opaques = self.infcx.clone_opaque_types_for_query_response(); + let opaques = self.delegate.clone_opaque_types_for_query_response(); let mut values = vec![]; for (candidate_key, candidate_ty) in opaques { @@ -1002,7 +1004,7 @@ where param_env: I::ParamEnv, unevaluated: ty::UnevaluatedConst<I>, ) -> Option<I::Const> { - self.infcx.try_const_eval_resolve(param_env, unevaluated) + self.delegate.try_const_eval_resolve(param_env, unevaluated) } pub(super) fn is_transmutable( @@ -1012,7 +1014,7 @@ where src: I::Ty, assume: I::Const, ) -> Result<Certainty, NoSolution> { - self.infcx.is_transmutable(param_env, dst, src, assume) + self.delegate.is_transmutable(param_env, dst, src, assume) } } @@ -1023,22 +1025,22 @@ where /// /// This is a performance optimization to more eagerly detect cycles during trait /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs. -struct ReplaceAliasWithInfer<'me, 'a, Infcx, I> +struct ReplaceAliasWithInfer<'me, 'a, D, I> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - ecx: &'me mut EvalCtxt<'a, Infcx>, + ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv, } -impl<Infcx, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, Infcx, I> +impl<D, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, D, I> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - fn interner(&self) -> I { - self.ecx.interner() + fn cx(&self) -> I { + self.ecx.cx() } fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { @@ -1052,7 +1054,7 @@ where ); self.ecx.add_goal( GoalSource::Misc, - Goal::new(self.interner(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, normalizes_to), ); infer_ty } @@ -1071,7 +1073,7 @@ where ); self.ecx.add_goal( GoalSource::Misc, - Goal::new(self.interner(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, normalizes_to), ); infer_ct } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index 1c5358b3edb..e9516c60c70 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -3,34 +3,34 @@ use std::marker::PhantomData; use rustc_type_ir::Interner; use tracing::instrument; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::assembly::Candidate; use crate::solve::inspect; use crate::solve::{BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult}; -pub(in crate::solve) struct ProbeCtxt<'me, 'a, Infcx, I, F, T> +pub(in crate::solve) struct ProbeCtxt<'me, 'a, D, I, F, T> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - ecx: &'me mut EvalCtxt<'a, Infcx, I>, + ecx: &'me mut EvalCtxt<'a, D, I>, probe_kind: F, _result: PhantomData<T>, } -impl<Infcx, I, F, T> ProbeCtxt<'_, '_, Infcx, I, F, T> +impl<D, I, F, T> ProbeCtxt<'_, '_, D, I, F, T> where F: FnOnce(&T) -> inspect::ProbeKind<I>, - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> T) -> T { + pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T { let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; - let infcx = outer_ecx.infcx; + let delegate = outer_ecx.delegate; let max_input_universe = outer_ecx.max_input_universe; let mut nested_ecx = EvalCtxt { - infcx, + delegate, variables: outer_ecx.variables, var_values: outer_ecx.var_values, is_normalizes_to_goal: outer_ecx.is_normalizes_to_goal, @@ -41,9 +41,9 @@ where tainted: outer_ecx.tainted, inspect: outer_ecx.inspect.take_and_enter_probe(), }; - let r = nested_ecx.infcx.probe(|| { + let r = nested_ecx.delegate.probe(|| { let r = f(&mut nested_ecx); - nested_ecx.inspect.probe_final_state(infcx, max_input_universe); + nested_ecx.inspect.probe_final_state(delegate, max_input_universe); r }); if !nested_ecx.inspect.is_noop() { @@ -55,41 +55,38 @@ where } } -pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, Infcx, I, F> +pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, D, I, F> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - cx: ProbeCtxt<'me, 'a, Infcx, I, F, QueryResult<I>>, + cx: ProbeCtxt<'me, 'a, D, I, F, QueryResult<I>>, source: CandidateSource<I>, } -impl<Infcx, I, F> TraitProbeCtxt<'_, '_, Infcx, I, F> +impl<D, I, F> TraitProbeCtxt<'_, '_, D, I, F> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>, { #[instrument(level = "debug", skip_all, fields(source = ?self.source))] pub(in crate::solve) fn enter( self, - f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>, + f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, ) -> Result<Candidate<I>, NoSolution> { self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result }) } } -impl<'a, Infcx, I> EvalCtxt<'a, Infcx, I> +impl<'a, D, I> EvalCtxt<'a, D, I> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// `probe_kind` is only called when proof tree building is enabled so it can be /// as expensive as necessary to output the desired information. - pub(in crate::solve) fn probe<F, T>( - &mut self, - probe_kind: F, - ) -> ProbeCtxt<'_, 'a, Infcx, I, F, T> + pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, D, I, F, T> where F: FnOnce(&T) -> inspect::ProbeKind<I>, { @@ -99,16 +96,14 @@ where pub(in crate::solve) fn probe_builtin_trait_candidate( &mut self, source: BuiltinImplSource, - ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> - { + ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> { self.probe_trait_candidate(CandidateSource::BuiltinImpl(source)) } pub(in crate::solve) fn probe_trait_candidate( &mut self, source: CandidateSource<I>, - ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> - { + ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> { TraitProbeCtxt { cx: ProbeCtxt { ecx: self, diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index 5fbec4b28d4..ae59f0c5e95 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -9,7 +9,7 @@ use std::mem; use rustc_type_ir::{self as ty, Interner}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::eval_ctxt::canonical; use crate::solve::inspect; use crate::solve::{ @@ -37,12 +37,12 @@ use crate::solve::{ /// trees. At the end of trait solving `ProofTreeBuilder::finalize` /// is called to recursively convert the whole structure to a /// finished proof tree. -pub(in crate::solve) struct ProofTreeBuilder<Infcx, I = <Infcx as SolverDelegate>::Interner> +pub(in crate::solve) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { - _infcx: PhantomData<Infcx>, + _infcx: PhantomData<D>, state: Option<Box<DebugSolver<I>>>, } @@ -235,8 +235,8 @@ impl<I: Interner> WipProbeStep<I> { } } -impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { - fn new(state: impl Into<DebugSolver<I>>) -> ProofTreeBuilder<Infcx> { +impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { + fn new(state: impl Into<DebugSolver<I>>) -> ProofTreeBuilder<D> { ProofTreeBuilder { state: Some(Box::new(state.into())), _infcx: PhantomData } } @@ -258,7 +258,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { self.state.as_deref_mut() } - pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<Infcx> { + pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> { let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData }; nested.enter_probe(); nested @@ -273,18 +273,18 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { } } - pub fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<Infcx> { + pub fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> { match generate_proof_tree { GenerateProofTree::No => ProofTreeBuilder::new_noop(), GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } - pub fn new_root() -> ProofTreeBuilder<Infcx> { + pub fn new_root() -> ProofTreeBuilder<D> { ProofTreeBuilder::new(DebugSolver::Root) } - pub fn new_noop() -> ProofTreeBuilder<Infcx> { + pub fn new_noop() -> ProofTreeBuilder<D> { ProofTreeBuilder { state: None, _infcx: PhantomData } } @@ -297,7 +297,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { goal: Goal<I, I::Predicate>, orig_values: &[I::GenericArg], kind: GoalEvaluationKind, - ) -> ProofTreeBuilder<Infcx> { + ) -> ProofTreeBuilder<D> { self.opt_nested(|| match kind { GoalEvaluationKind::Root => Some(WipGoalEvaluation { uncanonicalized_goal: goal, @@ -311,7 +311,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { pub fn new_canonical_goal_evaluation( &mut self, goal: CanonicalInput<I>, - ) -> ProofTreeBuilder<Infcx> { + ) -> ProofTreeBuilder<D> { self.nested(|| WipCanonicalGoalEvaluation { goal, kind: None, @@ -337,10 +337,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { }) } - pub fn canonical_goal_evaluation( - &mut self, - canonical_goal_evaluation: ProofTreeBuilder<Infcx>, - ) { + pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<D>) { if let Some(this) = self.as_mut() { match (this, *canonical_goal_evaluation.state.unwrap()) { ( @@ -366,7 +363,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { } } - pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<Infcx>) { + pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) { if let Some(this) = self.as_mut() { match this { DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), @@ -382,7 +379,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { &mut self, var_values: ty::CanonicalVarValues<I>, instantiated_goal: QueryInput<I, I::Predicate>, - ) -> ProofTreeBuilder<Infcx> { + ) -> ProofTreeBuilder<D> { self.nested(|| WipCanonicalGoalEvaluationStep { var_values: var_values.var_values.to_vec(), instantiated_goal, @@ -396,7 +393,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { }) } - pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<Infcx>) { + pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) { if let Some(this) = self.as_mut() { match (this, *goal_evaluation_step.state.unwrap()) { ( @@ -448,12 +445,12 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { } } - pub fn probe_final_state(&mut self, infcx: &Infcx, max_input_universe: ty::UniverseIndex) { + pub fn probe_final_state(&mut self, delegate: &D, max_input_universe: ty::UniverseIndex) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let final_state = canonical::make_canonical_state( - infcx, + delegate, &state.var_values, max_input_universe, (), @@ -467,21 +464,21 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { pub fn add_normalizes_to_goal( &mut self, - infcx: &Infcx, + delegate: &D, max_input_universe: ty::UniverseIndex, goal: Goal<I, ty::NormalizesTo<I>>, ) { self.add_goal( - infcx, + delegate, max_input_universe, GoalSource::Misc, - goal.with(infcx.interner(), goal.predicate), + goal.with(delegate.cx(), goal.predicate), ); } pub fn add_goal( &mut self, - infcx: &Infcx, + delegate: &D, max_input_universe: ty::UniverseIndex, source: GoalSource, goal: Goal<I, I::Predicate>, @@ -490,7 +487,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let goal = canonical::make_canonical_state( - infcx, + delegate, &state.var_values, max_input_universe, goal, @@ -503,14 +500,14 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { pub(crate) fn record_impl_args( &mut self, - infcx: &Infcx, + delegate: &D, max_input_universe: ty::UniverseIndex, impl_args: I::GenericArgs, ) { match self.as_mut() { Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let impl_args = canonical::make_canonical_state( - infcx, + delegate, &state.var_values, max_input_universe, impl_args, @@ -538,7 +535,7 @@ impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> { } } - pub fn finish_probe(mut self) -> ProofTreeBuilder<Infcx> { + pub fn finish_probe(mut self) -> ProofTreeBuilder<D> { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 02069016c2b..b76b4c09852 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -29,7 +29,7 @@ use rustc_type_ir::{self as ty, Interner}; use tracing::instrument; pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; /// How many fixpoint iterations we should attempt inside of the solver before bailing /// with overflow. @@ -56,9 +56,9 @@ fn has_no_inference_or_external_constraints<I: Interner>( && response.value.external_constraints.opaque_types.is_empty() } -impl<'a, Infcx, I> EvalCtxt<'a, Infcx> +impl<'a, D, I> EvalCtxt<'a, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { #[instrument(level = "trace", skip(self))] @@ -104,7 +104,7 @@ where } fn compute_object_safe_goal(&mut self, trait_def_id: I::DefId) -> QueryResult<I> { - if self.interner().trait_is_object_safe(trait_def_id) { + if self.cx().trait_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { Err(NoSolution) @@ -182,7 +182,7 @@ where return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } ty::ConstKind::Unevaluated(uv) => { - self.interner().type_of(uv.def).instantiate(self.interner(), &uv.args) + self.cx().type_of(uv.def).instantiate(self.cx(), &uv.args) } ty::ConstKind::Expr(_) => unimplemented!( "`feature(generic_const_exprs)` is not supported in the new trait solver" @@ -193,7 +193,7 @@ where ty::ConstKind::Bound(_, _) => panic!("escaping bound vars in {:?}", ct), ty::ConstKind::Value(ty, _) => ty, ty::ConstKind::Placeholder(placeholder) => { - self.interner().find_const_ty_from_env(goal.param_env, placeholder) + self.cx().find_const_ty_from_env(goal.param_env, placeholder) } }; @@ -202,9 +202,9 @@ where } } -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`. @@ -267,7 +267,7 @@ where if let ty::Alias(..) = ty.kind() { let normalized_ty = self.next_ty_infer(); let alias_relate_goal = Goal::new( - self.interner(), + self.cx(), param_env, ty::PredicateKind::AliasRelate( ty.into(), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 0f1c1f13c16..5d5597429da 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -1,12 +1,12 @@ use rustc_type_ir::{self as ty, Interner}; use tracing::instrument; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { #[instrument(level = "trace", skip(self), ret)] diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 8436f3ad484..827fe5f2ca4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -7,19 +7,19 @@ use rustc_type_ir::{self as ty, Interner}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { pub(super) fn normalize_inherent_associated_type( &mut self, goal: Goal<I, ty::NormalizesTo<I>>, ) -> QueryResult<I> { - let tcx = self.interner(); + let tcx = self.cx(); let inherent = goal.predicate.alias.expect_ty(tcx); let impl_def_id = tcx.parent(inherent.def_id); diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index ebc83bef513..f58384d86cd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -9,7 +9,7 @@ use rustc_type_ir::Upcast as _; use rustc_type_ir::{self as ty, Interner, NormalizesTo}; use tracing::instrument; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; use crate::solve::assembly::{self, Candidate}; use crate::solve::inspect::ProbeKind; @@ -18,9 +18,9 @@ use crate::solve::{ NoSolution, QueryResult, }; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { #[instrument(level = "trace", skip(self), ret)] @@ -48,7 +48,7 @@ where /// returns `NoSolution`. #[instrument(level = "trace", skip(self), ret)] fn normalize_at_least_one_step(&mut self, goal: Goal<I, NormalizesTo<I>>) -> QueryResult<I> { - match goal.predicate.alias.kind(self.interner()) { + match goal.predicate.alias.kind(self.cx()) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { let candidates = self.assemble_and_evaluate_candidates(goal); self.merge_candidates(candidates) @@ -75,9 +75,9 @@ where } } -impl<Infcx, I> assembly::GoalKind<Infcx> for NormalizesTo<I> +impl<D, I> assembly::GoalKind<D> for NormalizesTo<I> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { fn self_ty(self) -> I::Ty { @@ -97,15 +97,15 @@ where } fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, ) -> Result<Candidate<I>, NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { - let tcx = ecx.interner(); + let tcx = ecx.cx(); ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); @@ -136,15 +136,15 @@ where } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, NormalizesTo<I>>, impl_def_id: I::DefId, ) -> Result<Candidate<I>, NoSolution> { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let goal_trait_ref = goal.predicate.alias.trait_ref(tcx); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); - if !ecx.interner().args_may_unify_deep( + if !ecx.cx().args_may_unify_deep( goal.predicate.alias.trait_ref(tcx).args, impl_trait_ref.skip_binder().args, ) { @@ -194,7 +194,7 @@ where return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); }; - let error_response = |ecx: &mut EvalCtxt<'_, Infcx>, msg: &str| { + let error_response = |ecx: &mut EvalCtxt<'_, D>, msg: &str| { let guar = tcx.delay_bug(msg); let error_term = match goal.predicate.alias.kind(tcx) { ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(), @@ -262,61 +262,61 @@ where /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error` /// and succeed. Can experiment with this to figure out what results in better error messages. fn consider_error_guaranteed_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, _guar: I::ErrorGuaranteed, ) -> Result<Candidate<I>, NoSolution> { Err(NoSolution) } fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, _goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { - ecx.interner().delay_bug("associated types not allowed on auto traits"); + ecx.cx().delay_bug("associated types not allowed on auto traits"); Err(NoSolution) } fn consider_trait_alias_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("trait aliases do not have associated types: {:?}", goal); } fn consider_builtin_sized_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`Sized` does not have an associated type: {:?}", goal); } fn consider_builtin_copy_clone_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal); } fn consider_builtin_pointer_like_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`PointerLike` does not have an associated type: {:?}", goal); } fn consider_builtin_fn_ptr_trait_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`FnPtr` does not have an associated type: {:?}", goal); } fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, goal_kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution> { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, @@ -355,11 +355,11 @@ where } fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, goal_kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution> { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let env_region = match goal_kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), @@ -457,7 +457,7 @@ where } fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let [ @@ -489,7 +489,7 @@ where } let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( - ecx.interner(), + ecx.cx(), goal_kind, tupled_inputs_ty.expect_ty(), tupled_upvars_ty.expect_ty(), @@ -504,17 +504,17 @@ where } fn consider_builtin_tuple_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`Tuple` does not have an associated type: {:?}", goal); } fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let metadata_def_id = tcx.require_lang_item(TraitSolverLangItem::Metadata); assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { @@ -592,7 +592,7 @@ where } fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -601,7 +601,7 @@ where }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -613,11 +613,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new( - ecx.interner(), - goal.predicate.def_id(), - [self_ty], - ), + projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]), term, } .upcast(tcx), @@ -628,7 +624,7 @@ where } fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -637,7 +633,7 @@ where }; // Coroutines are not Iterators unless they come from `gen` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -649,11 +645,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new( - ecx.interner(), - goal.predicate.def_id(), - [self_ty], - ), + projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]), term, } .upcast(tcx), @@ -664,14 +656,14 @@ where } fn consider_builtin_fused_iterator_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`FusedIterator` does not have an associated type: {:?}", goal); } fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -680,7 +672,7 @@ where }; // Coroutines are not AsyncIterators unless they come from `gen` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -707,7 +699,7 @@ where } fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -716,7 +708,7 @@ where }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.is_general_coroutine(def_id) { return Err(NoSolution); } @@ -739,7 +731,7 @@ where goal, ty::ProjectionPredicate { projection_term: ty::AliasTerm::new( - ecx.interner(), + ecx.cx(), goal.predicate.def_id(), [self_ty, coroutine.resume_ty()], ), @@ -753,14 +745,14 @@ where } fn consider_structural_builtin_unsize_candidates( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Vec<Candidate<I>> { panic!("`Unsize` does not have an associated type: {:?}", goal); } fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -788,7 +780,7 @@ where | ty::Slice(_) | ty::Dynamic(_, _, _) | ty::Tuple(_) - | ty::Error(_) => self_ty.discriminant_ty(ecx.interner()), + | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()), // We do not call `Ty::discriminant_ty` on alias, param, or placeholder // types, which return `<self_ty as DiscriminantKind>::Discriminant` @@ -812,7 +804,7 @@ where } fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -835,7 +827,7 @@ where | ty::Str | ty::Slice(_) | ty::Tuple(_) - | ty::Error(_) => self_ty.async_destructor_ty(ecx.interner()), + | ty::Error(_) => self_ty.async_destructor_ty(ecx.cx()), // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder // types, which return `<self_ty as AsyncDestruct>::AsyncDestructor` @@ -865,23 +857,23 @@ where } fn consider_builtin_destruct_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`Destruct` does not have an associated type: {:?}", goal); } fn consider_builtin_transmute_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, + _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) } } -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { fn translate_args( @@ -892,7 +884,7 @@ where impl_trait_ref: rustc_type_ir::TraitRef<I>, target_container_def_id: I::DefId, ) -> Result<I::GenericArgs, NoSolution> { - let tcx = self.interner(); + let tcx = self.cx(); Ok(if target_container_def_id == impl_trait_ref.def_id { // Default value from the trait definition. No need to rebase. goal.predicate.alias.args diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 710671b45d0..f3494328d9e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -6,19 +6,19 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { pub(super) fn normalize_opaque_type( &mut self, goal: Goal<I, ty::NormalizesTo<I>>, ) -> QueryResult<I> { - let tcx = self.interner(); + let tcx = self.cx(); let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); @@ -34,7 +34,7 @@ where return Err(NoSolution); } // FIXME: This may have issues when the args contain aliases... - match uses_unique_placeholders_ignoring_regions(self.interner(), opaque_ty.args) { + match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) { Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { return self.evaluate_added_goals_and_make_canonical_response( Certainty::AMBIGUOUS, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs index 45341917bb2..27d5ae07729 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs @@ -6,19 +6,19 @@ use rustc_type_ir::{self as ty, Interner}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { pub(super) fn normalize_weak_type( &mut self, goal: Goal<I, ty::NormalizesTo<I>>, ) -> QueryResult<I> { - let tcx = self.interner(); + let tcx = self.cx(); let weak_ty = goal.predicate.alias; // Check where clauses diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs index 4bb1fe5be6f..a430dbb408c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs @@ -1,12 +1,12 @@ use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; use tracing::instrument; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { #[instrument(level = "trace", skip(self), ret)] @@ -14,7 +14,7 @@ where &mut self, goal: Goal<I, ProjectionPredicate<I>>, ) -> QueryResult<I> { - let tcx = self.interner(); + let tcx = self.cx(); let projection_term = goal.predicate.projection_term.to_term(tcx); let goal = goal.with( tcx, diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index fc78a864f81..d3ad55d6491 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::Interner; use tracing::debug; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::{ CacheData, CanonicalInput, Certainty, QueryResult, SolverMode, FIXPOINT_STEP_LIMIT, @@ -255,12 +255,12 @@ impl<I: Interner> SearchGraph<I> { /// /// Given some goal which is proven via the `prove_goal` closure, this /// handles caching, overflow, and coinductive cycles. - pub(super) fn with_new_goal<Infcx: SolverDelegate<Interner = I>>( + pub(super) fn with_new_goal<D: SolverDelegate<Interner = I>>( &mut self, tcx: I, input: CanonicalInput<I>, - inspect: &mut ProofTreeBuilder<Infcx>, - mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<Infcx>) -> QueryResult<I>, + inspect: &mut ProofTreeBuilder<D>, + mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<D>) -> QueryResult<I>, ) -> QueryResult<I> { self.check_invariants(); // Check for overflow. @@ -416,12 +416,12 @@ impl<I: Interner> SearchGraph<I> { /// Try to fetch a previously computed result from the global cache, /// making sure to only do so if it would match the result of reevaluating /// this goal. - fn lookup_global_cache<Infcx: SolverDelegate<Interner = I>>( + fn lookup_global_cache<D: SolverDelegate<Interner = I>>( &mut self, tcx: I, input: CanonicalInput<I>, available_depth: SolverLimit, - inspect: &mut ProofTreeBuilder<Infcx>, + inspect: &mut ProofTreeBuilder<D>, ) -> Option<QueryResult<I>> { let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self .global_cache(tcx) @@ -465,16 +465,16 @@ impl<I: Interner> SearchGraph<I> { /// of this we continuously recompute the cycle until the result /// of the previous iteration is equal to the final result, at which /// point we are done. - fn fixpoint_step_in_task<Infcx, F>( + fn fixpoint_step_in_task<D, F>( &mut self, tcx: I, input: CanonicalInput<I>, - inspect: &mut ProofTreeBuilder<Infcx>, + inspect: &mut ProofTreeBuilder<D>, prove_goal: &mut F, ) -> StepResult<I> where - Infcx: SolverDelegate<Interner = I>, - F: FnMut(&mut Self, &mut ProofTreeBuilder<Infcx>) -> QueryResult<I>, + D: SolverDelegate<Interner = I>, + F: FnMut(&mut Self, &mut ProofTreeBuilder<D>) -> QueryResult<I>, { let result = prove_goal(self, inspect); let stack_entry = self.pop_stack(); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index c0353f92bf8..2ddb3c981db 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -8,7 +8,7 @@ use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, TraitPredicate, Upcast as _}; use tracing::{instrument, trace}; -use crate::infcx::SolverDelegate; +use crate::delegate::SolverDelegate; use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; use crate::solve::assembly::{self, Candidate}; use crate::solve::inspect::ProbeKind; @@ -17,9 +17,9 @@ use crate::solve::{ NoSolution, QueryResult, Reveal, SolverMode, }; -impl<Infcx, I> assembly::GoalKind<Infcx> for TraitPredicate<I> +impl<D, I> assembly::GoalKind<D> for TraitPredicate<I> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { fn self_ty(self) -> I::Ty { @@ -39,11 +39,11 @@ where } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, TraitPredicate<I>>, impl_def_id: I::DefId, ) -> Result<Candidate<I>, NoSolution> { - let tcx = ecx.interner(); + let tcx = ecx.cx(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); if !tcx @@ -91,7 +91,7 @@ where } fn consider_error_guaranteed_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, _guar: I::ErrorGuaranteed, ) -> Result<Candidate<I>, NoSolution> { // FIXME: don't need to enter a probe here. @@ -100,11 +100,11 @@ where } fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, ) -> Result<Candidate<I>, NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() @@ -128,7 +128,7 @@ where } fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -174,14 +174,14 @@ where } fn consider_trait_alias_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let tcx = ecx.interner(); + let tcx = ecx.cx(); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let nested_obligations = tcx @@ -195,7 +195,7 @@ where } fn consider_builtin_sized_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -210,7 +210,7 @@ where } fn consider_builtin_copy_clone_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -225,14 +225,14 @@ where } fn consider_builtin_pointer_like_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let tcx = ecx.interner(); + let tcx = ecx.cx(); // But if there are inference variables, we have to wait until it's resolved. if (goal.param_env, goal.predicate.self_ty()).has_non_region_infer() { return ecx.forced_ambiguity(MaybeCause::Ambiguity); @@ -247,7 +247,7 @@ where } fn consider_builtin_fn_ptr_trait_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let self_ty = goal.predicate.self_ty(); @@ -278,7 +278,7 @@ where } fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, goal_kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution> { @@ -286,7 +286,7 @@ where return Err(NoSolution); } - let tcx = ecx.interner(); + let tcx = ecx.cx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, @@ -319,7 +319,7 @@ where } fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, goal_kind: ty::ClosureKind, ) -> Result<Candidate<I>, NoSolution> { @@ -327,7 +327,7 @@ where return Err(NoSolution); } - let tcx = ecx.interner(); + let tcx = ecx.cx(); let (tupled_inputs_and_output_and_coroutine, nested_preds) = structural_traits::extract_tupled_inputs_and_output_from_async_callable( tcx, @@ -370,7 +370,7 @@ where } fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else { @@ -397,7 +397,7 @@ where /// impl Tuple for (T1, .., Tn) {} /// ``` fn consider_builtin_tuple_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -413,7 +413,7 @@ where } fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -425,7 +425,7 @@ where } fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -437,7 +437,7 @@ where }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -451,7 +451,7 @@ where } fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -463,7 +463,7 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -477,7 +477,7 @@ where } fn consider_builtin_fused_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -489,7 +489,7 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -501,7 +501,7 @@ where } fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -513,7 +513,7 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -527,7 +527,7 @@ where } fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -540,7 +540,7 @@ where }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.interner(); + let tcx = ecx.cx(); if !tcx.is_general_coroutine(def_id) { return Err(NoSolution); } @@ -559,7 +559,7 @@ where } fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -572,7 +572,7 @@ where } fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -585,7 +585,7 @@ where } fn consider_builtin_destruct_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -601,7 +601,7 @@ where } fn consider_builtin_transmute_candidate( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -634,7 +634,7 @@ where /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {} /// ``` fn consider_structural_builtin_unsize_candidates( - ecx: &mut EvalCtxt<'_, Infcx>, + ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Vec<Candidate<I>> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { @@ -657,7 +657,7 @@ where return vec![]; }; - let goal = goal.with(ecx.interner(), (a_ty, b_ty)); + let goal = goal.with(ecx.cx(), (a_ty, b_ty)); match (a_ty.kind(), b_ty.kind()) { (ty::Infer(ty::TyVar(..)), ..) => panic!("unexpected infer {a_ty:?} {b_ty:?}"), @@ -705,9 +705,9 @@ where } } -impl<Infcx, I> EvalCtxt<'_, Infcx> +impl<D, I> EvalCtxt<'_, D> where - Infcx: SolverDelegate<Interner = I>, + D: SolverDelegate<Interner = I>, I: Interner, { /// Trait upcasting allows for coercions between trait objects: @@ -727,7 +727,7 @@ where b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Vec<Candidate<I>> { - let tcx = self.interner(); + let tcx = self.cx(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; let mut responses = vec![]; @@ -745,8 +745,7 @@ where )); } else if let Some(a_principal) = a_data.principal() { for new_a_principal in - Infcx::elaborate_supertraits(self.interner(), a_principal.with_self_ty(tcx, a_ty)) - .skip(1) + D::elaborate_supertraits(self.cx(), a_principal.with_self_ty(tcx, a_ty)).skip(1) { responses.extend(self.consider_builtin_upcast_to_principal( goal, @@ -771,7 +770,7 @@ where b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result<Candidate<I>, NoSolution> { - let tcx = self.interner(); + let tcx = self.cx(); let Goal { predicate: (a_ty, _), .. } = goal; // Can only unsize to an object-safe trait. @@ -825,10 +824,10 @@ where .auto_traits() .into_iter() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - self.interner() + self.cx() .supertrait_def_ids(principal_def_id) .into_iter() - .filter(|def_id| self.interner().trait_is_auto(*def_id)) + .filter(|def_id| self.cx().trait_is_auto(*def_id)) })) .collect(); @@ -837,7 +836,7 @@ where // having any inference side-effects. We process obligations because // unification may initially succeed due to deferred projection equality. let projection_may_match = - |ecx: &mut EvalCtxt<'_, Infcx>, + |ecx: &mut EvalCtxt<'_, D>, source_projection: ty::Binder<I, ty::ExistentialProjection<I>>, target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| { source_projection.item_def_id() == target_projection.item_def_id() @@ -896,7 +895,7 @@ where // Also require that a_ty's lifetime outlives b_ty's lifetime. ecx.add_goal( GoalSource::ImplWhereBound, - Goal::new(ecx.interner(), param_env, ty::OutlivesPredicate(a_region, b_region)), + Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -942,7 +941,7 @@ where a_args: I::GenericArgs, b_args: I::GenericArgs, ) -> Result<Candidate<I>, NoSolution> { - let tcx = self.interner(); + let tcx = self.cx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; let unsizing_params = tcx.unsizing_params_for_adt(def.def_id()); @@ -1002,7 +1001,7 @@ where a_tys: I::Tys, b_tys: I::Tys, ) -> Result<Candidate<I>, NoSolution> { - let tcx = self.interner(); + let tcx = self.cx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); @@ -1062,11 +1061,9 @@ where // takes precedence over the structural auto trait candidate being // assembled. ty::Coroutine(def_id, _) - if self - .interner() - .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) => + if self.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) => { - match self.interner().coroutine_movability(def_id) { + match self.cx().coroutine_movability(def_id) { Movability::Static => Some(Err(NoSolution)), Movability::Movable => Some( self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { @@ -1111,7 +1108,7 @@ where | ty::Tuple(_) | ty::Adt(_, _) => { let mut disqualifying_impl = None; - self.interner().for_each_relevant_impl( + self.cx().for_each_relevant_impl( goal.predicate.def_id(), goal.predicate.self_ty(), |impl_def_id| { @@ -1140,7 +1137,7 @@ where source: CandidateSource<I>, goal: Goal<I, TraitPredicate<I>>, constituent_tys: impl Fn( - &EvalCtxt<'_, Infcx>, + &EvalCtxt<'_, D>, I::Ty, ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>, ) -> Result<Candidate<I>, NoSolution> { @@ -1151,10 +1148,7 @@ where .into_iter() .map(|ty| { ecx.enter_forall(ty, |ty| { - goal.with( - ecx.interner(), - goal.predicate.with_self_ty(ecx.interner(), ty), - ) + goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty)) }) }) .collect::<Vec<_>>(), diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 84dbd192723..84c71c4bed2 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -14,7 +14,7 @@ passes_abi_of = fn_abi_of({$fn_name}) = {$fn_abi} passes_allow_incoherent_impl = - `rustc_allow_incoherent_impl` attribute should be applied to impl items. + `rustc_allow_incoherent_impl` attribute should be applied to impl items .label = the only currently supported targets are inherent methods passes_allow_internal_unstable = @@ -253,8 +253,8 @@ passes_doc_test_unknown_spotlight = .no_op_note = `doc(spotlight)` is now a no-op passes_duplicate_diagnostic_item_in_crate = - duplicate diagnostic item in crate `{$crate_name}`: `{$name}`. - .note = the diagnostic item is first defined in crate `{$orig_crate_name}`. + duplicate diagnostic item in crate `{$crate_name}`: `{$name}` + .note = the diagnostic item is first defined in crate `{$orig_crate_name}` passes_duplicate_feature_err = the feature `{$feature}` has already been declared @@ -263,27 +263,27 @@ passes_duplicate_lang_item = found duplicate lang item `{$lang_item_name}` .first_defined_span = the lang item is first defined here .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`. + .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) .second_definition_local = second definition in the local crate (`{$crate_name}`) .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} .second_definition_path = second definition in `{$crate_name}` loaded from {$path} passes_duplicate_lang_item_crate = - duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`. + duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}` .first_defined_span = the lang item is first defined here .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`. + .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) .second_definition_local = second definition in the local crate (`{$crate_name}`) .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} .second_definition_path = second definition in `{$crate_name}` loaded from {$path} passes_duplicate_lang_item_crate_depends = - duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`. + duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}` .first_defined_span = the lang item is first defined here .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`. + .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) .second_definition_local = second definition in the local crate (`{$crate_name}`) .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} @@ -315,7 +315,7 @@ passes_ffi_pure_invalid_target = `#[ffi_pure]` may only be used on foreign functions passes_has_incoherent_inherent_impl = - `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits. + `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits .label = only adts, extern types and traits are supported passes_ignored_attr = diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 358f25e2334..4b9c36ad39f 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -240,7 +240,7 @@ resolve_label_with_similar_name_reachable = resolve_lending_iterator_report_error = associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type. + .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type resolve_lifetime_param_in_enum_discriminant = lifetime parameters may not be used in enum discriminant values diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index e74c1208a39..44b31f2659c 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -214,7 +214,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> { } } - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b8dacc6968d..b84280a3ccf 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -82,9 +82,9 @@ session_octal_float_literal_not_supported = octal float literal is not supported session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} -session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist. +session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist -session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist. +session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi` diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 9afd507ce11..dde5e30c3d0 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -533,6 +533,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables)) } + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let sig = fn_ptr.internal(&mut *tables, tcx); + Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables)) + } + fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { let mut tables = self.0.borrow_mut(); let def_id = tables.instances[def].def_id(); diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 98ed985738a..83a554fe31d 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +derivative = "2.2.0" indexmap = { version = "2.0.0" } itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index ba0ad9230c8..483e32c6453 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -43,9 +43,15 @@ use std::hash::Hash; use tracing::{debug, trace}; /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks". -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct SyntaxContext(u32); +// To ensure correctness of incremental compilation, +// `SyntaxContext` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for SyntaxContext {} +impl !PartialOrd for SyntaxContext {} + #[derive(Debug, Encodable, Decodable, Clone)] pub struct SyntaxContextData { outer_expn: ExpnId, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b3f3899542d..266956d63d7 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -467,46 +467,23 @@ impl FileName { /// `SpanData` is public because `Span` uses a thread-local interner and can't be /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, derivative::Derivative)] +#[derivative(PartialOrd, Ord)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. + #[derivative(PartialOrd = "ignore", Ord = "ignore")] + // `SyntaxContext` does not implement `Ord`. + // The other fields are enough to determine in-file order. pub ctxt: SyntaxContext, + #[derivative(PartialOrd = "ignore", Ord = "ignore")] + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. pub parent: Option<LocalDefId>, } -// Order spans by position in the file. -impl Ord for SpanData { - fn cmp(&self, other: &Self) -> Ordering { - let SpanData { - lo: s_lo, - hi: s_hi, - ctxt: s_ctxt, - // `LocalDefId` does not implement `Ord`. - // The other fields are enough to determine in-file order. - parent: _, - } = self; - let SpanData { - lo: o_lo, - hi: o_hi, - ctxt: o_ctxt, - // `LocalDefId` does not implement `Ord`. - // The other fields are enough to determine in-file order. - parent: _, - } = other; - - (s_lo, s_hi, s_ctxt).cmp(&(o_lo, o_hi, o_ctxt)) - } -} - -impl PartialOrd for SpanData { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - impl SpanData { #[inline] pub fn span(&self) -> Span { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a508c279439..a8123fe994c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1593,6 +1593,8 @@ symbols! { rustc_do_not_const_check, rustc_doc_primitive, rustc_dummy, + rustc_dump_item_bounds, + rustc_dump_predicates, rustc_dump_user_args, rustc_dump_vtable, rustc_effective_visibility, @@ -2054,6 +2056,8 @@ symbols! { yes, yield_expr, ymm_reg, + zfh, + zfhmin, zmm_reg, } } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 37184393a73..9d79faadd61 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -47,16 +47,18 @@ impl ArmInlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<Symbol>)] { match self { - Self::reg => types! { _: I8, I16, I32, F32; }, - Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; }, + Self::reg => types! { _: I8, I16, I32, F16, F32; }, + Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F16, F32; }, Self::dreg_low16 | Self::dreg_low8 => types! { - vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); + vfp2: I64, F64; + neon: VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2); }, Self::dreg => types! { - d32: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); + d32: I64, F64; + neon: VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2); }, Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! { - neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4); + neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4); }, } } diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index 3845a0e14af..02a4a5e2ece 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -40,12 +40,13 @@ impl RiscVInlineAsmRegClass { match self { Self::reg => { if arch == InlineAsmArch::RiscV64 { - types! { _: I8, I16, I32, I64, F32, F64; } + types! { _: I8, I16, I32, I64, F16, F32, F64; } } else { - types! { _: I8, I16, I32, F32; } + types! { _: I8, I16, I32, F16, F32; } } } - Self::freg => types! { f: F32; d: F64; }, + // FIXME(f16_f128): Add `q: F128;` once LLVM support the `Q` extension. + Self::freg => types! { f: F16, F32; d: F64; }, Self::vreg => &[], } } diff --git a/compiler/rustc_trait_selection/src/solve.rs b/compiler/rustc_trait_selection/src/solve.rs index a7c8cc5a32b..e47f5389cd1 100644 --- a/compiler/rustc_trait_selection/src/solve.rs +++ b/compiler/rustc_trait_selection/src/solve.rs @@ -1,7 +1,7 @@ pub use rustc_next_trait_solver::solve::*; +mod delegate; mod fulfill; -mod infcx; pub mod inspect; mod normalize; mod select; diff --git a/compiler/rustc_trait_selection/src/solve/infcx.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e574166cbfc..643d5f80480 100644 --- a/compiler/rustc_trait_selection/src/solve/infcx.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -39,10 +39,10 @@ impl<'tcx> Deref for SolverDelegate<'tcx> { } } -impl<'tcx> rustc_next_trait_solver::infcx::SolverDelegate for SolverDelegate<'tcx> { +impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<'tcx> { type Interner = TyCtxt<'tcx>; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.0.tcx } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 8937ed467a1..76b88aeb0f7 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -17,7 +17,7 @@ use rustc_span::symbol::sym; use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError}; -use super::infcx::SolverDelegate; +use super::delegate::SolverDelegate; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::Certainty; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index cb621487125..e8de8457440 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -22,7 +22,7 @@ use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state} use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _}; use rustc_span::{Span, DUMMY_SP}; -use crate::solve::infcx::SolverDelegate; +use crate::solve::delegate::SolverDelegate; use crate::traits::ObligationCtxt; pub struct InspectConfig { diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index f42edebfcc4..2679da942b7 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -156,7 +156,7 @@ where { type Error = Vec<E>; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.at.infcx.tcx } @@ -244,7 +244,7 @@ struct DeeplyNormalizeForDiagnosticsFolder<'a, 'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.at.infcx.tcx } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 33074c20f57..b2fa3489dda 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4936,7 +4936,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> { t.super_fold_with(self) } - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index b5f2d34852f..d3096cf4b52 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2840,7 +2840,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ParamToVarFolder<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index af6bfdae440..662d95db8ba 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -350,7 +350,7 @@ pub fn normalize_param_env_or_error<'tcx>( struct ConstNormalizer<'tcx>(TyCtxt<'tcx>); impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ConstNormalizer<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.0 } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index d7408eab84a..a9ac0f7eb25 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -163,7 +163,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.selcx.tcx() } @@ -217,7 +217,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx Reveal::UserFacing => ty.super_fold_with(self), Reveal::All => { - let recursion_limit = self.interner().recursion_limit(); + let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( OverflowCause::DeeplyNormalize(data.into()), @@ -228,8 +228,8 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx } let args = data.args.fold_with(self); - let generic_ty = self.interner().type_of(data.def_id); - let concrete_ty = generic_ty.instantiate(self.interner(), args); + let generic_ty = self.cx().type_of(data.def_id); + let concrete_ty = generic_ty.instantiate(self.cx(), args); self.depth += 1; let folded_ty = self.fold_ty(concrete_ty); self.depth -= 1; @@ -313,7 +313,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx normalized_ty } ty::Weak => { - let recursion_limit = self.interner().recursion_limit(); + let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( OverflowCause::DeeplyNormalize(data.into()), diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e170d7cae93..bed76b84ee0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -172,7 +172,7 @@ struct QueryNormalizer<'cx, 'tcx> { impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> { type Error = NoSolution; - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -217,7 +217,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> Reveal::All => { let args = data.args.try_fold_with(self)?; - let recursion_limit = self.interner().recursion_limit(); + let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let guar = self @@ -229,15 +229,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> true, ) .delay_as_bug(); - return Ok(Ty::new_error(self.interner(), guar)); + return Ok(Ty::new_error(self.cx(), guar)); } - let generic_ty = self.interner().type_of(data.def_id); - let mut concrete_ty = generic_ty.instantiate(self.interner(), args); + let generic_ty = self.cx().type_of(data.def_id); + let mut concrete_ty = generic_ty.instantiate(self.cx(), args); self.anon_depth += 1; if concrete_ty == ty { concrete_ty = Ty::new_error_with_message( - self.interner(), + self.cx(), DUMMY_SP, "recursive opaque type", ); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c3fe816028e..f132e36468a 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -394,7 +394,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -509,7 +509,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { } impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -550,7 +550,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - ty::Region::new_bound(self.interner(), db, *replace_var) + ty::Region::new_bound(self.cx(), db, *replace_var) } None => r1, } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 59de7c552af..18b34f8d99b 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -625,7 +625,7 @@ struct ArgFolder<'a, I: Interner> { impl<'a, I: Interner> TypeFolder<I> for ArgFolder<'a, I> { #[inline] - fn interner(&self) -> I { + fn cx(&self) -> I { self.tcx } @@ -845,7 +845,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { return val; } - let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); + let result = ty::fold::shift_vars(TypeFolder::cx(self), val, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 26e365f64fa..953a438cb14 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -129,7 +129,7 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> { /// the infallible methods of this trait to ensure that the two APIs /// are coherent. pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> { - fn interner(&self) -> I; + fn cx(&self) -> I; fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> where @@ -167,7 +167,7 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> { pub trait FallibleTypeFolder<I: Interner>: Sized { type Error; - fn interner(&self) -> I; + fn cx(&self) -> I; fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Self::Error> where @@ -203,8 +203,8 @@ where { type Error = Never; - fn interner(&self) -> I { - TypeFolder::interner(self) + fn cx(&self) -> I { + TypeFolder::cx(self) } fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Never> @@ -351,7 +351,7 @@ impl<I: Interner> Shifter<I> { } impl<I: Interner> TypeFolder<I> for Shifter<I> { - fn interner(&self) -> I { + fn cx(&self) -> I { self.tcx } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 97752934632..3a17a27bd03 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -521,7 +521,7 @@ struct FoldEscapingRegions<I: Interner> { } impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> { - fn interner(&self) -> I { + fn cx(&self) -> I { self.interner } diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 3e138e3c2e0..44dbf549c1a 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -215,6 +215,9 @@ pub trait Context { /// Get an instance ABI. fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>; + /// Get the ABI of a function pointer. + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>; + /// Get the layout of a type. fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>; diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 35927237281..8c120a96e75 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -2,7 +2,7 @@ use super::{ mir::{Body, Mutability, Safety}, with, DefId, Error, Symbol, }; -use crate::abi::Layout; +use crate::abi::{FnAbi, Layout}; use crate::crate_def::{CrateDef, CrateDefType}; use crate::mir::alloc::{read_target_int, read_target_uint, AllocId}; use crate::mir::mono::StaticDef; @@ -996,6 +996,16 @@ pub struct AliasTerm { pub type PolyFnSig = Binder<FnSig>; +impl PolyFnSig { + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `Instance::fn_abi` + /// instead, where the instance is an `InstanceKind::Virtual`. + pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> { + with(|cx| cx.fn_ptr_abi(self)) + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct FnSig { pub inputs_and_output: Vec<Ty>, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 6677534eafc..1833a7f477f 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -424,29 +424,3 @@ pub mod __alloc_error_handler { } } } - -#[cfg(not(no_global_oom_handling))] -/// Specialize clones into pre-allocated, uninitialized memory. -/// Used by `Box::clone` and `Rc`/`Arc::make_mut`. -pub(crate) trait WriteCloneIntoRaw: Sized { - unsafe fn write_clone_into_raw(&self, target: *mut Self); -} - -#[cfg(not(no_global_oom_handling))] -impl<T: Clone> WriteCloneIntoRaw for T { - #[inline] - default unsafe fn write_clone_into_raw(&self, target: *mut Self) { - // Having allocated *first* may allow the optimizer to create - // the cloned value in-place, skipping the local and move. - unsafe { target.write(self.clone()) }; - } -} - -#[cfg(not(no_global_oom_handling))] -impl<T: Copy> WriteCloneIntoRaw for T { - #[inline] - unsafe fn write_clone_into_raw(&self, target: *mut Self) { - // We can always copy in-place, without ever involving a local value. - unsafe { target.copy_from_nonoverlapping(self, 1) }; - } -} diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 01a954ed75b..1ec095a46f7 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -188,6 +188,8 @@ use core::any::Any; use core::async_iter::AsyncIterator; use core::borrow; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; use core::cmp::Ordering; use core::error::Error; use core::fmt; @@ -207,7 +209,7 @@ use core::slice; use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] -use crate::alloc::{handle_alloc_error, WriteCloneIntoRaw}; +use crate::alloc::handle_alloc_error; use crate::alloc::{AllocError, Allocator, Global, Layout}; #[cfg(not(no_global_oom_handling))] use crate::borrow::Cow; @@ -1346,7 +1348,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> { // Pre-allocate memory to allow writing the cloned value directly. let mut boxed = Self::new_uninit_in(self.1.clone()); unsafe { - (**self).write_clone_into_raw(boxed.as_mut_ptr()); + (**self).clone_to_uninit(boxed.as_mut_ptr()); boxed.assume_init() } } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 022a14b931a..ecb019b49c6 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -103,6 +103,7 @@ #![feature(assert_matches)] #![feature(async_fn_traits)] #![feature(async_iterator)] +#![feature(clone_to_uninit)] #![feature(coerce_unsized)] #![feature(const_align_of_val)] #![feature(const_box)] @@ -175,7 +176,6 @@ #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_ptr_write)] -#![feature(const_trait_impl)] #![feature(const_try)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2b7ab2f6e25..3745ecb48c1 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -249,6 +249,8 @@ use std::boxed::Box; use core::any::Any; use core::borrow; use core::cell::Cell; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; @@ -268,8 +270,6 @@ use core::slice::from_raw_parts_mut; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -#[cfg(not(no_global_oom_handling))] -use crate::alloc::WriteCloneIntoRaw; use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; #[cfg(not(no_global_oom_handling))] @@ -1749,7 +1749,8 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { } } -impl<T: Clone, A: Allocator + Clone> Rc<T, A> { +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Rc<T, A> { /// Makes a mutable reference into the given `Rc`. /// /// If there are other `Rc` pointers to the same allocation, then `make_mut` will @@ -1800,31 +1801,52 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> { /// assert!(76 == *data); /// assert!(weak.upgrade().is_none()); /// ``` - #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { + let size_of_val = size_of_val::<T>(&**this); + if Rc::strong_count(this) != 1 { // Gotta clone the data, there are other Rcs. - // Pre-allocate memory to allow writing the cloned value directly. - let mut rc = Self::new_uninit_in(this.alloc.clone()); - unsafe { - let data = Rc::get_mut_unchecked(&mut rc); - (**this).write_clone_into_raw(data.as_mut_ptr()); - *this = rc.assume_init(); - } + + let this_data_ref: &T = &**this; + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueRcUninit<T, A> = + UniqueRcUninit::new(this_data_ref, this.alloc.clone()); + + // Initialize with clone of this. + let initialized_clone = unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + this_data_ref.clone_to_uninit(in_progress.data_ptr()); + // Cast type of pointer, now that it is initialized. + in_progress.into_rc() + }; + + // Replace `this` with newly constructed Rc. + *this = initialized_clone; } else if Rc::weak_count(this) != 0 { // Can just steal the data, all that's left is Weaks - let mut rc = Self::new_uninit_in(this.alloc.clone()); + + // We don't need panic-protection like the above branch does, but we might as well + // use the same mechanism. + let mut in_progress: UniqueRcUninit<T, A> = + UniqueRcUninit::new(&**this, this.alloc.clone()); unsafe { - let data = Rc::get_mut_unchecked(&mut rc); - data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1); + // Initialize `in_progress` with move of **this. + // We have to express this in terms of bytes because `T: ?Sized`; there is no + // operation that just copies a value based on its `size_of_val()`. + ptr::copy_nonoverlapping( + ptr::from_ref(&**this).cast::<u8>(), + in_progress.data_ptr().cast::<u8>(), + size_of_val, + ); this.inner().dec_strong(); // Remove implicit strong-weak ref (no need to craft a fake // Weak here -- we know other Weaks can clean up for us) this.inner().dec_weak(); - ptr::write(this, rc.assume_init()); + // Replace `this` with newly constructed Rc that has the moved data. + ptr::write(this, in_progress.into_rc()); } } // This unsafety is ok because we're guaranteed that the pointer @@ -3686,3 +3708,67 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> { } } } + +/// A unique owning pointer to a [`RcBox`] **that does not imply the contents are initialized,** +/// but will deallocate it (without dropping the value) when dropped. +/// +/// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic. +/// It is nearly a duplicate of `UniqueRc<MaybeUninit<T>, A>` except that it allows `T: !Sized`, +/// which `MaybeUninit` does not. +#[cfg(not(no_global_oom_handling))] +struct UniqueRcUninit<T: ?Sized, A: Allocator> { + ptr: NonNull<RcBox<T>>, + layout_for_value: Layout, + alloc: Option<A>, +} + +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> { + /// Allocate a RcBox with layout suitable to contain `for_value` or a clone of it. + fn new(for_value: &T, alloc: A) -> UniqueRcUninit<T, A> { + let layout = Layout::for_value(for_value); + let ptr = unsafe { + Rc::allocate_for_layout( + layout, + |layout_for_rcbox| alloc.allocate(layout_for_rcbox), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcBox<T>), + ) + }; + Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } + } + + /// Returns the pointer to be written into to initialize the [`Rc`]. + fn data_ptr(&mut self) -> *mut T { + let offset = data_offset_align(self.layout_for_value.align()); + unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } + } + + /// Upgrade this into a normal [`Rc`]. + /// + /// # Safety + /// + /// The data must have been initialized (by writing to [`Self::data_ptr()`]). + unsafe fn into_rc(mut self) -> Rc<T, A> { + let ptr = self.ptr; + let alloc = self.alloc.take().unwrap(); + mem::forget(self); + // SAFETY: The pointer is valid as per `UniqueRcUninit::new`, and the caller is responsible + // for having initialized the data. + unsafe { Rc::from_ptr_in(ptr.as_ptr(), alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized, A: Allocator> Drop for UniqueRcUninit<T, A> { + fn drop(&mut self) { + // SAFETY: + // * new() produced a pointer safe to deallocate. + // * We own the pointer unless into_rc() was called, which forgets us. + unsafe { + self.alloc + .take() + .unwrap() + .deallocate(self.ptr.cast(), rcbox_layout_for_value_layout(self.layout_for_value)); + } + } +} diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 0f09be7721f..5e2e4beb94a 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -316,6 +316,24 @@ fn test_cowrc_clone_weak() { assert!(cow1_weak.upgrade().is_none()); } +/// This is similar to the doc-test for `Rc::make_mut()`, but on an unsized type (slice). +#[test] +fn test_cowrc_unsized() { + use std::rc::Rc; + + let mut data: Rc<[i32]> = Rc::new([10, 20, 30]); + + Rc::make_mut(&mut data)[0] += 1; // Won't clone anything + let mut other_data = Rc::clone(&data); // Won't clone inner data + Rc::make_mut(&mut data)[1] += 1; // Clones inner data + Rc::make_mut(&mut data)[2] += 1; // Won't clone anything + Rc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything + + // Now `data` and `other_data` point to different allocations. + assert_eq!(*data, [11, 21, 31]); + assert_eq!(*other_data, [110, 20, 30]); +} + #[test] fn test_show() { let foo = Rc::new(75); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f9d884e0ea5..90672164cb9 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -10,6 +10,8 @@ use core::any::Any; use core::borrow; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; @@ -30,8 +32,6 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -#[cfg(not(no_global_oom_handling))] -use crate::alloc::WriteCloneIntoRaw; use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; @@ -2150,7 +2150,8 @@ unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {} #[unstable(feature = "receiver_trait", issue = "none")] impl<T: ?Sized> Receiver for Arc<T> {} -impl<T: Clone, A: Allocator + Clone> Arc<T, A> { +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Arc<T, A> { /// Makes a mutable reference into the given `Arc`. /// /// If there are other `Arc` pointers to the same allocation, then `make_mut` will @@ -2201,10 +2202,11 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> { /// assert!(76 == *data); /// assert!(weak.upgrade().is_none()); /// ``` - #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "arc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { + let size_of_val = mem::size_of_val::<T>(&**this); + // Note that we hold both a strong reference and a weak reference. // Thus, releasing our strong reference only will not, by itself, cause // the memory to be deallocated. @@ -2215,13 +2217,19 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> { // deallocated. if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { // Another strong pointer exists, so we must clone. - // Pre-allocate memory to allow writing the cloned value directly. - let mut arc = Self::new_uninit_in(this.alloc.clone()); - unsafe { - let data = Arc::get_mut_unchecked(&mut arc); - (**this).write_clone_into_raw(data.as_mut_ptr()); - *this = arc.assume_init(); - } + + let this_data_ref: &T = &**this; + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueArcUninit<T, A> = + UniqueArcUninit::new(this_data_ref, this.alloc.clone()); + + let initialized_clone = unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + this_data_ref.clone_to_uninit(in_progress.data_ptr()); + // Cast type of pointer, now that it is initialized. + in_progress.into_arc() + }; + *this = initialized_clone; } else if this.inner().weak.load(Relaxed) != 1 { // Relaxed suffices in the above because this is fundamentally an // optimization: we are always racing with weak pointers being @@ -2240,11 +2248,22 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> { let _weak = Weak { ptr: this.ptr, alloc: this.alloc.clone() }; // Can just steal the data, all that's left is Weaks - let mut arc = Self::new_uninit_in(this.alloc.clone()); + // + // We don't need panic-protection like the above branch does, but we might as well + // use the same mechanism. + let mut in_progress: UniqueArcUninit<T, A> = + UniqueArcUninit::new(&**this, this.alloc.clone()); unsafe { - let data = Arc::get_mut_unchecked(&mut arc); - data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1); - ptr::write(this, arc.assume_init()); + // Initialize `in_progress` with move of **this. + // We have to express this in terms of bytes because `T: ?Sized`; there is no + // operation that just copies a value based on its `size_of_val()`. + ptr::copy_nonoverlapping( + ptr::from_ref(&**this).cast::<u8>(), + in_progress.data_ptr().cast::<u8>(), + size_of_val, + ); + + ptr::write(this, in_progress.into_arc()); } } else { // We were the sole reference of either kind; bump back up the @@ -3809,6 +3828,68 @@ fn data_offset_align(align: usize) -> usize { layout.size() + layout.padding_needed_for(align) } +/// A unique owning pointer to a [`ArcInner`] **that does not imply the contents are initialized,** +/// but will deallocate it (without dropping the value) when dropped. +/// +/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic. +#[cfg(not(no_global_oom_handling))] +struct UniqueArcUninit<T: ?Sized, A: Allocator> { + ptr: NonNull<ArcInner<T>>, + layout_for_value: Layout, + alloc: Option<A>, +} + +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> { + /// Allocate a ArcInner with layout suitable to contain `for_value` or a clone of it. + fn new(for_value: &T, alloc: A) -> UniqueArcUninit<T, A> { + let layout = Layout::for_value(for_value); + let ptr = unsafe { + Arc::allocate_for_layout( + layout, + |layout_for_arcinner| alloc.allocate(layout_for_arcinner), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner<T>), + ) + }; + Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } + } + + /// Returns the pointer to be written into to initialize the [`Arc`]. + fn data_ptr(&mut self) -> *mut T { + let offset = data_offset_align(self.layout_for_value.align()); + unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } + } + + /// Upgrade this into a normal [`Arc`]. + /// + /// # Safety + /// + /// The data must have been initialized (by writing to [`Self::data_ptr()`]). + unsafe fn into_arc(mut self) -> Arc<T, A> { + let ptr = self.ptr; + let alloc = self.alloc.take().unwrap(); + mem::forget(self); + // SAFETY: The pointer is valid as per `UniqueArcUninit::new`, and the caller is responsible + // for having initialized the data. + unsafe { Arc::from_ptr_in(ptr.as_ptr(), alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl<T: ?Sized, A: Allocator> Drop for UniqueArcUninit<T, A> { + fn drop(&mut self) { + // SAFETY: + // * new() produced a pointer safe to deallocate. + // * We own the pointer unless into_arc() was called, which forgets us. + unsafe { + self.alloc.take().unwrap().deallocate( + self.ptr.cast(), + arcinner_layout_for_value_layout(self.layout_for_value), + ); + } + } +} + #[stable(feature = "arc_error", since = "1.52.0")] impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> { #[allow(deprecated, deprecated_in_future)] diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs index d564a30b103..c37a80dca95 100644 --- a/library/alloc/tests/arc.rs +++ b/library/alloc/tests/arc.rs @@ -209,3 +209,21 @@ fn weak_may_dangle() { // `val` dropped here while still borrowed // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak` } + +/// This is similar to the doc-test for `Arc::make_mut()`, but on an unsized type (slice). +#[test] +fn make_mut_unsized() { + use alloc::sync::Arc; + + let mut data: Arc<[i32]> = Arc::new([10, 20, 30]); + + Arc::make_mut(&mut data)[0] += 1; // Won't clone anything + let mut other_data = Arc::clone(&data); // Won't clone inner data + Arc::make_mut(&mut data)[1] += 1; // Clones inner data + Arc::make_mut(&mut data)[2] += 1; // Won't clone anything + Arc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything + + // Now `data` and `other_data` point to different allocations. + assert_eq!(*data, [11, 21, 31]); + assert_eq!(*other_data, [110, 20, 30]); +} diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index d448c5338fc..d7ce65f6c53 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -36,6 +36,9 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::mem::{self, MaybeUninit}; +use crate::ptr; + /// A common trait for the ability to explicitly duplicate an object. /// /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while @@ -204,6 +207,189 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: crate::marker::PhantomData<T>, } +/// A generalization of [`Clone`] to dynamically-sized types stored in arbitrary containers. +/// +/// This trait is implemented for all types implementing [`Clone`], and also [slices](slice) of all +/// such types. You may also implement this trait to enable cloning trait objects and custom DSTs +/// (structures containing dynamically-sized fields). +/// +/// # Safety +/// +/// Implementations must ensure that when `.clone_to_uninit(dst)` returns normally rather than +/// panicking, it always leaves `*dst` initialized as a valid value of type `Self`. +/// +/// # See also +/// +/// * [`Clone::clone_from`] is a safe function which may be used instead when `Self` is a [`Sized`] +/// and the destination is already initialized; it may be able to reuse allocations owned by +/// the destination. +/// * [`ToOwned`], which allocates a new destination container. +/// +/// [`ToOwned`]: ../../std/borrow/trait.ToOwned.html +#[unstable(feature = "clone_to_uninit", issue = "126799")] +pub unsafe trait CloneToUninit { + /// Performs copy-assignment from `self` to `dst`. + /// + /// This is analogous to to `std::ptr::write(dst, self.clone())`, + /// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)). + /// + /// Before this function is called, `dst` may point to uninitialized memory. + /// After this function is called, `dst` will point to initialized memory; it will be + /// sound to create a `&Self` reference from the pointer. + /// + /// # Safety + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * `dst` must be [valid] for writes. + /// * `dst` must be properly aligned. + /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`. + /// + /// [valid]: ptr#safety + /// [pointer metadata]: crate::ptr::metadata() + /// + /// # Panics + /// + /// This function may panic. (For example, it might panic if memory allocation for a clone + /// of a value owned by `self` fails.) + /// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be + /// read or dropped, because even if it was previously valid, it may have been partially + /// overwritten. + /// + /// The caller may also need to take care to deallocate the allocation pointed to by `dst`, + /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure + /// soundness in the presence of unwinding. + /// + /// Implementors should avoid leaking values by, upon unwinding, dropping all component values + /// that might have already been created. (For example, if a `[Foo]` of length 3 is being + /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo` + /// cloned should be dropped.) + unsafe fn clone_to_uninit(&self, dst: *mut Self); +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl<T: Clone> CloneToUninit for T { + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::write(). + unsafe { + // We hope the optimizer will figure out to create the cloned value in-place, + // skipping ever storing it on the stack and the copy to the destination. + ptr::write(dst, self.clone()); + } + } +} + +// Specialized implementation for types that are [`Copy`], not just [`Clone`], +// and can therefore be copied bitwise. +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl<T: Copy> CloneToUninit for T { + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(self, dst, 1); + } + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl<T: Clone> CloneToUninit for [T] { + #[cfg_attr(debug_assertions, track_caller)] + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { + let len = self.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The produced `&mut` is valid because: + // * The caller is obligated to provide a pointer which is valid for writes. + // * All bytes pointed to are in MaybeUninit, so we don't care about the memory's + // initialization status. + let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit<T>]) }; + + // Copy the elements + let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref); + for element_ref in self.iter() { + // If the clone() panics, `initializing` will take care of the cleanup. + initializing.push(element_ref.clone()); + } + // If we reach here, then the entire slice is initialized, and we've satisfied our + // responsibilities to the caller. Disarm the cleanup guard by forgetting it. + mem::forget(initializing); + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl<T: Copy> CloneToUninit for [T] { + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut Self) { + let len = self.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len); + } + } +} + +/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which +/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. +/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* +/// initialized, unless disarmed by forgetting. +/// +/// This is a helper for `impl<T: Clone> CloneToUninit for [T]`. +struct InitializingSlice<'a, T> { + data: &'a mut [MaybeUninit<T>], + /// Number of elements of `*self.data` that are initialized. + initialized_len: usize, +} + +impl<'a, T> InitializingSlice<'a, T> { + #[inline] + fn from_fully_uninit(data: &'a mut [MaybeUninit<T>]) -> Self { + Self { data, initialized_len: 0 } + } + + /// Push a value onto the end of the initialized part of the slice. + /// + /// # Panics + /// + /// Panics if the slice is already fully initialized. + #[inline] + fn push(&mut self, value: T) { + MaybeUninit::write(&mut self.data[self.initialized_len], value); + self.initialized_len += 1; + } +} + +impl<'a, T> Drop for InitializingSlice<'a, T> { + #[cold] // will only be invoked on unwind + fn drop(&mut self) { + let initialized_slice = ptr::slice_from_raw_parts_mut( + MaybeUninit::slice_as_mut_ptr(self.data), + self.initialized_len, + ); + // SAFETY: + // * the pointer is valid because it was made from a mutable reference + // * `initialized_len` counts the initialized elements as an invariant of this type, + // so each of the pointed-to elements is initialized and may be dropped. + unsafe { + ptr::drop_in_place::<[T]>(initialized_slice); + } + } +} + /// Implementations of `Clone` for primitive types. /// /// Implementations that cannot be described in Rust diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index f3f757ce69d..cff75870790 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -245,7 +245,6 @@ use self::Ordering::*; append_const_msg )] #[rustc_diagnostic_item = "PartialEq"] -#[const_trait] pub trait PartialEq<Rhs: ?Sized = Self> { /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. @@ -1475,8 +1474,7 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialEq for $t { + impl PartialEq for $t { #[inline] fn eq(&self, other: &$t) -> bool { (*self) == (*other) } #[inline] diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index f6ec30b9f79..b213cc2b916 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -60,7 +60,7 @@ const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], Range<u8>) { const { assert!(N >= 10 && N < u8::MAX as usize) }; - let c = u32::from(c); + let c = c as u32; // OR-ing `1` ensures that for `c == 0` the code computes that // one digit should be printed. diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 297f52e756b..d2a408485d1 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -515,7 +515,10 @@ impl CStr { #[inline] #[must_use] const fn as_non_null_ptr(&self) -> NonNull<c_char> { - NonNull::from(&self.inner).as_non_null_ptr() + // FIXME(effects) replace with `NonNull::from` + // SAFETY: a reference is never null + unsafe { NonNull::new_unchecked(&self.inner as *const [c_char] as *mut [c_char]) } + .as_non_null_ptr() } /// Returns the length of `self`. Like C's `strlen`, this does not include the nul terminator. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 94ad8fbd5df..2d0b8825f43 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -200,6 +200,7 @@ // Language features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(c_unwind))] +#![cfg_attr(bootstrap, feature(effects))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -214,13 +215,11 @@ #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] -#![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] -#![feature(effects)] #![feature(extern_types)] #![feature(f128)] #![feature(f16)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 1d073a6d649..2e8be7bde4b 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -944,7 +944,6 @@ marker_impls! { #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl(implement_via_object = false)] -#[const_trait] pub trait Destruct {} /// A marker for tuple types. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 44889484963..d40e02352a1 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -484,7 +484,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) { overflow_panic::add() } else { a } + if b { overflow_panic::add() } else { a } } /// Unchecked integer addition. Computes `self + rhs`, assuming overflow @@ -580,7 +580,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_add_unsigned(rhs); - if unlikely!(b) { overflow_panic::add() } else { a } + if b { overflow_panic::add() } else { a } } /// Checked integer subtraction. Computes `self - rhs`, returning `None` if @@ -636,7 +636,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) { overflow_panic::sub() } else { a } + if b { overflow_panic::sub() } else { a } } /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow @@ -732,7 +732,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_sub_unsigned(rhs); - if unlikely!(b) { overflow_panic::sub() } else { a } + if b { overflow_panic::sub() } else { a } } /// Checked integer multiplication. Computes `self * rhs`, returning `None` if @@ -788,7 +788,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) { overflow_panic::mul() } else { a } + if b { overflow_panic::mul() } else { a } } /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow @@ -902,7 +902,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_div(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div(rhs); - if unlikely!(b) { overflow_panic::div() } else { a } + if b { overflow_panic::div() } else { a } } /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, @@ -976,7 +976,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_div_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div_euclid(rhs); - if unlikely!(b) { overflow_panic::div() } else { a } + if b { overflow_panic::div() } else { a } } /// Checked integer remainder. Computes `self % rhs`, returning `None` if @@ -1049,7 +1049,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_rem(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem(rhs); - if unlikely!(b) { overflow_panic::rem() } else { a } + if b { overflow_panic::rem() } else { a } } /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` @@ -1122,7 +1122,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_rem_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem_euclid(rhs); - if unlikely!(b) { overflow_panic::rem() } else { a } + if b { overflow_panic::rem() } else { a } } /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. @@ -1210,7 +1210,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); - if unlikely!(b) { overflow_panic::neg() } else { a } + if b { overflow_panic::neg() } else { a } } /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger @@ -1273,7 +1273,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) { overflow_panic::shl() } else { a } + if b { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -1371,7 +1371,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) { overflow_panic::shr() } else { a } + if b { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5956a08593a..0c6f06dc017 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -33,7 +33,6 @@ use super::{IntErrorKind, ParseIntError}; reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] -#[const_trait] pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed { #[doc(hidden)] type NonZeroInner: Sized + Copy; @@ -47,7 +46,6 @@ macro_rules! impl_zeroable_primitive { reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] - #[const_trait] pub trait Sealed {} $( @@ -70,14 +68,14 @@ macro_rules! impl_zeroable_primitive { reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] - impl const private::Sealed for $primitive {} + impl private::Sealed for $primitive {} #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] - unsafe impl const ZeroablePrimitive for $primitive { + unsafe impl ZeroablePrimitive for $primitive { type NonZeroInner = private::$NonZeroInner; } )+ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index cdbd695008e..00450c2cda3 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -491,7 +491,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) { overflow_panic ::add()} else {a} + if b { overflow_panic::add() } else { a } } /// Unchecked integer addition. Computes `self + rhs`, assuming overflow @@ -593,7 +593,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { let (a, b) = self.overflowing_add_signed(rhs); - if unlikely!(b) { overflow_panic ::add()} else {a} + if b { overflow_panic::add() } else { a } } /// Checked integer subtraction. Computes `self - rhs`, returning @@ -658,7 +658,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) { overflow_panic ::sub()} else {a} + if b { overflow_panic::sub() } else { a } } /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow @@ -779,7 +779,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) { overflow_panic ::mul()} else {a} + if b { overflow_panic::mul() } else { a } } /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow @@ -1304,7 +1304,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); - if unlikely!(b) { overflow_panic::neg() } else { a } + if b { overflow_panic::neg() } else { a } } /// Checked shift left. Computes `self << rhs`, returning `None` @@ -1367,7 +1367,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) { overflow_panic::shl() } else { a } + if b { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -1465,7 +1465,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) { overflow_panic::shr() } else { a } + if b { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 5e77788d8ea..133ae04f026 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,7 +73,6 @@ append_const_msg )] #[doc(alias = "+")] -#[const_trait] pub trait Add<Rhs = Self> { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -95,8 +94,7 @@ pub trait Add<Rhs = Self> { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Add for $t { + impl Add for $t { type Output = $t; #[inline] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 3d21b09fa8a..86a965f68e0 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -282,7 +282,7 @@ impl<'a> Context<'a> { pub const fn ext(&mut self) -> &mut dyn Any { // FIXME: this field makes Context extra-weird about unwind safety // can we justify AssertUnwindSafe if we stabilize this? do we care? - match &mut *self.ext { + match &mut self.ext.0 { ExtData::Some(data) => *data, ExtData::None(unit) => unit, } @@ -356,7 +356,7 @@ impl<'a> ContextBuilder<'a> { #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[unstable(feature = "context_ext", issue = "123392")] pub const fn from(cx: &'a mut Context<'_>) -> Self { - let ext = match &mut *cx.ext { + let ext = match &mut cx.ext.0 { ExtData::Some(ext) => ExtData::Some(*ext), ExtData::None(()) => ExtData::None(()), }; diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs index 64193e11558..23efab2f1b5 100644 --- a/library/core/tests/clone.rs +++ b/library/core/tests/clone.rs @@ -1,3 +1,6 @@ +use core::clone::CloneToUninit; +use core::mem::MaybeUninit; + #[test] #[allow(suspicious_double_ref_op)] fn test_borrowed_clone() { @@ -14,3 +17,66 @@ fn test_clone_from() { b.clone_from(&a); assert_eq!(*b, 5); } + +#[test] +fn test_clone_to_uninit_slice_success() { + // Using `String`s to exercise allocation and Drop of the individual elements; + // if something is aliased or double-freed, at least Miri will catch that. + let a: [String; 3] = ["a", "b", "c"].map(String::from); + + let mut storage: MaybeUninit<[String; 3]> = MaybeUninit::uninit(); + let b: [String; 3] = unsafe { + a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [String]); + storage.assume_init() + }; + + assert_eq!(a, b); +} + +#[test] +#[cfg(panic = "unwind")] +fn test_clone_to_uninit_slice_drops_on_panic() { + use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; + + /// A static counter is OK to use as long as _this one test_ isn't run several times in + /// multiple threads. + static COUNTER: AtomicUsize = AtomicUsize::new(0); + /// Counts how many instances are live, and panics if a fifth one is created + struct CountsDropsAndPanics {} + impl CountsDropsAndPanics { + fn new() -> Self { + COUNTER.fetch_add(1, Relaxed); + Self {} + } + } + impl Clone for CountsDropsAndPanics { + fn clone(&self) -> Self { + if COUNTER.load(Relaxed) == 4 { panic!("intentional panic") } else { Self::new() } + } + } + impl Drop for CountsDropsAndPanics { + fn drop(&mut self) { + COUNTER.fetch_sub(1, Relaxed); + } + } + + let a: [CountsDropsAndPanics; 3] = core::array::from_fn(|_| CountsDropsAndPanics::new()); + assert_eq!(COUNTER.load(Relaxed), 3); + + let panic_payload = std::panic::catch_unwind(|| { + let mut storage: MaybeUninit<[CountsDropsAndPanics; 3]> = MaybeUninit::uninit(); + // This should panic halfway through + unsafe { + a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [CountsDropsAndPanics]); + } + }) + .unwrap_err(); + assert_eq!(panic_payload.downcast().unwrap(), Box::new("intentional panic")); + + // Check for lack of leak, which is what this test is looking for + assert_eq!(COUNTER.load(Relaxed), 3, "leaked during clone!"); + + // Might as well exercise the rest of the drops + drop(a); + assert_eq!(COUNTER.load(Relaxed), 0); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 6845a630dff..3a2c98db0d5 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -8,6 +8,7 @@ #![feature(async_iterator)] #![feature(bigint_helper_methods)] #![feature(cell_update)] +#![feature(clone_to_uninit)] #![feature(const_align_offset)] #![feature(const_align_of_val_raw)] #![feature(const_black_box)] @@ -53,6 +54,7 @@ #![feature(slice_split_once)] #![feature(split_as_slice)] #![feature(maybe_uninit_fill)] +#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] #![feature(maybe_uninit_uninit_array_transpose)] diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index dce2da31644..f830808d196 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -16,7 +16,7 @@ alloc = { path = "../alloc" } core = { path = "../core" } unwind = { path = "../unwind" } compiler_builtins = "0.1.0" -cfg-if = "1.0" +cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2", default-features = false } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index cf9a3446522..6413b3515ec 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2742,18 +2742,15 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { /// # Examples /// /// ```no_run -/// #![feature(fs_try_exists)] /// use std::fs; /// -/// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt")); -/// assert!(fs::try_exists("/root/secret_file.txt").is_err()); +/// assert!(!fs::exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt")); +/// assert!(fs::exists("/root/secret_file.txt").is_err()); /// ``` /// /// [`Path::exists`]: crate::path::Path::exists -// FIXME: stabilization should modify documentation of `exists()` to recommend this method -// instead. -#[unstable(feature = "fs_try_exists", issue = "83186")] +#[stable(feature = "fs_try_exists", since = "CURRENT_RUSTC_VERSION")] #[inline] -pub fn try_exists<P: AsRef<Path>>(path: P) -> io::Result<bool> { - fs_imp::try_exists(path.as_ref()) +pub fn exists<P: AsRef<Path>>(path: P) -> io::Result<bool> { + fs_imp::exists(path.as_ref()) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 80f67838ac0..caa8c7375ec 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -284,7 +284,6 @@ #![feature(cfi_encoding)] #![feature(concat_idents)] #![feature(const_mut_refs)] -#![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 2ba67a6dd1a..91959094797 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -6,20 +6,20 @@ use crate::io::Result; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::process; +use crate::process::{self, ExitStatus}; use crate::sealed::Sealed; #[cfg(not(doc))] -use crate::sys::fd::FileDesc; +use crate::sys::{fd::FileDesc, linux::pidfd::PidFd as InnerPidFd}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; #[cfg(doc)] -struct FileDesc; +struct InnerPidFd; /// This type represents a file descriptor that refers to a process. /// /// A `PidFd` can be obtained by setting the corresponding option on [`Command`] /// with [`create_pidfd`]. Subsequently, the created pidfd can be retrieved -/// from the [`Child`] by calling [`pidfd`] or [`take_pidfd`]. +/// from the [`Child`] by calling [`pidfd`] or [`into_pidfd`]. /// /// Example: /// ```no_run @@ -33,7 +33,7 @@ struct FileDesc; /// .expect("Failed to spawn child"); /// /// let pidfd = child -/// .take_pidfd() +/// .into_pidfd() /// .expect("Failed to retrieve pidfd"); /// /// // The file descriptor will be closed when `pidfd` is dropped. @@ -44,28 +44,63 @@ struct FileDesc; /// [`create_pidfd`]: CommandExt::create_pidfd /// [`Child`]: process::Child /// [`pidfd`]: fn@ChildExt::pidfd -/// [`take_pidfd`]: ChildExt::take_pidfd +/// [`into_pidfd`]: ChildExt::into_pidfd /// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html #[derive(Debug)] +#[repr(transparent)] pub struct PidFd { - inner: FileDesc, + inner: InnerPidFd, } -impl AsInner<FileDesc> for PidFd { +impl PidFd { + /// Forces the child process to exit. + /// + /// Unlike [`Child::kill`] it is possible to attempt to kill + /// reaped children since PidFd does not suffer from pid recycling + /// races. But doing so will return an Error. + /// + /// [`Child::kill`]: process::Child::kill + pub fn kill(&self) -> Result<()> { + self.inner.kill() + } + + /// Waits for the child to exit completely, returning the status that it exited with. + /// + /// Unlike [`Child::wait`] it does not ensure that the stdin handle is closed. + /// Additionally it will not return an `ExitStatus` if the child + /// has already been reaped. Instead an error will be returned. + /// + /// [`Child::wait`]: process::Child::wait + pub fn wait(&self) -> Result<ExitStatus> { + self.inner.wait().map(FromInner::from_inner) + } + + /// Attempts to collect the exit status of the child if it has already exited. + /// + /// Unlike [`Child::try_wait`] this method will return an Error + /// if the child has already been reaped. + /// + /// [`Child::try_wait`]: process::Child::try_wait + pub fn try_wait(&self) -> Result<Option<ExitStatus>> { + Ok(self.inner.try_wait()?.map(FromInner::from_inner)) + } +} + +impl AsInner<InnerPidFd> for PidFd { #[inline] - fn as_inner(&self) -> &FileDesc { + fn as_inner(&self) -> &InnerPidFd { &self.inner } } -impl FromInner<FileDesc> for PidFd { - fn from_inner(inner: FileDesc) -> PidFd { +impl FromInner<InnerPidFd> for PidFd { + fn from_inner(inner: InnerPidFd) -> PidFd { PidFd { inner } } } -impl IntoInner<FileDesc> for PidFd { - fn into_inner(self) -> FileDesc { +impl IntoInner<InnerPidFd> for PidFd { + fn into_inner(self) -> InnerPidFd { self.inner } } @@ -73,37 +108,37 @@ impl IntoInner<FileDesc> for PidFd { impl AsRawFd for PidFd { #[inline] fn as_raw_fd(&self) -> RawFd { - self.as_inner().as_raw_fd() + self.as_inner().as_inner().as_raw_fd() } } impl FromRawFd for PidFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { - Self::from_inner(FileDesc::from_raw_fd(fd)) + Self::from_inner(InnerPidFd::from_raw_fd(fd)) } } impl IntoRawFd for PidFd { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_raw_fd() + self.into_inner().into_inner().into_raw_fd() } } impl AsFd for PidFd { fn as_fd(&self) -> BorrowedFd<'_> { - self.as_inner().as_fd() + self.as_inner().as_inner().as_fd() } } impl From<OwnedFd> for PidFd { fn from(fd: OwnedFd) -> Self { - Self::from_inner(FileDesc::from_inner(fd)) + Self::from_inner(InnerPidFd::from_inner(FileDesc::from_inner(fd))) } } impl From<PidFd> for OwnedFd { fn from(pid_fd: PidFd) -> Self { - pid_fd.into_inner().into_inner() + pid_fd.into_inner().into_inner().into_inner() } } @@ -124,18 +159,26 @@ pub trait ChildExt: Sealed { /// [`Child`]: process::Child fn pidfd(&self) -> Result<&PidFd>; - /// Takes ownership of the [`PidFd`] created for this [`Child`], if available. + /// Returns the [`PidFd`] created for this [`Child`], if available. + /// Otherwise self is returned. /// /// A pidfd will only be available if its creation was requested with /// [`create_pidfd`] when the corresponding [`Command`] was created. /// + /// Taking ownership of the PidFd consumes the Child to avoid pid reuse + /// races. Use [`pidfd`] and [`BorrowedFd::try_clone_to_owned`] if + /// you don't want to disassemble the Child yet. + /// /// Even if requested, a pidfd may not be available due to an older /// version of Linux being in use, or if some other error occurred. /// /// [`Command`]: process::Command /// [`create_pidfd`]: CommandExt::create_pidfd + /// [`pidfd`]: ChildExt::pidfd /// [`Child`]: process::Child - fn take_pidfd(&mut self) -> Result<PidFd>; + fn into_pidfd(self) -> crate::result::Result<PidFd, Self> + where + Self: Sized; } /// Os-specific extensions for [`Command`] @@ -146,7 +189,7 @@ pub trait CommandExt: Sealed { /// spawned by this [`Command`]. /// By default, no pidfd will be created. /// - /// The pidfd can be retrieved from the child with [`pidfd`] or [`take_pidfd`]. + /// The pidfd can be retrieved from the child with [`pidfd`] or [`into_pidfd`]. /// /// A pidfd will only be created if it is possible to do so /// in a guaranteed race-free manner. Otherwise, [`pidfd`] will return an error. @@ -160,7 +203,7 @@ pub trait CommandExt: Sealed { /// [`Command`]: process::Command /// [`Child`]: process::Child /// [`pidfd`]: fn@ChildExt::pidfd - /// [`take_pidfd`]: ChildExt::take_pidfd + /// [`into_pidfd`]: ChildExt::into_pidfd fn create_pidfd(&mut self, val: bool) -> &mut process::Command; } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 7b8caaa2684..72073d13280 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2907,6 +2907,8 @@ impl Path { /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios /// where those bugs are not an issue. /// + /// This is an alias for [`std::fs::exists`](crate::fs::exists). + /// /// # Examples /// /// ```no_run @@ -2919,7 +2921,7 @@ impl Path { #[stable(feature = "path_try_exists", since = "1.63.0")] #[inline] pub fn try_exists(&self) -> io::Result<bool> { - fs::try_exists(self) + fs::exists(self) } /// Returns `true` if the path exists on disk and is pointing at a regular file. diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index a98a1006ef4..e4e9eee044e 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -18,7 +18,7 @@ use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -pub use crate::sys_common::fs::{copy, try_exists}; +pub use crate::sys_common::fs::{copy, exists}; #[derive(Debug)] pub struct File(FileDesc); diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index a6c1336109a..dc83e4f4b49 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -12,7 +12,7 @@ use crate::{ sys::unsupported, }; -pub use crate::sys_common::fs::try_exists; +pub use crate::sys_common::fs::exists; /// A file descriptor. #[derive(Clone, Copy)] diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 035c92bc84b..5c4ccd32850 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -97,7 +97,7 @@ use libc::{ ))] use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64}; -pub use crate::sys_common::fs::try_exists; +pub use crate::sys_common::fs::exists; pub struct File(FileDesc); diff --git a/library/std/src/sys/pal/unix/linux/mod.rs b/library/std/src/sys/pal/unix/linux/mod.rs new file mode 100644 index 00000000000..88aa1e3decc --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/mod.rs @@ -0,0 +1 @@ +pub mod pidfd; diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs new file mode 100644 index 00000000000..7474f80e94f --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -0,0 +1,76 @@ +use crate::io; +use crate::os::fd::{AsRawFd, FromRawFd, RawFd}; +use crate::sys::cvt; +use crate::sys::pal::unix::fd::FileDesc; +use crate::sys::process::ExitStatus; +use crate::sys_common::{AsInner, FromInner, IntoInner}; + +#[cfg(test)] +mod tests; + +#[derive(Debug)] +pub(crate) struct PidFd(FileDesc); + +impl PidFd { + pub fn kill(&self) -> io::Result<()> { + return cvt(unsafe { + libc::syscall( + libc::SYS_pidfd_send_signal, + self.0.as_raw_fd(), + libc::SIGKILL, + crate::ptr::null::<()>(), + 0, + ) + }) + .map(drop); + } + + pub fn wait(&self) -> io::Result<ExitStatus> { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + cvt(unsafe { + libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) + })?; + return Ok(ExitStatus::from_waitid_siginfo(siginfo)); + } + + pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + + cvt(unsafe { + libc::waitid( + libc::P_PIDFD, + self.0.as_raw_fd() as u32, + &mut siginfo, + libc::WEXITED | libc::WNOHANG, + ) + })?; + if unsafe { siginfo.si_pid() } == 0 { + return Ok(None); + } + return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))); + } +} + +impl AsInner<FileDesc> for PidFd { + fn as_inner(&self) -> &FileDesc { + &self.0 + } +} + +impl IntoInner<FileDesc> for PidFd { + fn into_inner(self) -> FileDesc { + self.0 + } +} + +impl FromInner<FileDesc> for PidFd { + fn from_inner(inner: FileDesc) -> Self { + Self(inner) + } +} + +impl FromRawFd for PidFd { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Self(FileDesc::from_raw_fd(fd)) + } +} diff --git a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs new file mode 100644 index 00000000000..6d9532f2ef1 --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs @@ -0,0 +1,87 @@ +use crate::assert_matches::assert_matches; +use crate::os::fd::{AsRawFd, RawFd}; +use crate::os::linux::process::{ChildExt, CommandExt}; +use crate::os::unix::process::ExitStatusExt; +use crate::process::Command; + +#[test] +fn test_command_pidfd() { + let pidfd_open_available = probe_pidfd_support(); + + // always exercise creation attempts + let mut child = Command::new("false").create_pidfd(true).spawn().unwrap(); + + // but only check if we know that the kernel supports pidfds. + // We don't assert the precise value, since the standard library + // might have opened other file descriptors before our code runs. + if pidfd_open_available { + assert!(child.pidfd().is_ok()); + } + if let Ok(pidfd) = child.pidfd() { + let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap(); + assert!(flags & libc::FD_CLOEXEC != 0); + } + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.code(), Some(1)); + + let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap(); + assert_matches!(child.try_wait(), Ok(None)); + child.kill().expect("failed to kill child"); + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.signal(), Some(libc::SIGKILL)); + + let _ = Command::new("echo") + .create_pidfd(false) + .spawn() + .unwrap() + .pidfd() + .expect_err("pidfd should not have been created when create_pid(false) is set"); + + let _ = Command::new("echo") + .spawn() + .unwrap() + .pidfd() + .expect_err("pidfd should not have been created"); +} + +#[test] +fn test_pidfd() { + if !probe_pidfd_support() { + return; + } + + let child = Command::new("sleep") + .arg("1000") + .create_pidfd(true) + .spawn() + .expect("executing 'sleep' failed"); + + let fd = child.into_pidfd().unwrap(); + + assert_matches!(fd.try_wait(), Ok(None)); + fd.kill().expect("kill failed"); + fd.kill().expect("sending kill twice failed"); + let status = fd.wait().expect("1st wait failed"); + assert_eq!(status.signal(), Some(libc::SIGKILL)); + + // Trying to wait again for a reaped child is safe since there's no pid-recycling race. + // But doing so will return an error. + let res = fd.wait(); + assert_matches!(res, Err(e) if e.raw_os_error() == Some(libc::ECHILD)); + + // Ditto for additional attempts to kill an already-dead child. + let res = fd.kill(); + assert_matches!(res, Err(e) if e.raw_os_error() == Some(libc::ESRCH)); +} + +fn probe_pidfd_support() -> bool { + // pidfds require the pidfd_open syscall + let our_pid = crate::process::id(); + let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) }; + if pidfd >= 0 { + unsafe { libc::close(pidfd as RawFd) }; + true + } else { + false + } +} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 735ed96bc7b..b370f06e92b 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -20,6 +20,8 @@ pub mod io; pub mod kernel_copy; #[cfg(target_os = "l4re")] mod l4re; +#[cfg(target_os = "linux")] +pub mod linux; #[cfg(not(target_os = "l4re"))] pub mod net; #[cfg(target_os = "l4re")] diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 72bda90a9ba..32382d9a50c 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -7,9 +7,7 @@ use crate::sys::cvt; use crate::sys::process::process_common::*; #[cfg(target_os = "linux")] -use crate::os::linux::process::PidFd; -#[cfg(target_os = "linux")] -use crate::os::unix::io::AsRawFd; +use crate::sys::pal::unix::linux::pidfd::PidFd; #[cfg(target_os = "vxworks")] use libc::RTP_ID as pid_t; @@ -815,16 +813,7 @@ impl Process { #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { // pidfd_send_signal predates pidfd_open. so if we were able to get an fd then sending signals will work too - return cvt(unsafe { - libc::syscall( - libc::SYS_pidfd_send_signal, - pid_fd.as_raw_fd(), - libc::SIGKILL, - crate::ptr::null::<()>(), - 0, - ) - }) - .map(drop); + return pid_fd.kill(); } cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) } @@ -836,12 +825,7 @@ impl Process { } #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { - let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; - - cvt_r(|| unsafe { - libc::waitid(libc::P_PIDFD, pid_fd.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) - })?; - let status = ExitStatus::from_waitid_siginfo(siginfo); + let status = pid_fd.wait()?; self.status = Some(status); return Ok(status); } @@ -857,22 +841,11 @@ impl Process { } #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { - let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; - - cvt(unsafe { - libc::waitid( - libc::P_PIDFD, - pid_fd.as_raw_fd() as u32, - &mut siginfo, - libc::WEXITED | libc::WNOHANG, - ) - })?; - if unsafe { siginfo.si_pid() } == 0 { - return Ok(None); + let status = pid_fd.try_wait()?; + if let Some(status) = status { + self.status = Some(status) } - let status = ExitStatus::from_waitid_siginfo(siginfo); - self.status = Some(status); - return Ok(Some(status)); + return Ok(status); } let mut status = 0 as c_int; let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?; @@ -1105,20 +1078,33 @@ impl ExitStatusError { } #[cfg(target_os = "linux")] -#[unstable(feature = "linux_pidfd", issue = "82971")] -impl crate::os::linux::process::ChildExt for crate::process::Child { - fn pidfd(&self) -> io::Result<&PidFd> { - self.handle - .pidfd - .as_ref() - .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) - } +mod linux_child_ext { + + use crate::io; + use crate::mem; + use crate::os::linux::process as os; + use crate::sys::pal::unix::linux::pidfd as imp; + use crate::sys::pal::unix::ErrorKind; + use crate::sys_common::FromInner; + + #[unstable(feature = "linux_pidfd", issue = "82971")] + impl crate::os::linux::process::ChildExt for crate::process::Child { + fn pidfd(&self) -> io::Result<&os::PidFd> { + self.handle + .pidfd + .as_ref() + // SAFETY: The os type is a transparent wrapper, therefore we can transmute references + .map(|fd| unsafe { mem::transmute::<&imp::PidFd, &os::PidFd>(fd) }) + .ok_or_else(|| io::Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + } - fn take_pidfd(&mut self) -> io::Result<PidFd> { - self.handle - .pidfd - .take() - .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + fn into_pidfd(mut self) -> Result<os::PidFd, Self> { + self.handle + .pidfd + .take() + .map(|fd| <os::PidFd as FromInner<imp::PidFd>>::from_inner(fd)) + .ok_or_else(|| self) + } } } diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index 0a6c6ec19fc..e5e1f956bc3 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -60,57 +60,3 @@ fn test_command_fork_no_unwind() { || signal == libc::SIGSEGV ); } - -#[test] -#[cfg(target_os = "linux")] // pidfds are a linux-specific concept -fn test_command_pidfd() { - use crate::assert_matches::assert_matches; - use crate::os::fd::{AsRawFd, RawFd}; - use crate::os::linux::process::{ChildExt, CommandExt}; - use crate::process::Command; - - // pidfds require the pidfd_open syscall - let our_pid = crate::process::id(); - let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) }; - let pidfd_open_available = if pidfd >= 0 { - unsafe { libc::close(pidfd as RawFd) }; - true - } else { - false - }; - - // always exercise creation attempts - let mut child = Command::new("false").create_pidfd(true).spawn().unwrap(); - - // but only check if we know that the kernel supports pidfds. - // We don't assert the precise value, since the standard library - // might have opened other file descriptors before our code runs. - if pidfd_open_available { - assert!(child.pidfd().is_ok()); - } - if let Ok(pidfd) = child.pidfd() { - let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap(); - assert!(flags & libc::FD_CLOEXEC != 0); - } - let status = child.wait().expect("error waiting on pidfd"); - assert_eq!(status.code(), Some(1)); - - let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap(); - assert_matches!(child.try_wait(), Ok(None)); - child.kill().expect("failed to kill child"); - let status = child.wait().expect("error waiting on pidfd"); - assert_eq!(status.signal(), Some(libc::SIGKILL)); - - let _ = Command::new("echo") - .create_pidfd(false) - .spawn() - .unwrap() - .pidfd() - .expect_err("pidfd should not have been created when create_pid(false) is set"); - - let _ = Command::new("echo") - .spawn() - .unwrap() - .pidfd() - .expect_err("pidfd should not have been created"); -} diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 3ebf1cfd33f..619f4e4121e 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -478,7 +478,7 @@ mod cgroups { use crate::borrow::Cow; use crate::ffi::OsString; - use crate::fs::{try_exists, File}; + use crate::fs::{exists, File}; use crate::io::Read; use crate::io::{BufRead, BufReader}; use crate::os::unix::ffi::OsStringExt; @@ -556,7 +556,7 @@ mod cgroups { path.push("cgroup.controllers"); // skip if we're not looking at cgroup2 - if matches!(try_exists(&path), Err(_) | Ok(false)) { + if matches!(exists(&path), Err(_) | Ok(false)) { return usize::MAX; }; @@ -613,7 +613,7 @@ mod cgroups { path.push(&group_path); // skip if we guessed the mount incorrectly - if matches!(try_exists(&path), Err(_) | Ok(false)) { + if matches!(exists(&path), Err(_) | Ok(false)) { continue; } diff --git a/library/std/src/sys/pal/unsupported/fs.rs b/library/std/src/sys/pal/unsupported/fs.rs index 6ac1b5d2bcf..474c9fe97d1 100644 --- a/library/std/src/sys/pal/unsupported/fs.rs +++ b/library/std/src/sys/pal/unsupported/fs.rs @@ -291,7 +291,7 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> { unsupported() } -pub fn try_exists(_path: &Path) -> io::Result<bool> { +pub fn exists(_path: &Path) -> io::Result<bool> { unsupported() } diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 529b82e0198..c58e6a08b37 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -17,7 +17,7 @@ use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::{AsInner, FromInner, IntoInner}; -pub use crate::sys_common::fs::try_exists; +pub use crate::sys_common::fs::exists; pub struct File { fd: WasiFd, diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 629ff114b5a..cc68f5ef5f0 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1531,7 +1531,7 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { } // Try to see if a file exists but, unlike `exists`, report I/O errors. -pub fn try_exists(path: &Path) -> io::Result<bool> { +pub fn exists(path: &Path) -> io::Result<bool> { // Open the file to ensure any symlinks are followed to their target. let mut opts = OpenOptions::new(); // No read, write, etc access rights are needed. diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index 617ac52e51c..acb6713cf1b 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -42,7 +42,7 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { fs::remove_dir(path) } -pub fn try_exists(path: &Path) -> io::Result<bool> { +pub fn exists(path: &Path) -> io::Result<bool> { match fs::metadata(path) { Ok(_) => Ok(true), Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs index 381ee7ef53b..004174e35e1 100644 --- a/src/bootstrap/src/core/build_steps/mod.rs +++ b/src/bootstrap/src/core/build_steps/mod.rs @@ -7,6 +7,7 @@ pub(crate) mod doc; pub(crate) mod format; pub(crate) mod install; pub(crate) mod llvm; +pub(crate) mod perf; pub(crate) mod run; pub(crate) mod setup; pub(crate) mod suggest; diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs new file mode 100644 index 00000000000..9d70ca6bd71 --- /dev/null +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -0,0 +1,45 @@ +use std::process::Command; + +use crate::core::build_steps::compile::{Std, Sysroot}; +use crate::core::build_steps::tool::RustcPerf; +use crate::core::builder::Builder; +use crate::core::config::DebuginfoLevel; + +/// Performs profiling using `rustc-perf` on a built version of the compiler. +pub fn perf(builder: &Builder<'_>) { + let collector = builder.ensure(RustcPerf { + compiler: builder.compiler(0, builder.config.build), + target: builder.config.build, + }); + + if builder.build.config.rust_debuginfo_level_rustc == DebuginfoLevel::None { + builder.info(r#"WARNING: You are compiling rustc without debuginfo, this will make profiling less useful. +Consider setting `rust.debuginfo-level = 1` in `config.toml`."#); + } + + let compiler = builder.compiler(builder.top_stage, builder.config.build); + builder.ensure(Std::new(compiler, builder.config.build)); + let sysroot = builder.ensure(Sysroot::new(compiler)); + let rustc = sysroot.join("bin/rustc"); + + let results_dir = builder.build.tempdir().join("rustc-perf"); + + let mut cmd = Command::new(collector); + let cmd = cmd + .arg("profile_local") + .arg("eprintln") + .arg("--out-dir") + .arg(&results_dir) + .arg("--include") + .arg("helloworld") + .arg(&rustc); + + builder.info(&format!("Running `rustc-perf` using `{}`", rustc.display())); + + // We need to set the working directory to `src/tools/perf`, so that it can find the directory + // with compile-time benchmarks. + let cmd = cmd.current_dir(builder.src.join("src/tools/rustc-perf")); + builder.build.run(cmd); + + builder.info(&format!("You can find the results at `{}`", results_dir.display())); +} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 5459b4c7b29..8a2bc3b9d48 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -26,7 +26,7 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::flags::get_completion; use crate::core::config::flags::Subcommand; use crate::core::config::TargetSelection; -use crate::utils::exec::BootstrapCommand; +use crate::utils::exec::{BootstrapCommand, OutputMode}; use crate::utils::helpers::{ self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, linker_args, linker_flags, output, t, target_supports_cranelift_backend, up_to_date, @@ -156,7 +156,10 @@ You can skip linkcheck with --skip src/tools/linkchecker" let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = helpers::timeit(builder); - builder.run_delaying_failure(linkchecker.arg(builder.out.join(host.triple).join("doc"))); + builder.run_tracked( + BootstrapCommand::from(linkchecker.arg(builder.out.join(host.triple).join("doc"))) + .delay_failure(), + ); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -213,8 +216,11 @@ impl Step for HtmlCheck { builder, )); - builder.run_delaying_failure( - builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), + builder.run_tracked( + BootstrapCommand::from( + builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), + ) + .delay_failure(), ); } } @@ -261,7 +267,7 @@ impl Step for Cargotest { .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)); add_rustdoc_cargo_linker_args(cmd, builder, compiler.host, LldThreads::No); - builder.run_delaying_failure(cmd); + builder.run_tracked(BootstrapCommand::from(cmd).delay_failure()); } } @@ -813,7 +819,7 @@ impl Step for RustdocTheme { .env("RUSTC_BOOTSTRAP", "1"); cmd.args(linker_args(builder, self.compiler.host, LldThreads::No)); - builder.run_delaying_failure(&mut cmd); + builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); } } @@ -1093,7 +1099,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } builder.info("tidy check"); - builder.run_delaying_failure(&mut cmd); + builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); builder.info("x.py completions check"); let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] @@ -2179,7 +2185,8 @@ impl BookTest { compiler.host, ); let _time = helpers::timeit(builder); - let toolstate = if builder.run_delaying_failure(&mut rustbook_cmd) { + let cmd = BootstrapCommand::from(&mut rustbook_cmd).delay_failure(); + let toolstate = if builder.run_tracked(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail @@ -2312,7 +2319,8 @@ impl Step for ErrorIndex { let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = helpers::timeit(builder); - builder.run_quiet(&mut tool); + builder + .run_tracked(BootstrapCommand::from(&mut tool).output_mode(OutputMode::OnlyOnFailure)); drop(guard); // The tests themselves need to link to std, so make sure it is // available. @@ -2341,11 +2349,11 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> let test_args = builder.config.test_args().join(" "); cmd.arg("--test-args").arg(test_args); - if builder.config.verbose_tests { - builder.run_delaying_failure(&mut cmd) - } else { - builder.run_quiet_delaying_failure(&mut cmd) + let mut cmd = BootstrapCommand::from(&mut cmd).delay_failure(); + if !builder.config.verbose_tests { + cmd = cmd.quiet(); } + builder.run_tracked(cmd).is_success() } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2370,7 +2378,8 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - let toolstate = if builder.run_delaying_failure(rustbook_cmd.arg("linkcheck").arg(&src)) { + let cmd = BootstrapCommand::from(rustbook_cmd.arg("linkcheck").arg(&src)).delay_failure(); + let toolstate = if builder.run_tracked(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail @@ -2984,7 +2993,7 @@ impl Step for Bootstrap { .current_dir(builder.src.join("src/bootstrap/")); // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible. // Use `python -m unittest` manually if you want to pass arguments. - builder.run_delaying_failure(&mut check_bootstrap); + builder.run_tracked(BootstrapCommand::from(&mut check_bootstrap).delay_failure()); let mut cmd = Command::new(&builder.initial_cargo); cmd.arg("test") @@ -3061,7 +3070,7 @@ impl Step for TierCheck { self.compiler.host, self.compiler.host, ); - builder.run_delaying_failure(&mut cargo.into()); + builder.run_tracked(BootstrapCommand::from(&mut cargo.into()).delay_failure()); } } @@ -3147,7 +3156,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - builder.run_delaying_failure(&mut cmd); + builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 613484788b6..850c8bfe2f8 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -32,6 +32,8 @@ struct ToolBuild { extra_features: Vec<String>, /// Nightly-only features that are allowed (comma-separated list). allow_features: &'static str, + /// Additional arguments to pass to the `cargo` invocation. + cargo_args: Vec<String>, } impl Builder<'_> { @@ -100,6 +102,7 @@ impl Step for ToolBuild { if !self.allow_features.is_empty() { cargo.allow_features(self.allow_features); } + cargo.args(self.cargo_args); let _guard = builder.msg_tool( Kind::Build, self.mode, @@ -126,10 +129,7 @@ impl Step for ToolBuild { if tool == "tidy" { tool = "rust-tidy"; } - let cargo_out = builder.cargo_out(compiler, self.mode, target).join(exe(tool, target)); - let bin = builder.tools_dir(compiler).join(exe(tool, target)); - builder.copy_link(&cargo_out, &bin); - bin + copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool) } } } @@ -214,6 +214,21 @@ pub fn prepare_tool_cargo( cargo } +/// Links a built tool binary with the given `name` from the build directory to the +/// tools directory. +fn copy_link_tool_bin( + builder: &Builder<'_>, + compiler: Compiler, + target: TargetSelection, + mode: Mode, + name: &str, +) -> PathBuf { + let cargo_out = builder.cargo_out(compiler, mode, target).join(exe(name, target)); + let bin = builder.tools_dir(compiler).join(exe(name, target)); + builder.copy_link(&cargo_out, &bin); + bin +} + macro_rules! bootstrap_tool { ($( $name:ident, $path:expr, $tool_name:expr @@ -283,6 +298,7 @@ macro_rules! bootstrap_tool { }, extra_features: vec![], allow_features: concat!($($allow_features)*), + cargo_args: vec![] }) } } @@ -349,10 +365,60 @@ impl Step for OptimizedDist { source_type: SourceType::InTree, extra_features: Vec::new(), allow_features: "", + cargo_args: Vec::new(), }) } } +/// The [rustc-perf](https://github.com/rust-lang/rustc-perf) benchmark suite, which is added +/// as a submodule at `src/tools/rustc-perf`. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct RustcPerf { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Step for RustcPerf { + /// Path to the built `collector` binary. + type Output = PathBuf; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/rustc-perf") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(RustcPerf { + compiler: run.builder.compiler(0, run.builder.config.build), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + // We need to ensure the rustc-perf submodule is initialized. + builder.update_submodule(Path::new("src/tools/rustc-perf")); + + let tool = ToolBuild { + compiler: self.compiler, + target: self.target, + tool: "collector", + mode: Mode::ToolBootstrap, + path: "src/tools/rustc-perf", + source_type: SourceType::Submodule, + extra_features: Vec::new(), + allow_features: "", + // Only build the collector package, which is used for benchmarking through + // a CLI. + cargo_args: vec!["-p".to_string(), "collector".to_string()], + }; + let collector_bin = builder.ensure(tool.clone()); + // We also need to symlink the `rustc-fake` binary to the corresponding directory, + // because `collector` expects it in the same directory. + copy_link_tool_bin(builder, tool.compiler, tool.target, tool.mode, "rustc-fake"); + + collector_bin + } +} + #[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] pub struct ErrorIndex { pub compiler: Compiler, @@ -403,6 +469,7 @@ impl Step for ErrorIndex { source_type: SourceType::InTree, extra_features: Vec::new(), allow_features: "", + cargo_args: Vec::new(), }) } } @@ -437,6 +504,7 @@ impl Step for RemoteTestServer { source_type: SourceType::InTree, extra_features: Vec::new(), allow_features: "", + cargo_args: Vec::new(), }) } } @@ -595,6 +663,7 @@ impl Step for Cargo { source_type: SourceType::Submodule, extra_features: Vec::new(), allow_features: "", + cargo_args: Vec::new(), }) } } @@ -622,6 +691,7 @@ impl Step for LldWrapper { source_type: SourceType::InTree, extra_features: Vec::new(), allow_features: "", + cargo_args: Vec::new(), }) } } @@ -670,6 +740,7 @@ impl Step for RustAnalyzer { extra_features: vec!["in-rust-tree".to_owned()], source_type: SourceType::InTree, allow_features: RustAnalyzer::ALLOW_FEATURES, + cargo_args: Vec::new(), }) } } @@ -717,6 +788,7 @@ impl Step for RustAnalyzerProcMacroSrv { extra_features: vec!["in-rust-tree".to_owned()], source_type: SourceType::InTree, allow_features: RustAnalyzer::ALLOW_FEATURES, + cargo_args: Vec::new(), }); // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/` @@ -923,6 +995,7 @@ macro_rules! tool_extended { extra_features: $sel.extra_features, source_type: SourceType::InTree, allow_features: concat!($($allow_features)*), + cargo_args: vec![] }); if (false $(|| !$add_bins_to_sysroot.is_empty())?) && $sel.compiler.stage > 0 { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 3c4806a1311..a638d6f31db 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -666,6 +666,7 @@ pub enum Kind { Setup, Suggest, Vendor, + Perf, } impl Kind { @@ -687,6 +688,7 @@ impl Kind { Kind::Setup => "setup", Kind::Suggest => "suggest", Kind::Vendor => "vendor", + Kind::Perf => "perf", } } @@ -698,6 +700,7 @@ impl Kind { Kind::Run => "Running", Kind::Suggest => "Suggesting", Kind::Clippy => "Linting", + Kind::Perf => "Profiling & benchmarking", _ => { let title_letter = self.as_str()[0..1].to_ascii_uppercase(); return format!("{title_letter}{}ing", &self.as_str()[1..]); @@ -749,7 +752,8 @@ impl<'a> Builder<'a> { tool::RustdocGUITest, tool::OptimizedDist, tool::CoverageDump, - tool::LlvmBitcodeLinker + tool::LlvmBitcodeLinker, + tool::RustcPerf, ), Kind::Clippy => describe!( clippy::Std, @@ -945,7 +949,7 @@ impl<'a> Builder<'a> { Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std), Kind::Vendor => describe!(vendor::Vendor), // special-cased in Build::build() - Kind::Format | Kind::Suggest => vec![], + Kind::Format | Kind::Suggest | Kind::Perf => vec![], } } @@ -1017,6 +1021,7 @@ impl<'a> Builder<'a> { path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)), ), Subcommand::Vendor { .. } => (Kind::Vendor, &paths[..]), + Subcommand::Perf { .. } => (Kind::Perf, &paths[..]), }; Self::new_internal(build, kind, paths.to_owned()) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 0438dee7241..948f97e746f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2043,6 +2043,7 @@ impl Config { Subcommand::Bench { .. } => flags.stage.or(bench_stage).unwrap_or(2), Subcommand::Dist { .. } => flags.stage.or(dist_stage).unwrap_or(2), Subcommand::Install { .. } => flags.stage.or(install_stage).unwrap_or(2), + Subcommand::Perf { .. } => flags.stage.unwrap_or(1), // These are all bootstrap tools, which don't depend on the compiler. // The stage we pass shouldn't matter, but use 0 just in case. Subcommand::Clean { .. } @@ -2080,7 +2081,8 @@ impl Config { | Subcommand::Setup { .. } | Subcommand::Format { .. } | Subcommand::Suggest { .. } - | Subcommand::Vendor { .. } => {} + | Subcommand::Vendor { .. } + | Subcommand::Perf { .. } => {} } } diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 83def0c6df0..eb5152a3831 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -469,6 +469,9 @@ Arguments: #[arg(long)] versioned_dirs: bool, }, + /// Perform profiling and benchmarking of the compiler using the + /// `rustc-perf` benchmark suite. + Perf {}, } impl Subcommand { @@ -490,6 +493,7 @@ impl Subcommand { Subcommand::Setup { .. } => Kind::Setup, Subcommand::Suggest { .. } => Kind::Suggest, Subcommand::Vendor { .. } => Kind::Vendor, + Subcommand::Perf { .. } => Kind::Perf, } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 449d8c128ec..dfc30298c28 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -23,7 +23,7 @@ use std::fmt::Display; use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; -use std::process::{Command, Output, Stdio}; +use std::process::{Command, Stdio}; use std::str; use std::sync::OnceLock; @@ -41,7 +41,7 @@ use crate::core::builder::Kind; use crate::core::config::{flags, LldMode}; use crate::core::config::{DryRun, Target}; use crate::core::config::{LlvmLibunwind, TargetSelection}; -use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, OutputMode}; +use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode}; use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir}; mod core; @@ -585,8 +585,8 @@ impl Build { BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) .allow_failure() .output_mode(match self.is_verbose() { - true => OutputMode::PrintAll, - false => OutputMode::PrintOutput, + true => OutputMode::All, + false => OutputMode::OnlyOutput, }), ); if has_local_modifications { @@ -659,6 +659,9 @@ impl Build { Subcommand::Suggest { run } => { return core::build_steps::suggest::suggest(&builder::Builder::new(self), *run); } + Subcommand::Perf { .. } => { + return core::build_steps::perf::perf(&builder::Builder::new(self)); + } _ => (), } @@ -958,73 +961,36 @@ impl Build { }) } - /// Runs a command, printing out nice contextual information if it fails. - fn run(&self, cmd: &mut Command) { - self.run_cmd(BootstrapCommand::from(cmd).fail_fast().output_mode( - match self.is_verbose() { - true => OutputMode::PrintAll, - false => OutputMode::PrintOutput, - }, - )); - } - - /// Runs a command, printing out contextual info if it fails, and delaying errors until the build finishes. - pub(crate) fn run_delaying_failure(&self, cmd: &mut Command) -> bool { - self.run_cmd(BootstrapCommand::from(cmd).delay_failure().output_mode( - match self.is_verbose() { - true => OutputMode::PrintAll, - false => OutputMode::PrintOutput, - }, - )) - } - - /// Runs a command, printing out nice contextual information if it fails. - fn run_quiet(&self, cmd: &mut Command) { - self.run_cmd( - BootstrapCommand::from(cmd).fail_fast().output_mode(OutputMode::SuppressOnSuccess), - ); - } - - /// Runs a command, printing out nice contextual information if it fails. - /// Exits if the command failed to execute at all, otherwise returns its - /// `status.success()`. - fn run_quiet_delaying_failure(&self, cmd: &mut Command) -> bool { - self.run_cmd( - BootstrapCommand::from(cmd).delay_failure().output_mode(OutputMode::SuppressOnSuccess), - ) - } - - /// A centralized function for running commands that do not return output. - pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool { + /// Execute a command and return its output. + fn run_tracked(&self, command: BootstrapCommand<'_>) -> CommandOutput { if self.config.dry_run() { - return true; + return CommandOutput::default(); } - let command = cmd.into(); self.verbose(|| println!("running: {command:?}")); - let (output, print_error) = match command.output_mode { - mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => ( - command.command.status().map(|status| Output { - status, - stdout: Vec::new(), - stderr: Vec::new(), - }), - matches!(mode, OutputMode::PrintAll), + let output_mode = command.output_mode.unwrap_or_else(|| match self.is_verbose() { + true => OutputMode::All, + false => OutputMode::OnlyOutput, + }); + let (output, print_error): (io::Result<CommandOutput>, bool) = match output_mode { + mode @ (OutputMode::All | OutputMode::OnlyOutput) => ( + command.command.status().map(|status| status.into()), + matches!(mode, OutputMode::All), ), - OutputMode::SuppressOnSuccess => (command.command.output(), true), + OutputMode::OnlyOnFailure => (command.command.output().map(|o| o.into()), true), }; let output = match output { Ok(output) => output, Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", command, e)), }; - let result = if !output.status.success() { + if !output.is_success() { if print_error { println!( "\n\nCommand did not execute successfully.\ - \nExpected success, got: {}", - output.status, + \nExpected success, got: {}", + output.status(), ); if !self.is_verbose() { @@ -1034,37 +1000,45 @@ impl Build { self.verbose(|| { println!( "\nSTDOUT ----\n{}\n\ - STDERR ----\n{}\n", - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) + STDERR ----\n{}\n", + output.stdout(), + output.stderr(), ) }); } - Err(()) - } else { - Ok(()) - }; - match result { - Ok(_) => true, - Err(_) => { - match command.failure_behavior { - BehaviorOnFailure::DelayFail => { - if self.fail_fast { - exit!(1); - } - - let mut failures = self.delayed_failures.borrow_mut(); - failures.push(format!("{command:?}")); - } - BehaviorOnFailure::Exit => { + match command.failure_behavior { + BehaviorOnFailure::DelayFail => { + if self.fail_fast { exit!(1); } - BehaviorOnFailure::Ignore => {} + + let mut failures = self.delayed_failures.borrow_mut(); + failures.push(format!("{command:?}")); + } + BehaviorOnFailure::Exit => { + exit!(1); } - false + BehaviorOnFailure::Ignore => {} } } + output + } + + /// Runs a command, printing out nice contextual information if it fails. + fn run(&self, cmd: &mut Command) { + self.run_cmd(BootstrapCommand::from(cmd).fail_fast().output_mode( + match self.is_verbose() { + true => OutputMode::All, + false => OutputMode::OnlyOutput, + }, + )); + } + + /// A centralized function for running commands that do not return output. + pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool { + let command = cmd.into(); + self.run_tracked(command).is_success() } /// Check if verbosity is greater than the `level` diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 0aede2022ba..e8c588b75b3 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -1,4 +1,4 @@ -use std::process::Command; +use std::process::{Command, ExitStatus, Output}; /// What should be done when the command fails. #[derive(Debug, Copy, Clone)] @@ -16,11 +16,11 @@ pub enum BehaviorOnFailure { pub enum OutputMode { /// Print both the output (by inheriting stdout/stderr) and also the command itself, if it /// fails. - PrintAll, + All, /// Print the output (by inheriting stdout/stderr). - PrintOutput, + OnlyOutput, /// Suppress the output if the command succeeds, otherwise print the output. - SuppressOnSuccess, + OnlyOnFailure, } /// Wrapper around `std::process::Command`. @@ -28,7 +28,7 @@ pub enum OutputMode { pub struct BootstrapCommand<'a> { pub command: &'a mut Command, pub failure_behavior: BehaviorOnFailure, - pub output_mode: OutputMode, + pub output_mode: Option<OutputMode>, } impl<'a> BootstrapCommand<'a> { @@ -44,17 +44,62 @@ impl<'a> BootstrapCommand<'a> { Self { failure_behavior: BehaviorOnFailure::Ignore, ..self } } + /// Do not print the output of the command, unless it fails. + pub fn quiet(self) -> Self { + self.output_mode(OutputMode::OnlyOnFailure) + } + pub fn output_mode(self, output_mode: OutputMode) -> Self { - Self { output_mode, ..self } + Self { output_mode: Some(output_mode), ..self } } } impl<'a> From<&'a mut Command> for BootstrapCommand<'a> { fn from(command: &'a mut Command) -> Self { - Self { - command, - failure_behavior: BehaviorOnFailure::Exit, - output_mode: OutputMode::PrintAll, - } + Self { command, failure_behavior: BehaviorOnFailure::Exit, output_mode: None } + } +} + +/// Represents the output of an executed process. +#[allow(unused)] +pub struct CommandOutput(Output); + +impl CommandOutput { + pub fn is_success(&self) -> bool { + self.0.status.success() + } + + pub fn is_failure(&self) -> bool { + !self.is_success() + } + + pub fn status(&self) -> ExitStatus { + self.0.status + } + + pub fn stdout(&self) -> String { + String::from_utf8(self.0.stdout.clone()).expect("Cannot parse process stdout as UTF-8") + } + + pub fn stderr(&self) -> String { + String::from_utf8(self.0.stderr.clone()).expect("Cannot parse process stderr as UTF-8") + } +} + +impl Default for CommandOutput { + fn default() -> Self { + Self(Output { status: Default::default(), stdout: vec![], stderr: vec![] }) + } +} + +impl From<Output> for CommandOutput { + fn from(output: Output) -> Self { + Self(output) + } +} + +impl From<ExitStatus> for CommandOutput { + fn from(status: ExitStatus) -> Self { + Self(Output { status, stdout: vec![], stderr: vec![] }) } } diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index 115ee69a589..6db25ff1a80 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -112,7 +112,7 @@ def atomic_link(link: Path, target: Path): os.remove(tmp_file) -@dataclass(kw_only=True) +@dataclass class TestEnvironment: rust_build_dir: Path sdk_dir: Path diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index 02a009d56d3..c262d3f6da1 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -18,7 +18,7 @@ All intrinsic fallback bodies are automatically made cross-crate inlineable (lik by the codegen backend, but not the MIR inliner. ```rust -#![feature(rustc_attrs, effects)] +#![feature(rustc_attrs)] #![allow(internal_features)] #[rustc_intrinsic] @@ -28,7 +28,7 @@ const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} Since these are just regular functions, it is perfectly ok to create the intrinsic twice: ```rust -#![feature(rustc_attrs, effects)] +#![feature(rustc_attrs)] #![allow(internal_features)] #[rustc_intrinsic] diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 7343f3147ee..2072f76a481 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -48,6 +48,7 @@ complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development' complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files' complete -c x.py -n "__fish_use_subcommand" -f -a "vendor" -d 'Vendor dependencies' +complete -c x.py -n "__fish_use_subcommand" -f -a "perf" -d 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite' complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f @@ -628,3 +629,37 @@ complete -c x.py -n "__fish_seen_subcommand_from vendor" -l llvm-profile-generat complete -c x.py -n "__fish_seen_subcommand_from vendor" -l enable-bolt-settings -d 'Enable BOLT link flags' complete -c x.py -n "__fish_seen_subcommand_from vendor" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from vendor" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l config -d 'TOML configuration file for build' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_seen_subcommand_from perf" -l build -d 'build target of the stage0 compiler' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l host -d 'host targets to build' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l target -d 'target targets to build' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l skip -d 'build paths to skip' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l rustc-error-format -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" +complete -c x.py -n "__fish_seen_subcommand_from perf" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_seen_subcommand_from perf" -s j -l jobs -d 'number of jobs to run in parallel' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}" +complete -c x.py -n "__fish_seen_subcommand_from perf" -l error-format -d 'rustc error format' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}" +complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}" +complete -c x.py -n "__fish_seen_subcommand_from perf" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F +complete -c x.py -n "__fish_seen_subcommand_from perf" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r +complete -c x.py -n "__fish_seen_subcommand_from perf" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_seen_subcommand_from perf" -s v -l verbose -d 'use verbose output (-vv for very verbose)' +complete -c x.py -n "__fish_seen_subcommand_from perf" -s i -l incremental -d 'use incremental compilation' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l include-default-paths -d 'include default paths in addition to the provided ones' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l dry-run -d 'dry run; don\'t build anything' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l json-output -d 'use message-format=json' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l enable-bolt-settings -d 'Enable BOLT link flags' +complete -c x.py -n "__fish_seen_subcommand_from perf" -l skip-stage0-validation -d 'Skip stage0 compiler validation' +complete -c x.py -n "__fish_seen_subcommand_from perf" -s h -l help -d 'Print help (see more with \'--help\')' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index d9adb1778f2..919382d441f 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -75,6 +75,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development') [CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files') [CompletionResult]::new('vendor', 'vendor', [CompletionResultType]::ParameterValue, 'Vendor dependencies') + [CompletionResult]::new('perf', 'perf', [CompletionResultType]::ParameterValue, 'Perform profiling and benchmarking of the compiler using the `rustc-perf` benchmark suite') break } 'x.py;build' { @@ -769,6 +770,47 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') break } + 'x.py;perf' { + [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') + [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') + [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') + [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') + [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') + [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') + [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') + [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') + [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)') + [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout') + [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel') + [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour') + [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format') + [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output') + [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml') + [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build') + [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') + [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') + [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') + [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') + [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation') + [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones') + [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything') + [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims') + [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json') + [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)') + [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc') + [CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags') + [CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation') + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')') + break + } }) $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 6cb9e95c8c1..a4234905476 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -45,6 +45,9 @@ _x.py() { bootstrap,miri) cmd="bootstrap__miri" ;; + bootstrap,perf) + cmd="bootstrap__perf" + ;; bootstrap,run) cmd="bootstrap__run" ;; @@ -67,7 +70,7 @@ _x.py() { case "${cmd}" in x.py) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1414,6 +1417,116 @@ _x.py() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + x.py__perf) + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --config) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --build-dir) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --build) + COMPREPLY=("${cur}") + return 0 + ;; + --host) + COMPREPLY=("${cur}") + return 0 + ;; + --target) + COMPREPLY=("${cur}") + return 0 + ;; + --exclude) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --rustc-error-format) + COMPREPLY=("${cur}") + return 0 + ;; + --on-fail) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --stage) + COMPREPLY=("${cur}") + return 0 + ;; + --keep-stage) + COMPREPLY=("${cur}") + return 0 + ;; + --keep-stage-std) + COMPREPLY=("${cur}") + return 0 + ;; + --src) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --jobs) + COMPREPLY=("${cur}") + return 0 + ;; + -j) + COMPREPLY=("${cur}") + return 0 + ;; + --warnings) + COMPREPLY=($(compgen -W "deny warn default" -- "${cur}")) + return 0 + ;; + --error-format) + COMPREPLY=("${cur}") + return 0 + ;; + --color) + COMPREPLY=($(compgen -W "always never auto" -- "${cur}")) + return 0 + ;; + --llvm-skip-rebuild) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; + --rust-profile-generate) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --rust-profile-use) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --llvm-profile-use) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --reproducible-artifact) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --set) + COMPREPLY=("${cur}") + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; x.py__run) opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 24ddd1c4b7c..bbebf8b892d 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -789,6 +789,49 @@ _arguments "${_arguments_options[@]}" \ '*::paths -- paths for the subcommand:_files' \ && ret=0 ;; +(perf) +_arguments "${_arguments_options[@]}" \ +'--config=[TOML configuration file for build]:FILE:_files' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build=[build target of the stage0 compiler]:BUILD:( )' \ +'--host=[host targets to build]:HOST:( )' \ +'--target=[target targets to build]:TARGET:( )' \ +'*--exclude=[build paths to exclude]:PATH:_files' \ +'*--skip=[build paths to skip]:PATH:_files' \ +'--rustc-error-format=[]:RUSTC_ERROR_FORMAT:( )' \ +'--on-fail=[command to run on failure]:CMD:_cmdstring' \ +'--stage=[stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)]:N:( )' \ +'*--keep-stage=[stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)]:N:( )' \ +'*--keep-stage-std=[stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)]:N:( )' \ +'--src=[path to the root of the rust checkout]:DIR:_files -/' \ +'-j+[number of jobs to run in parallel]:JOBS:( )' \ +'--jobs=[number of jobs to run in parallel]:JOBS:( )' \ +'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \ +'--error-format=[rustc error format]:FORMAT:( )' \ +'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \ +'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \ +'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \ +'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ +'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ +'*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT: ' \ +'*--set=[override options in config.toml]:section.option=value:( )' \ +'*-v[use verbose output (-vv for very verbose)]' \ +'*--verbose[use verbose output (-vv for very verbose)]' \ +'-i[use incremental compilation]' \ +'--incremental[use incremental compilation]' \ +'--include-default-paths[include default paths in addition to the provided ones]' \ +'--dry-run[dry run; don'\''t build anything]' \ +'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \ +'--json-output[use message-format=json]' \ +'--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \ +'--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \ +'--enable-bolt-settings[Enable BOLT link flags]' \ +'--skip-stage0-validation[Skip stage0 compiler validation]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +'*::paths -- paths for the subcommand:_files' \ +&& ret=0 +;; esac ;; esac @@ -813,6 +856,7 @@ _x.py_commands() { 'setup:Set up the environment for development' \ 'suggest:Suggest a subset of tests to run, based on modified files' \ 'vendor:Vendor dependencies' \ +'perf:Perform profiling and benchmarking of the compiler using the \`rustc-perf\` benchmark suite' \ ) _describe -t commands 'x.py commands' commands "$@" } @@ -871,6 +915,11 @@ _x.py__miri_commands() { local commands; commands=() _describe -t commands 'x.py miri commands' commands "$@" } +(( $+functions[_x.py__perf_commands] )) || +_x.py__perf_commands() { + local commands; commands=() + _describe -t commands 'x.py perf commands' commands "$@" +} (( $+functions[_x.py__run_commands] )) || _x.py__run_commands() { local commands; commands=() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index da41f974068..22565ea4028 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3077,9 +3077,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - // FIXME(missing_unsafe_on_extern) handle safety of foreign fns. - // Safety was added as part of the implementation of unsafe extern blocks PR #124482 - hir::ForeignItemKind::Fn(decl, names, generics, _) => { + hir::ForeignItemKind::Fn(decl, names, generics, safety) => { let (generics, decl) = enter_impl_trait(cx, |cx| { // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); @@ -3087,13 +3085,12 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let decl = clean_fn_decl_with_args(cx, decl, None, args); (generics, decl) }); - ForeignFunctionItem(Box::new(Function { decl, generics })) - } - // FIXME(missing_unsafe_on_extern) handle safety of foreign statics. - // Safety was added as part of the implementation of unsafe extern blocks PR #124482 - hir::ForeignItemKind::Static(ty, mutability, _) => { - ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None }) + ForeignFunctionItem(Box::new(Function { decl, generics }), safety) } + hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( + Static { type_: clean_ty(ty, cx), mutability, expr: None }, + safety, + ), hir::ForeignItemKind::Type => ForeignTypeItem, }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 69678b727c1..c4020f2a450 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -639,14 +639,14 @@ impl Item { hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness } } let header = match *self.kind { - ItemKind::ForeignFunctionItem(_) => { + ItemKind::ForeignFunctionItem(_, safety) => { let def_id = self.def_id().unwrap(); let abi = tcx.fn_sig(def_id).skip_binder().abi(); hir::FnHeader { safety: if abi == Abi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id.expect_local()) } else { - hir::Safety::Unsafe + safety }, abi, constness: if tcx.is_const_fn(def_id) @@ -842,9 +842,9 @@ pub(crate) enum ItemKind { StructFieldItem(Type), VariantItem(Variant), /// `fn`s from an extern block - ForeignFunctionItem(Box<Function>), + ForeignFunctionItem(Box<Function>, hir::Safety), /// `static`s from an extern block - ForeignStaticItem(Static), + ForeignStaticItem(Static, hir::Safety), /// `type`s from an extern block ForeignTypeItem, MacroItem(Macro), @@ -893,8 +893,8 @@ impl ItemKind { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(_, _) + | ForeignStaticItem(_, _) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) @@ -924,8 +924,8 @@ impl ItemKind { | StaticItem(_) | ConstantItem(_, _, _) | TraitAliasItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(_, _) + | ForeignStaticItem(_, _) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index c85b955d4c5..346e9a4e113 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -84,8 +84,8 @@ pub(crate) trait DocFolder: Sized { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(..) + | ForeignStaticItem(..) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e1f79254b24..00973865915 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -254,7 +254,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf match &*item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), - clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => { + clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => { item_function(buf, cx, item, f) } clean::TraitItem(ref t) => item_trait(buf, cx, item, t), @@ -265,7 +265,8 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), - clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i), + clean::StaticItem(ref i) => item_static(buf, cx, item, i, None), + clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)), clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem => item_keyword(buf, cx, item), @@ -491,11 +492,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: } let unsafety_flag = match *myitem.kind { - clean::FunctionItem(_) | clean::ForeignFunctionItem(_) + clean::FunctionItem(_) | clean::ForeignFunctionItem(..) if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe => { "<sup title=\"unsafe function\">⚠</sup>" } + clean::ForeignStaticItem(_, hir::Safety::Unsafe) => { + "<sup title=\"unsafe static\">⚠</sup>" + } _ => "", }; @@ -1957,13 +1961,22 @@ fn item_fields( } } -fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { +fn item_static( + w: &mut impl fmt::Write, + cx: &mut Context<'_>, + it: &clean::Item, + s: &clean::Static, + safety: Option<hir::Safety>, +) { wrap_item(w, |buffer| { render_attributes_in_code(buffer, it, cx); write!( buffer, - "{vis}static {mutability}{name}: {typ}", + "{vis}{safe}static {mutability}{name}: {typ}", vis = visibility_print_with_space(it, cx), + safe = safety + .map(|safe| if safe == hir::Safety::Unsafe { "unsafe " } else { "" }) + .unwrap_or(""), mutability = s.mutability.print_with_space(), name = it.name.unwrap(), typ = s.type_.print(cx) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index afafb4fbe4b..d099a97f1cb 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -310,14 +310,16 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)), VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), tcx)), - ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)), + ForeignFunctionItem(f, _) => { + ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)) + } TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), tcx)), TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), tcx)), ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), + ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 0660037e4d8..b335dc5bd16 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -33,8 +33,8 @@ pub(crate) trait DocVisitor: Sized { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | ForeignFunctionItem(_) - | ForeignStaticItem(_) + | ForeignFunctionItem(..) + | ForeignStaticItem(..) | ForeignTypeItem | MacroItem(_) | ProcMacroItem(_) diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 3ed207e416fb2f678a40cc79c02dcf4f936a21c +Subproject bc89bffa5987d4af8f71011c7557119b39e44a6 diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr index 73255651abe..b15857c325a 100644 --- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr +++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr @@ -62,7 +62,7 @@ LL | } LL | match s.len() { LL ~ 10 => 2, LL | 20 => { - ... +... LL | if foo() { LL ~ return 20; LL | } diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr index 0cce718a1ac..f25c0293754 100644 --- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr +++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr @@ -212,7 +212,7 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | - ... +... LL | // Do lint LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr index ce64861fa40..de048091cfb 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.stderr +++ b/src/tools/clippy/tests/ui/needless_late_init.stderr @@ -215,7 +215,7 @@ help: move the declaration `x` here | LL ~ LL | // types that should be considered insignificant - ... +... LL | let y = Box::new(4); LL ~ let x = SignificantDrop; | diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index bf5a89d8b75..b49f199ba5a 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -518,7 +518,7 @@ help: remove `return` | LL ~ 10 LL | }, - ... +... LL | }, LL ~ } | diff --git a/src/tools/miri/src/alloc_bytes.rs b/src/tools/miri/src/alloc_bytes.rs index 87579293001..84225d83b6a 100644 --- a/src/tools/miri/src/alloc_bytes.rs +++ b/src/tools/miri/src/alloc_bytes.rs @@ -112,4 +112,8 @@ impl AllocBytes for MiriAllocBytes { fn as_mut_ptr(&mut self) -> *mut u8 { self.ptr } + + fn as_ptr(&self) -> *const u8 { + self.ptr + } } diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs index 888c548e49b..fa7c0bf5c0c 100644 --- a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, effects)] +#![feature(rustc_attrs)] #[rustc_intrinsic] #[rustc_nounwind] diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index f4c101cf81c..487132683e9 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -387,7 +387,7 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) { }); } -pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) { +pub fn read_dir<F: FnMut(&Path)>(dir: impl AsRef<Path>, mut callback: F) { for entry in fs_wrapper::read_dir(dir) { callback(&entry.unwrap().path()); } diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml index 314ce0e84c6..f0dd0cf73bb 100644 --- a/src/tools/rustfmt/.github/workflows/integration.yml +++ b/src/tools/rustfmt/.github/workflows/integration.yml @@ -19,7 +19,6 @@ jobs: matrix: integration: [ bitflags, - error-chain, log, mdbook, packed_simd, diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md index ec4c682d2c4..89e90fb17dd 100644 --- a/src/tools/rustfmt/CHANGELOG.md +++ b/src/tools/rustfmt/CHANGELOG.md @@ -2,6 +2,99 @@ ## [Unreleased] +### Fixed + +- Fix an idempotency issue when rewriting where clauses in which rustfmt would continuously add a trailing comma `,` to the end of trailing line comments [#5941](https://github.com/rust-lang/rustfmt/issues/5941). +- Prevent enum variant attributes from wrapping one character early when using `version=Two` [#5801](https://github.com/rust-lang/rustfmt/issues/5801) +- Properly wrap macro matchers at the `max_width` when using `version=Two` and `format_macro_matchers=true` [#3805](https://github.com/rust-lang/rustfmt/issues/3805) +- Prevent panic when formatting trait declaration with non [Unicode Normalization Form] C (NFC) identifiers [#6069](https://github.com/rust-lang/rustfmt/issues/6069) + ```rust + // The ó below is two codepoints, ASCII o followed by U+0301 COMBINING ACUTE ACCENT. + // It NFC-normalizes to ó, U+00F3 LATIN SMALL LETTER O WITH ACUTE. + trait Foó: Bar {} + ``` + [unicode normalization form]: https://unicode.org/reports/tr15/ +- Ensure a space is added to a range expression, when the right hand side of the range expression is a binary expression that ends with a trailing period [#6059](https://github.com/rust-lang/rustfmt/issues/6059) + ```rust + let range = 3. / 2. ..4.; + ``` +- When using `version=Two`, comments in match arms that contain `=>` no longer prevent formatting [#5998](https://github.com/rust-lang/rustfmt/issues/5998) + ```rust + match a { + _ => + // comment with => + { + println!("A") + } + } + ``` +- Prevent panics when formatting input that contains the expanded form of `offset_of!` [#5885](https://github.com/rust-lang/rustfmt/issues/5885) [#6105](https://github.com/rust-lang/rustfmt/issues/6105) + ```rust + const _: () = builtin # offset_of(x, x); + ``` +- When using `version=Two` inner attributes in `match` expressions are correctly indented [#6147](https://github.com/rust-lang/rustfmt/issues/6147) + ```rust + pub fn main() { + match x { + #![attr1] + #![attr2] + _ => (), + } + } + ``` +- Output correct syntax for type ascription builtin [#6159](https://github.com/rust-lang/rustfmt/issues/6159) + ```rust + fn main() { + builtin # type_ascribe(10, usize) + } + ``` +- rustfmt no longer removes inner attributes from inline const blocks [#6158](https://github.com/rust-lang/rustfmt/issues/6158) + ```rust + fn main() { + const { + #![allow(clippy::assertions_on_constants)] + + assert!(1 < 2); + } + } + ``` +- rustfmt no longer removes `safe` and `unsafe` keywords from static items in extern blocks. + This helps support [`#![feature(unsafe_extern_blocks)]`](https://github.com/rust-lang/rust/issues/123743) [#6204](https://github.com/rust-lang/rustfmt/pull/6204) + ```rust + #![feature(unsafe_extern_blocks)] + + unsafe extern "C" { + safe static TEST1: i32; + unsafe static TEST2: i32; + } + ``` + + +### Changed + +- `hide_parse_errors` has been soft deprecated and it's been renamed to `show_parse_errors` [#5961](https://github.com/rust-lang/rustfmt/pull/5961). +- The diff output produced by `rustfmt --check` is more compatable with editors that support navigating directly to line numbers [#5971](https://github.com/rust-lang/rustfmt/pull/5971) +- When using `version=Two`, the `trace!` macro from the [log crate] is now formatted similarly to `debug!`, `info!`, `warn!`, and `error!` [#5987](https://github.com/rust-lang/rustfmt/issues/5987). + + [log crate]: https://crates.io/crates/log + + +### Added + +- `generated_marker_line_search_limit` is a new unstable configuration option that allows users to configure how many lines to search for an `@generated` marker when `format_generated_files=false` [#5658](https://github.com/rust-lang/rustfmt/issues/5658) + + +### Misc + +- Updating `dirs 4.0.0 -> 5.0.1` and `cargo_metadata 0.15.4 -> 0.18.0` [#6033] (https://github.com/rust-lang/rustfmt/issues/6033) + - For reference, here's the [dirs v5 changelog](https://github.com/dirs-dev/dirs-rs/blob/main/README.md#5) +- Updated [itertools v0.11 -> v0.12](https://github.com/rust-itertools/itertools/blob/v0.12.1/CHANGELOG.md#0120) [#6093](https://github.com/rust-lang/rustfmt/pull/6093) +- Addressed clap deprecations output when running `cargo check --features clap/deprecated` [#6101](https://github.com/rust-lang/rustfmt/pull/6101) +- Bumped bytecount `0.6.4` -> `0.6.8` to fix compilation issues with the `generic-simd` feature. See [bytecount#92] and [bytecount#93] + + [bytecount#92]: https://github.com/llogiq/bytecount/pull/92 + [bytecount#93]: https://github.com/llogiq/bytecount/pull/93 +- Replace the `lazy_static` dependency with `std::sync::OnceLock` [#6154](https://github.com/rust-lang/rustfmt/pull/6154) ## [1.7.0] 2023-10-22 @@ -27,7 +120,7 @@ } ``` - Prevent ICE when formatting `vec!{}` [#5735](https://github.com/rust-lang/rustfmt/issues/5735) -- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` defintion e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882) +- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` definition e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882) - Formatting doc comment lines that start with `.` or `)` won't be treated as ordered markdown lists because `.` or `)` must be preceded by a number to start an ordered markdown list [#5835](https://github.com/rust-lang/rustfmt/pull/5835) - Add parenthesis around closures when they're used as method receives, don't have a block body, and end with `.` [#4808](https://github.com/rust-lang/rustfmt/issues/4808) ```rust @@ -184,7 +277,7 @@ - Simplify the rustfmt help text by eliding the full path to the rustfmt binary path from the usage string when running `rustfmt --help` [#5214](https://github.com/rust-lang/rustfmt/issues/5214) -- Bumped the version for serveral dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237) +- Bumped the version for several dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237) ### Fixed @@ -942,7 +1035,7 @@ from formatting an attribute #3665 ### Fixed -- Do not remove path disambiugator inside macro #3142 +- Do not remove path disambiguator inside macro #3142 - Improve handling of Windows newlines #3141 - Fix alignment of a struct's fields (`struct_field_align_threshold` option) with the Visual `indent_style` #3165 - Fix a bug in formatting markdown lists within comments #3172 @@ -1031,7 +1124,7 @@ from formatting an attribute #3665 ### Changed -- Replace '--conifig-help' with '--config=help' cb10e06 +- Replace '--config-help' with '--config=help' cb10e06 - Improve formatting of slice patterns #2912 ### Fixed @@ -1075,7 +1168,7 @@ from formatting an attribute #3665 - Add max_width option for all heuristics c2ae39e - Add config option `format_macro_matchers` to format the metavariable matching patterns in macros 79c5ee8 - Add config option `format_macro_bodies` to format the bodies of macros 79c5ee8 -- Format exitential type fc307ff +- Format existential type fc307ff - Support raw identifiers in struct expressions f121b1a - Format Async block and async function 0b25f60 @@ -1131,7 +1224,7 @@ from formatting an attribute #3665 ### Changed -- Update rustc-ap-syntax to 128.0.0 and ustc-ap-rustc_target to 128.0.0 195395f +- Update rustc-ap-syntax to 128.0.0 and rustc-ap-rustc_target to 128.0.0 195395f - Put operands on its own line when each fits in a single line f8439ce - Improve CLI options 55ac062 1869888 798bffb 4d9de48 eca7796 8396da1 5d9f5aa @@ -1195,7 +1288,7 @@ from formatting an attribute #3665 - Do not collapse block around expr with condition on match arm 5b9b7d5 - Use vertical layout for complex attributes c77708f - Format array using heuristics for function calls 98c6f7b -- Implement stable ordering for impl items with the the following item priority: type, const, macro, then method fa80ddf +- Implement stable ordering for impl items with the following item priority: type, const, macro, then method fa80ddf - Reorder imports by default 164cf7d - Group `extern crate` by default 3a138a2 - Make `error_on_line_overflow` false by default f146711 diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock index 8fcefa97489..2a1fffa50fe 100644 --- a/src/tools/rustfmt/Cargo.lock +++ b/src/tools/rustfmt/Cargo.lock @@ -98,12 +98,9 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.4" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" -dependencies = [ - "packed_simd", -] +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "camino" @@ -125,9 +122,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" dependencies = [ "camino", "cargo-platform", @@ -217,9 +214,9 @@ checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] @@ -236,13 +233,14 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] @@ -343,9 +341,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -369,12 +367,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] name = "log" version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -409,36 +401,22 @@ dependencies = [ ] [[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] name = "once_cell" version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "overload" -version = "0.1.1" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "packed_simd" -version = "0.3.9" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d" -dependencies = [ - "cfg-if", - "num-traits", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pin-project-lite" @@ -521,7 +499,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.7.0" +version = "1.7.1" dependencies = [ "annotate-snippets", "anyhow", @@ -534,7 +512,6 @@ dependencies = [ "getopts", "ignore", "itertools", - "lazy_static", "regex", "rustfmt-config_proc_macro", "serde", diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index 032b9b54810..a16620ed99b 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.7.0" +version = "1.7.1" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" @@ -35,16 +35,15 @@ generic-simd = ["bytecount/generic-simd"] [dependencies] annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1.0" -bytecount = "0.6.4" -cargo_metadata = "0.15.4" +bytecount = "0.6.8" +cargo_metadata = "0.18" clap = { version = "4.4.2", features = ["derive"] } clap-cargo = "0.12.0" diff = "0.1" -dirs = "4.0" +dirs = "5.0" getopts = "0.2" ignore = "0.4" -itertools = "0.11" -lazy_static = "1.4" +itertools = "0.12" regex = "1.7" serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0" diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md index ac5747800b2..f52c2573154 100644 --- a/src/tools/rustfmt/Configurations.md +++ b/src/tools/rustfmt/Configurations.md @@ -1,6 +1,6 @@ # Configuring Rustfmt -Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well. +Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/5.0.1/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well. A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: @@ -1050,8 +1050,8 @@ Max width for code snippets included in doc comments. Only used if [`format_code ## `format_generated_files` -Format generated files. A file is considered generated -if any of the first five lines contain a `@generated` comment marker. +Format generated files. A file is considered generated if any of the first several lines contain a `@generated` comment marker. The number of lines to check is configured by `generated_marker_line_search_limit`. + By default, generated files are reformatted, i. e. `@generated` marker is ignored. This option is currently ignored for stdin (`@generated` in stdin is ignored.) @@ -1059,6 +1059,16 @@ This option is currently ignored for stdin (`@generated` in stdin is ignored.) - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080)) +## `generated_marker_line_search_limit` + +Number of lines to check for a `@generated` pragma header, starting from the top of the file. Setting this value to `0` will treat all files as non-generated. When`format_generated_files` is `true`, this option has no effect. + +- **Default value**: `5` +- **Possible values**: any positive integer +- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080)) + +See also [format_generated_files](#format_generated_files) link here. + ## `format_macro_matchers` Format the metavariable matching patterns in macros. @@ -1098,7 +1108,7 @@ See also [`format_macro_bodies`](#format_macro_bodies). ## `format_macro_bodies` -Format the bodies of macros. +Format the bodies of declarative macro definitions. - **Default value**: `true` - **Possible values**: `true`, `false` @@ -1248,12 +1258,20 @@ Control the case of the letters in hexadecimal literal values ## `hide_parse_errors` -Do not show parse errors if the parser failed to parse files. +This option is deprecated and has been renamed to `show_parse_errors` to avoid confusion around the double negative default of `hide_parse_errors=false`. - **Default value**: `false` - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390)) +## `show_parse_errors` + +Show parse errors if the parser failed to parse files. + +- **Default value**: `true` +- **Possible values**: `true`, `false` +- **Stable**: No (tracking issue: [#5977](https://github.com/rust-lang/rustfmt/issues/5977)) + ## `ignore` Skip formatting files and directories that match the specified pattern. @@ -1288,6 +1306,15 @@ If you want to ignore every file under the directory where you put your rustfmt. ignore = ["/"] ``` +If you want to allow specific paths that would otherwise be ignored, prefix those paths with a `!`: + +```toml +ignore = ["bar_dir/*", "!bar_dir/*/what.rs"] +``` + +In this case, all files under `bar_dir` will be ignored, except files like `bar_dir/sub/what.rs` +or `bar_dir/another/what.rs`. + ## `imports_indent` Indent style of imports @@ -1655,7 +1682,7 @@ use core::slice; Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator. -The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body does not contain multiple statements nor line comments. +The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body contains neither multiple statements nor line comments. - **Default value**: `true` - **Possible values**: `true`, `false` diff --git a/src/tools/rustfmt/Contributing.md b/src/tools/rustfmt/Contributing.md index 69a2c76369f..2f2ccfb175a 100644 --- a/src/tools/rustfmt/Contributing.md +++ b/src/tools/rustfmt/Contributing.md @@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file ## Debugging Some `rewrite_*` methods use the `debug!` macro for printing useful information. -These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`. +These messages can be printed by using the environment variable `RUSTFMT_LOG=debug`. These traces can be helpful in understanding which part of the code was used and get a better grasp on the execution flow. diff --git a/src/tools/rustfmt/Processes.md b/src/tools/rustfmt/Processes.md index 61abc87eec9..64ef20a9bd7 100644 --- a/src/tools/rustfmt/Processes.md +++ b/src/tools/rustfmt/Processes.md @@ -16,7 +16,7 @@ In this Section, we describe how to stabilise an option of the rustfmt's configu Open a pull request that closes the tracking issue. The tracking issue is listed beside the option in `Configurations.md`. - Update the `Config` enum marking the option as stable. -- Update the the `Configuration.md` file marking the option as stable. +- Update the `Configuration.md` file marking the option as stable. - Update `CHANGELOG.md` marking the option as stable. ## After the stabilisation diff --git a/src/tools/rustfmt/build.rs b/src/tools/rustfmt/build.rs index e7b1e1b854c..9a8bb77a8ed 100644 --- a/src/tools/rustfmt/build.rs +++ b/src/tools/rustfmt/build.rs @@ -40,7 +40,7 @@ fn channel() -> String { fn commit_hash() -> Option<String> { Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) + .args(["rev-parse", "--short", "HEAD"]) .output() .ok() .and_then(|r| String::from_utf8(r.stdout).ok()) @@ -48,7 +48,7 @@ fn commit_hash() -> Option<String> { fn commit_date() -> Option<String> { Command::new("git") - .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) + .args(["log", "-1", "--date=short", "--pretty=format:%cd"]) .output() .ok() .and_then(|r| String::from_utf8(r.stdout).ok()) diff --git a/src/tools/rustfmt/check_diff/.gitignore b/src/tools/rustfmt/check_diff/.gitignore new file mode 100644 index 00000000000..ea8c4bf7f35 --- /dev/null +++ b/src/tools/rustfmt/check_diff/.gitignore @@ -0,0 +1 @@ +/target diff --git a/src/tools/rustfmt/check_diff/Cargo.lock b/src/tools/rustfmt/check_diff/Cargo.lock new file mode 100644 index 00000000000..6716ccdf9a0 --- /dev/null +++ b/src/tools/rustfmt/check_diff/Cargo.lock @@ -0,0 +1,237 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "check_diff" +version = "0.1.0" +dependencies = [ + "clap", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/src/tools/rustfmt/check_diff/Cargo.toml b/src/tools/rustfmt/check_diff/Cargo.toml new file mode 100644 index 00000000000..a1ed154481a --- /dev/null +++ b/src/tools/rustfmt/check_diff/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "check_diff" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.4.2", features = ["derive"] } diff --git a/src/tools/rustfmt/check_diff/src/main.rs b/src/tools/rustfmt/check_diff/src/main.rs new file mode 100644 index 00000000000..6d07c1b0df6 --- /dev/null +++ b/src/tools/rustfmt/check_diff/src/main.rs @@ -0,0 +1,25 @@ +use clap::Parser; +/// Inputs for the check_diff script +#[derive(Parser)] +struct CliInputs { + /// Git url of a rustfmt fork to compare against the latest master rustfmt + remote_repo_url: String, + /// Name of the feature branch on the forked repo + feature_branch: String, + /// Optional commit hash from the feature branch + #[arg(short, long)] + commit_hash: Option<String>, + /// Optional comma separated list of rustfmt config options to + /// pass when running the feature branch + #[arg(value_delimiter = ',', short, long, num_args = 1..)] + rustfmt_config: Option<Vec<String>>, +} + +fn main() { + let args = CliInputs::parse(); + println!( + "remote_repo_url: {:?}, feature_branch: {:?}, + optional_commit_hash: {:?}, optional_rustfmt_config: {:?}", + args.remote_repo_url, args.feature_branch, args.commit_hash, args.rustfmt_config + ); +} diff --git a/src/tools/rustfmt/ci/check_diff.sh b/src/tools/rustfmt/ci/check_diff.sh index 50c58b1f492..2a29cb138ef 100755 --- a/src/tools/rustfmt/ci/check_diff.sh +++ b/src/tools/rustfmt/ci/check_diff.sh @@ -2,9 +2,6 @@ set -e -# https://github.com/rust-lang/rustfmt/issues/5675 -export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH - function print_usage() { echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]" } @@ -31,7 +28,7 @@ function clone_repo() { GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2 } -# Initialize Git submoduels for the repo. +# Initialize Git submodules for the repo. # # Parameters # $1: list of directories to initialize @@ -46,7 +43,7 @@ function init_submodules() { # $2: Output file path for the diff # $3: Any additional configuration options to pass to rustfmt # -# Globlas: +# Globals: # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 function create_diff() { local config; @@ -67,7 +64,7 @@ function create_diff() { # Parameters # $1: Name of the repository (used for logging) # -# Globlas: +# Globals: # $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt` # $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt` # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 @@ -90,7 +87,7 @@ function check_diff() { ) if [ -z "$diff" ]; then - echo "no diff detected between rustfmt and the feture branch" + echo "no diff detected between rustfmt and the feature branch" return 0 else echo "$diff" @@ -104,7 +101,7 @@ function check_diff() { # Parameters: # $1: Directory where rustfmt will be cloned # -# Globlas: +# Globals: # $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test # $FEATURE_BRANCH: Name of the feature branch # $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided @@ -114,15 +111,42 @@ function compile_rustfmt() { git remote add feature $REMOTE_REPO git fetch feature $FEATURE_BRANCH - cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt + CARGO_VERSION=$(cargo --version) + echo -e "\ncompiling with $CARGO_VERSION\n" + + # Because we're building standalone binaries we need to set `LD_LIBRARY_PATH` so each + # binary can find it's runtime dependencies. See https://github.com/rust-lang/rustfmt/issues/5675 + # This will prepend the `LD_LIBRARY_PATH` for the master rustfmt binary + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH + + echo "Building rustfmt from src" + cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt + if [ -z "$OPTIONAL_COMMIT_HASH" ] || [ "$FEATURE_BRANCH" = "$OPTIONAL_COMMIT_HASH" ]; then git switch $FEATURE_BRANCH else git switch $OPTIONAL_COMMIT_HASH --detach fi - cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt + + # This will prepend the `LD_LIBRARY_PATH` for the feature branch rustfmt binary. + # In most cases the `LD_LIBRARY_PATH` should be the same for both rustfmt binaries that we build + # in `compile_rustfmt`, however, there are scenarios where each binary has different runtime + # dependencies. For example, during subtree syncs we bump the nightly toolchain required to build + # rustfmt, and therefore the feature branch relies on a newer set of runtime dependencies. + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH + + echo "Building feature rustfmt from src" + cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt + + echo -e "\nRuntime dependencies for rustfmt -- LD_LIBRARY_PATH: $LD_LIBRARY_PATH" + RUSFMT_BIN=$1/rustfmt + RUSTFMT_VERSION=$($RUSFMT_BIN --version) + echo -e "\nRUSFMT_BIN $RUSTFMT_VERSION\n" + FEATURE_BIN=$1/feature_rustfmt + FEATURE_VERSION=$($FEATURE_BIN --version) + echo -e "FEATURE_BIN $FEATURE_VERSION\n" } # Check the diff for running rustfmt and the feature branch on all the .rs files in the repo. @@ -155,7 +179,7 @@ function check_repo() { STATUSES+=($?) set -e - echo "removing tmp_dir $tmp_dir" + echo -e "removing tmp_dir $tmp_dir\n\n" rm -rf $tmp_dir cd $WORKDIR } diff --git a/src/tools/rustfmt/ci/integration.sh b/src/tools/rustfmt/ci/integration.sh index 19d502bc5c7..ea96e4be130 100755 --- a/src/tools/rustfmt/ci/integration.sh +++ b/src/tools/rustfmt/ci/integration.sh @@ -104,7 +104,7 @@ case ${INTEGRATION} in check_fmt_with_all_tests cd - ;; - error-chain | tempdir) + tempdir) git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git cd ${INTEGRATION} show_head diff --git a/src/tools/rustfmt/config_proc_macro/src/attrs.rs b/src/tools/rustfmt/config_proc_macro/src/attrs.rs index d8de9aae088..e7534b813d7 100644 --- a/src/tools/rustfmt/config_proc_macro/src/attrs.rs +++ b/src/tools/rustfmt/config_proc_macro/src/attrs.rs @@ -68,7 +68,11 @@ fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> { match &attr.meta { syn::Meta::NameValue(syn::MetaNameValue { path, - value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }), + value: + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit_str), + .. + }), .. }) if path.is_ident(name) => Some(lit_str.value()), _ => None, diff --git a/src/tools/rustfmt/docs/index.html b/src/tools/rustfmt/docs/index.html index ee0339bc50d..5e588d1db54 100644 --- a/src/tools/rustfmt/docs/index.html +++ b/src/tools/rustfmt/docs/index.html @@ -3,13 +3,33 @@ <head> <meta name="viewport" content="width=device-width"> <title>Rustfmt</title> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" /> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css"> - <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> - <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> + <link rel="stylesheet" + href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css" + integrity="sha512-7e0rszTy0dKTIgYzCeBXpmycq0EOkwAvxZ0dv/LAtQfcXWCoaRhzs+v2Mn6of3jImxPazbYxiK0kpE/7wZ/UQA==" + crossorigin="anonymous" + referrerpolicy="no-referrer" /> + <link rel="stylesheet" + href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css" + integrity="sha512-od7JLoOTxM8w/HSKGzP9Kexc20K9p/M2zxSWsd7H1e4Ctf+8SQFtCWEZnW5u6ul5ehSECa5QmOk9ju2nQMmlVA==" + crossorigin="anonymous" + referrerpolicy="no-referrer" /> + <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.2/marked.min.js" + integrity="sha512-xeUh+KxNyTufZOje++oQHstlMQ8/rpyzPuM+gjMFYK3z5ILJGE7l2NvYL+XfliKURMpBIKKp1XoPN/qswlSMFA==" + crossorigin="anonymous" + referrerpolicy="no-referrer"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js" + integrity="sha512-PwQ5+jgXxxprNGc80ycHE3spgj6TuDieHe/yTkbEJ+U5aol7dTupi/4VbwHHzlQVW77Vb0GLOIsiYigHgC5vcg==" + crossorigin="anonymous" + referrerpolicy="no-referrer"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js" + integrity="sha512-av6ZR84Ldk6j29DMhf6v0cssEhow1VROFLoKbX7wrvzZB++/nV8m0jXbYeWcHPEzSNONImx6zwBskCUT9AQidA==" + crossorigin="anonymous" + referrerpolicy="no-referrer"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js" + integrity="sha512-3BBFWr73Xrf8GRjO+0pl0cbVwESBvg3ovnuCXpoqOkC/mkt/hTkFtutUPrwRz8eLySYvy5v1daulkyUZYvH8jw==" + crossorigin="anonymous" + referrerpolicy="no-referrer"></script> <script src="https://unpkg.com/vue-async-computed@3.8.1"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script> <style> @media (max-width: 767px) { .markdown-body { diff --git a/src/tools/rustfmt/intellij.md b/src/tools/rustfmt/intellij.md index 6a711c0171a..70170df388f 100644 --- a/src/tools/rustfmt/intellij.md +++ b/src/tools/rustfmt/intellij.md @@ -20,7 +20,7 @@ - Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"  -- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually +- IntelliJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually ### Bind shortcut to "Reformat File with Rustfmt" action diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain index 0057e2f370a..25e3961d32a 100644 --- a/src/tools/rustfmt/rust-toolchain +++ b/src/tools/rustfmt/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-22" +channel = "nightly-2024-06-13" components = ["llvm-tools", "rustc-dev"] diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 83f59837d44..433b9256202 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -353,10 +353,18 @@ impl Rewrite for ast::Attribute { // 1 = `[` let shape = shape.offset_left(prefix.len() + 1)?; - Some( - meta.rewrite(context, shape) - .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), - ) + Some(meta.rewrite(context, shape).map_or_else( + || snippet.to_owned(), + |rw| match &self.kind { + ast::AttrKind::Normal(normal_attr) => match normal_attr.item.unsafety { + // For #![feature(unsafe_attributes)] + // See https://github.com/rust-lang/rust/issues/123757 + ast::Safety::Unsafe(_) => format!("{}[unsafe({})]", prefix, rw), + _ => format!("{}[{}]", prefix, rw), + }, + _ => format!("{}[{}]", prefix, rw), + }, + )) } else { Some(snippet.to_owned()) } diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 6f564083656..88281d296be 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -387,16 +387,11 @@ fn format_and_emit_report<T: Write>(session: &mut Session<'_, T>, input: Input) } fn should_print_with_colors<T: Write>(session: &mut Session<'_, T>) -> bool { - match term::stderr() { - Some(ref t) - if session.config.color().use_colored_tty() - && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - true - } - _ => false, - } + term::stderr().is_some_and(|t| { + session.config.color().use_colored_tty() + && t.supports_color() + && t.supports_attr(term::Attr::Bold) + }) } fn print_usage_to_stdout(opts: &Options, reason: &str) { @@ -445,7 +440,7 @@ fn print_version() { fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> { if matches.opt_present("h") { let topic = matches.opt_str("h"); - if topic == None { + if topic.is_none() { return Ok(Operation::Help(HelpOp::None)); } else if topic == Some("config".to_owned()) { return Ok(Operation::Help(HelpOp::Config)); diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs index a1ad1aafac4..eedb43defb9 100644 --- a/src/tools/rustfmt/src/cargo-fmt/main.rs +++ b/src/tools/rustfmt/src/cargo-fmt/main.rs @@ -61,7 +61,7 @@ pub struct Opts { /// Options passed to rustfmt // 'raw = true' to make `--` explicit. - #[arg(name = "rustfmt_options", raw = true)] + #[arg(id = "rustfmt_options", raw = true)] rustfmt_options: Vec<String>, /// Format all packages, and also their local path-based dependencies @@ -209,9 +209,8 @@ fn convert_message_format_to_rustfmt_args( fn print_usage_to_stderr(reason: &str) { eprintln!("{reason}"); let app = Opts::command(); - app.after_help("") - .write_help(&mut io::stderr()) - .expect("failed to write to stderr"); + let help = app.after_help("").render_help(); + eprintln!("{help}"); } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -507,7 +506,7 @@ fn run_rustfmt( let mut command = rustfmt_command() .stdout(stdout) .args(files) - .args(&["--edition", edition.as_str()]) + .args(["--edition", edition.as_str()]) .args(fmt_args) .spawn() .map_err(|e| match e.kind() { diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs index 696326e4f94..255e0d679d4 100644 --- a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs +++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs @@ -20,7 +20,7 @@ fn default_options() { #[test] fn good_options() { - let o = Opts::parse_from(&[ + let o = Opts::parse_from([ "test", "-q", "-p", @@ -48,7 +48,7 @@ fn good_options() { fn unexpected_option() { assert!( Opts::command() - .try_get_matches_from(&["test", "unexpected"]) + .try_get_matches_from(["test", "unexpected"]) .is_err() ); } @@ -57,7 +57,7 @@ fn unexpected_option() { fn unexpected_flag() { assert!( Opts::command() - .try_get_matches_from(&["test", "--flag"]) + .try_get_matches_from(["test", "--flag"]) .is_err() ); } @@ -66,19 +66,19 @@ fn unexpected_flag() { fn mandatory_separator() { assert!( Opts::command() - .try_get_matches_from(&["test", "--emit"]) + .try_get_matches_from(["test", "--emit"]) .is_err() ); assert!( Opts::command() - .try_get_matches_from(&["test", "--", "--emit"]) + .try_get_matches_from(["test", "--", "--emit"]) .is_ok() ); } #[test] fn multiple_packages_one_by_one() { - let o = Opts::parse_from(&[ + let o = Opts::parse_from([ "test", "-p", "package1", @@ -92,7 +92,7 @@ fn multiple_packages_one_by_one() { #[test] fn multiple_packages_grouped() { - let o = Opts::parse_from(&[ + let o = Opts::parse_from([ "test", "--package", "package1", @@ -108,7 +108,7 @@ fn multiple_packages_grouped() { fn empty_packages_1() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p"]) + .try_get_matches_from(["test", "-p"]) .is_err() ); } @@ -117,7 +117,7 @@ fn empty_packages_1() { fn empty_packages_2() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p", "--", "--check"]) + .try_get_matches_from(["test", "-p", "--", "--check"]) .is_err() ); } @@ -126,7 +126,7 @@ fn empty_packages_2() { fn empty_packages_3() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p", "--verbose"]) + .try_get_matches_from(["test", "-p", "--verbose"]) .is_err() ); } @@ -135,7 +135,7 @@ fn empty_packages_3() { fn empty_packages_4() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p", "--check"]) + .try_get_matches_from(["test", "-p", "--check"]) .is_err() ); } diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index 7d1b0384431..24a5a1be2c3 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -3,8 +3,6 @@ use std::{borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; -use lazy_static::lazy_static; -use regex::Regex; use rustc_span::Span; use crate::config::Config; @@ -17,17 +15,6 @@ use crate::utils::{ }; use crate::{ErrorKind, FormattingError}; -lazy_static! { - /// A regex matching reference doc links. - /// - /// ```markdown - /// /// An [example]. - /// /// - /// /// [example]: this::is::a::link - /// ``` - static ref REFERENCE_LINK_URL: Regex = Regex::new(r"^\[.+\]\s?:").unwrap(); -} - fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { false @@ -173,10 +160,7 @@ pub(crate) fn combine_strs_with_missing_comments( ) -> Option<String> { trace!( "combine_strs_with_missing_comments `{}` `{}` {:?} {:?}", - prev_str, - next_str, - span, - shape + prev_str, next_str, span, shape ); let mut result = @@ -208,7 +192,7 @@ pub(crate) fn combine_strs_with_missing_comments( // We have a missing comment between the first expression and the second expression. - // Peek the the original source code and find out whether there is a newline between the first + // Peek the original source code and find out whether there is a newline between the first // expression and the second expression or the missing comment. We will preserve the original // layout whenever possible. let original_snippet = context.snippet(span); @@ -506,7 +490,7 @@ impl ItemizedBlock { let mut line_start = " ".repeat(indent); // Markdown blockquote start with a "> " - if line.trim_start().starts_with(">") { + if line.trim_start().starts_with('>') { // remove the original +2 indent because there might be multiple nested block quotes // and it's easier to reason about the final indent by just taking the length // of the new line_start. We update the indent because it effects the max width @@ -657,7 +641,7 @@ impl<'a> CommentRewrite<'a> { while let Some(line) = iter.next() { result.push_str(line); result.push_str(match iter.peek() { - Some(next_line) if next_line.is_empty() => sep.trim_end(), + Some(&"") => sep.trim_end(), Some(..) => sep, None => "", }); @@ -666,7 +650,7 @@ impl<'a> CommentRewrite<'a> { } /// Check if any characters were written to the result buffer after the start of the comment. - /// when calling [`CommentRewrite::new()`] the result buffer is initiazlied with the opening + /// when calling [`CommentRewrite::new()`] the result buffer is initialized with the opening /// characters for the comment. fn buffer_contains_comment(&self) -> bool { // if self.result.len() < self.opener.len() then an empty comment is in the buffer @@ -839,7 +823,7 @@ impl<'a> CommentRewrite<'a> { } } - let is_markdown_header_doc_comment = is_doc_comment && line.starts_with("#"); + let is_markdown_header_doc_comment = is_doc_comment && line.starts_with('#'); // We only want to wrap the comment if: // 1) wrap_comments = true is configured @@ -979,12 +963,21 @@ fn trim_custom_comment_prefix(s: &str) -> String { /// Returns `true` if the given string MAY include URLs or alike. fn has_url(s: &str) -> bool { + // A regex matching reference doc links. + // + // ```markdown + // /// An [example]. + // /// + // /// [example]: this::is::a::link + // ``` + let reference_link_url = static_regex!(r"^\[.+\]\s?:"); + // This function may return false positive, but should get its job done in most cases. s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") - || REFERENCE_LINK_URL.is_match(s) + || reference_link_url.is_match(s) } /// Returns true if the given string may be part of a Markdown table. @@ -1263,15 +1256,15 @@ pub(crate) enum FullCodeCharKind { InComment, /// Last character of a comment, '\n' for a line comment, '/' for a block comment. EndComment, - /// Start of a mutlitine string inside a comment + /// Start of a multiline string inside a comment StartStringCommented, - /// End of a mutlitine string inside a comment + /// End of a multiline string inside a comment EndStringCommented, /// Inside a commented string InStringCommented, - /// Start of a mutlitine string + /// Start of a multiline string StartString, - /// End of a mutlitine string + /// End of a multiline string EndString, /// Inside a string. InString, @@ -1764,7 +1757,7 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { let code_comment_content = |code| { let slices = UngroupedCommentCodeSlices::new(code); slices - .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) + .filter(|(kind, _, _)| *kind == CodeCharKind::Comment) .flat_map(|(_, _, s)| CommentReducer::new(s)) }; let res = code_comment_content(orig).ne(code_comment_content(new)); diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs index feb452d7235..f7cff1a1729 100644 --- a/src/tools/rustfmt/src/config/config_type.rs +++ b/src/tools/rustfmt/src/config/config_type.rs @@ -66,7 +66,7 @@ impl ConfigType for IgnoreList { } macro_rules! create_config { - // Options passed in to the macro. + // Options passed into the macro. // // - $i: the ident name of the option // - $ty: the type of the option value @@ -129,6 +129,7 @@ macro_rules! create_config { | "chain_width" => self.0.set_heuristics(), "merge_imports" => self.0.set_merge_imports(), "fn_args_layout" => self.0.set_fn_args_layout(), + "hide_parse_errors" => self.0.set_hide_parse_errors(), &_ => (), } } @@ -184,6 +185,7 @@ macro_rules! create_config { self.set_ignore(dir); self.set_merge_imports(); self.set_fn_args_layout(); + self.set_hide_parse_errors(); self } @@ -278,19 +280,21 @@ macro_rules! create_config { | "chain_width" => self.set_heuristics(), "merge_imports" => self.set_merge_imports(), "fn_args_layout" => self.set_fn_args_layout(), + "hide_parse_errors" => self.set_hide_parse_errors(), &_ => (), } } #[allow(unreachable_pub)] pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 6] = [ + const HIDE_OPTIONS: [&str; 7] = [ "verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports", - "fn_args_layout" + "fn_args_layout", + "hide_parse_errors" ]; HIDE_OPTIONS.contains(&name) } @@ -461,6 +465,18 @@ macro_rules! create_config { } } + fn set_hide_parse_errors(&mut self) { + if self.was_set().hide_parse_errors() { + eprintln!( + "Warning: the `hide_parse_errors` option is deprecated. \ + Use `show_parse_errors` instead" + ); + if !self.was_set().show_parse_errors() { + self.show_parse_errors.2 = self.hide_parse_errors(); + } + } + } + #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 9d454137b2c..9484b2e5829 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -26,6 +26,7 @@ pub(crate) mod file_lines; #[allow(unreachable_pub)] pub(crate) mod lists; pub(crate) mod macro_names; +pub(crate) mod style_edition; // This macro defines configuration options used in rustfmt. Each option // is defined as follows: @@ -73,7 +74,7 @@ create_config! { format_strings: bool, false, false, "Format string literals where necessary"; format_macro_matchers: bool, false, false, "Format the metavariable matching patterns in macros"; - format_macro_bodies: bool, true, false, "Format the bodies of macros"; + format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions"; skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false, "Skip formatting the bodies of macros invoked with the following names."; hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false, @@ -150,6 +151,8 @@ create_config! { "Write an item and its attribute on the same line \ if their combined width is below a threshold"; format_generated_files: bool, true, false, "Format generated files"; + generated_marker_line_search_limit: usize, 5, false, "Number of lines to check for a \ + `@generated` marker when `format_generated_files` is enabled"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; @@ -168,7 +171,8 @@ create_config! { "Enables unstable features. Only available on nightly channel"; disable_all_formatting: bool, false, true, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; - hide_parse_errors: bool, false, false, "Hide errors from the parser"; + hide_parse_errors: bool, false, false, "(deprecated: use show_parse_errors instead)"; + show_parse_errors: bool, true, false, "Show errors from the parser (unstable)"; error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; error_on_unformatted: bool, false, false, "Error if unable to get comments or string literals within max_width, \ @@ -203,6 +207,7 @@ impl PartialConfig { cloned.print_misformatted_file_names = None; cloned.merge_imports = None; cloned.fn_args_layout = None; + cloned.hide_parse_errors = None; ::toml::to_string(&cloned).map_err(ToTomlError) } @@ -282,7 +287,7 @@ impl Config { } } - // If none was found ther either, check in the user's configuration directory. + // If none was found there either, check in the user's configuration directory. if let Some(mut config_dir) = dirs::config_dir() { config_dir.push("rustfmt"); if let Some(path) = get_toml_path(&config_dir)? { @@ -455,6 +460,13 @@ mod test { fn_params_layout: Density, Density::Tall, true, "Control the layout of parameters in a function signatures."; + // hide_parse_errors renamed to show_parse_errors + hide_parse_errors: bool, false, false, + "(deprecated: use show_parse_errors instead)"; + show_parse_errors: bool, true, false, + "Show errors from the parser (unstable)"; + + // Width Heuristics use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different formatting for items and \ @@ -670,6 +682,7 @@ edition = "2015" version = "One" inline_attribute_width = 0 format_generated_files = true +generated_marker_line_search_limit = 5 merge_derives = true use_try_shorthand = false use_field_init_shorthand = false @@ -680,7 +693,7 @@ required_version = "{}" unstable_features = false disable_all_formatting = false skip_children = false -hide_parse_errors = false +show_parse_errors = true error_on_line_overflow = false error_on_unformatted = false ignore = [] diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index 03fd91eb10f..3c5c713a33a 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -191,7 +191,7 @@ pub enum Color { pub enum Version { /// 1.x.y. When specified, rustfmt will format in the same style as 1.0.0. One, - /// 2.x.y. When specified, rustfmt will format in the the latest style. + /// 2.x.y. When specified, rustfmt will format in the latest style. Two, } @@ -416,7 +416,7 @@ pub trait CliOptions { fn config_path(&self) -> Option<&Path>; } -/// The edition of the syntax and semntics of code (RFC 2052). +/// The edition of the syntax and semantics of code (RFC 2052). #[config_type] pub enum Edition { #[value = "2015"] @@ -470,3 +470,27 @@ pub enum MatchArmLeadingPipe { /// Preserve any existing leading pipes Preserve, } + +/// Defines the default values for each config according to [the style guide]. +/// rustfmt output may differ between style editions. +/// +/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/ +#[config_type] +pub enum StyleEdition { + #[value = "2015"] + #[doc_hint = "2015"] + /// [Edition 2015]() + Edition2015, + #[value = "2018"] + #[doc_hint = "2018"] + /// [Edition 2018]() + Edition2018, + #[value = "2021"] + #[doc_hint = "2021"] + /// [Edition 2021]() + Edition2021, + #[value = "2024"] + #[doc_hint = "2024"] + /// [Edition 2024](). + Edition2024, +} diff --git a/src/tools/rustfmt/src/config/style_edition.rs b/src/tools/rustfmt/src/config/style_edition.rs new file mode 100644 index 00000000000..7b3ea3bc119 --- /dev/null +++ b/src/tools/rustfmt/src/config/style_edition.rs @@ -0,0 +1,70 @@ +use crate::config::StyleEdition; + +/// Defines the default value for the given style edition +#[allow(dead_code)] +pub(crate) trait StyleEditionDefault { + type ConfigType; + fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType; +} + +/// macro to help implement `StyleEditionDefault` for config options +#[macro_export] +macro_rules! style_edition_default { + ($ty:ident, $config_ty:ty, _ => $default:expr) => { + impl $crate::config::style_edition::StyleEditionDefault for $ty { + type ConfigType = $config_ty; + + fn style_edition_default(_: $crate::config::StyleEdition) -> Self::ConfigType { + $default + } + } + }; + ($ty:ident, $config_ty:ty, Edition2024 => $default_2024:expr, _ => $default_2015:expr) => { + impl $crate::config::style_edition::StyleEditionDefault for $ty { + type ConfigType = $config_ty; + + fn style_edition_default( + style_edition: $crate::config::StyleEdition, + ) -> Self::ConfigType { + match style_edition { + $crate::config::StyleEdition::Edition2015 + | $crate::config::StyleEdition::Edition2018 + | $crate::config::StyleEdition::Edition2021 => $default_2015, + $crate::config::StyleEdition::Edition2024 => $default_2024, + } + } + } + }; +} + +#[cfg(test)] +mod test { + use super::*; + use crate::config::StyleEdition; + + #[test] + fn test_impl_default_style_edition_struct_for_all_editions() { + struct Unit; + style_edition_default!(Unit, usize, _ => 100); + + // regardless of the style edition used the value will always return 100 + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 100); + } + + #[test] + fn test_impl_default_style_edition_for_old_and_new_editions() { + struct Unit; + style_edition_default!(Unit, usize, Edition2024 => 50, _ => 100); + + // style edition 2015-2021 are all the same + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100); + + // style edition 2024 + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 50); + } +} diff --git a/src/tools/rustfmt/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs index 2a4a9dfce8e..9385ae59a06 100644 --- a/src/tools/rustfmt/src/emitter/checkstyle.rs +++ b/src/tools/rustfmt/src/emitter/checkstyle.rs @@ -89,11 +89,11 @@ mod tests { #[test] fn emits_single_xml_tree_containing_all_files() { let bin_file = "src/bin.rs"; - let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"]; - let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"]; + let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"]; + let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"]; let lib_file = "src/lib.rs"; - let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"]; - let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"]; + let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"]; + let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"]; let mut writer = Vec::new(); let mut emitter = CheckstyleEmitter::default(); let _ = emitter.emit_header(&mut writer); @@ -118,7 +118,7 @@ mod tests { ) .unwrap(); let _ = emitter.emit_footer(&mut writer); - let exp_bin_xml = vec![ + let exp_bin_xml = [ format!(r#"<file name="{}">"#, bin_file), format!( r#"<error line="2" severity="warning" message="Should be `{}`" />"#, @@ -126,7 +126,7 @@ mod tests { ), String::from("</file>"), ]; - let exp_lib_xml = vec![ + let exp_lib_xml = [ format!(r#"<file name="{}">"#, lib_file), format!( r#"<error line="2" severity="warning" message="Should be `{}`" />"#, @@ -136,7 +136,7 @@ mod tests { ]; assert_eq!( String::from_utf8(writer).unwrap(), - vec![ + [ r#"<?xml version="1.0" encoding="utf-8"?>"#, "\n", r#"<checkstyle version="4.3">"#, diff --git a/src/tools/rustfmt/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs index 0af19a7d0b2..4e48c59ea29 100644 --- a/src/tools/rustfmt/src/emitter/diff.rs +++ b/src/tools/rustfmt/src/emitter/diff.rs @@ -32,7 +32,7 @@ impl Emitter for DiffEmitter { } else { print_diff( mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num), + |line_num| format!("Diff in {}:{}:", filename, line_num), &self.config, ); } diff --git a/src/tools/rustfmt/src/emitter/json.rs b/src/tools/rustfmt/src/emitter/json.rs index f47c3260a02..084f565804c 100644 --- a/src/tools/rustfmt/src/emitter/json.rs +++ b/src/tools/rustfmt/src/emitter/json.rs @@ -212,7 +212,7 @@ mod tests { #[test] fn emits_array_with_files_with_diffs() { let file_name = "src/bin.rs"; - let original = vec![ + let original = [ "fn main() {", "println!(\"Hello, world!\");", "}", @@ -225,7 +225,7 @@ mod tests { "}", "}", ]; - let formatted = vec![ + let formatted = [ "fn main() {", " println!(\"Hello, world!\");", "}", @@ -285,11 +285,11 @@ mod tests { #[test] fn emits_valid_json_with_multiple_files() { let bin_file = "src/bin.rs"; - let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"]; - let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"]; + let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"]; + let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"]; let lib_file = "src/lib.rs"; - let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"]; - let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"]; + let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"]; + let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"]; let mut writer = Vec::new(); let mut emitter = JsonEmitter::default(); let _ = emitter.emit_header(&mut writer); diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 053afcc52d4..8266f95fd70 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -139,7 +139,17 @@ pub(crate) fn format_expr( | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), ast::ExprKind::ConstBlock(ref anon_const) => { - Some(format!("const {}", anon_const.rewrite(context, shape)?)) + let rewrite = match anon_const.value.kind { + ast::ExprKind::Block(ref block, opt_label) => { + // Inner attributes are associated with the `ast::ExprKind::ConstBlock` node, + // not the `ast::Block` node we're about to rewrite. To prevent dropping inner + // attributes call `rewrite_block` directly. + // See https://github.com/rust-lang/rustfmt/issues/6158 + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)? + } + _ => anon_const.rewrite(context, shape)?, + }; + Some(format!("const {}", rewrite)) } ast::ExprKind::Block(ref block, opt_label) => { match expr_type { @@ -253,14 +263,6 @@ pub(crate) fn format_expr( shape, SeparatorPlace::Front, ), - ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( - &**expr, - &**ty, - PairParts::infix(": "), - context, - shape, - SeparatorPlace::Back, - ), ast::ExprKind::Index(ref expr, ref index, _) => { rewrite_index(&**expr, &**index, context, shape) } @@ -282,6 +284,9 @@ pub(crate) fn format_expr( match lhs.kind { ast::ExprKind::Lit(token_lit) => lit_ends_in_dot(&token_lit), ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr), + ast::ExprKind::Binary(_, _, ref rhs_expr) => { + needs_space_before_range(context, rhs_expr) + } _ => false, } } @@ -399,10 +404,14 @@ pub(crate) fn format_expr( } ast::ExprKind::Underscore => Some("_".to_owned()), ast::ExprKind::FormatArgs(..) + | ast::ExprKind::Type(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) => { - // These do not occur in the AST because macros aren't expanded. - unreachable!() + // These don't normally occur in the AST because macros aren't expanded. However, + // rustfmt tries to parse macro arguments when formatting macros, so it's not totally + // impossible for rustfmt to come across one of these nodes when formatting a file. + // Also, rustfmt might get passed the output from `-Zunpretty=expanded`. + None } ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None, }; diff --git a/src/tools/rustfmt/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs index 61e2cb711a5..f9eb70f6e04 100644 --- a/src/tools/rustfmt/src/format-diff/main.rs +++ b/src/tools/rustfmt/src/format-diff/main.rs @@ -38,14 +38,14 @@ enum FormatDiffError { } #[derive(Parser, Debug)] -#[clap( +#[command( name = "rustfmt-format-diff", disable_version_flag = true, next_line_help = true )] pub struct Opts { /// Skip the smallest prefix containing NUMBER slashes - #[clap( + #[arg( short = 'p', long = "skip-prefix", value_name = "NUMBER", @@ -54,7 +54,7 @@ pub struct Opts { skip_prefix: u32, /// Custom pattern selecting file paths to reformat - #[clap( + #[arg( short = 'f', long = "filter", value_name = "PATTERN", @@ -234,14 +234,14 @@ mod cmd_line_tests { #[test] fn default_options() { let empty: Vec<String> = vec![]; - let o = Opts::parse_from(&empty); + let o = Opts::parse_from(empty); assert_eq!(DEFAULT_PATTERN, o.filter); assert_eq!(0, o.skip_prefix); } #[test] fn good_options() { - let o = Opts::parse_from(&["test", "-p", "10", "-f", r".*\.hs"]); + let o = Opts::parse_from(["test", "-p", "10", "-f", r".*\.hs"]); assert_eq!(r".*\.hs", o.filter); assert_eq!(10, o.skip_prefix); } @@ -250,7 +250,7 @@ mod cmd_line_tests { fn unexpected_option() { assert!( Opts::command() - .try_get_matches_from(&["test", "unexpected"]) + .try_get_matches_from(["test", "unexpected"]) .is_err() ); } @@ -259,7 +259,7 @@ mod cmd_line_tests { fn unexpected_flag() { assert!( Opts::command() - .try_get_matches_from(&["test", "--flag"]) + .try_get_matches_from(["test", "--flag"]) .is_err() ); } @@ -268,7 +268,7 @@ mod cmd_line_tests { fn overridden_option() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p", "10", "-p", "20"]) + .try_get_matches_from(["test", "-p", "10", "-p", "20"]) .is_err() ); } @@ -277,7 +277,7 @@ mod cmd_line_tests { fn negative_filter() { assert!( Opts::command() - .try_get_matches_from(&["test", "-p", "-1"]) + .try_get_matches_from(["test", "-p", "-1"]) .is_err() ); } diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs index 3bcb4d15184..7f442230b12 100644 --- a/src/tools/rustfmt/src/formatting.rs +++ b/src/tools/rustfmt/src/formatting.rs @@ -82,7 +82,7 @@ fn should_skip_module<T: FormatHandler>( let source_file = context.psess.span_to_file_contents(module.span); let src = source_file.src.as_ref().expect("SourceFile without src"); - if is_generated_file(src) { + if is_generated_file(src, config) { return true; } } diff --git a/src/tools/rustfmt/src/formatting/generated.rs b/src/tools/rustfmt/src/formatting/generated.rs index 58f43f17ee1..68ffee6e664 100644 --- a/src/tools/rustfmt/src/formatting/generated.rs +++ b/src/tools/rustfmt/src/formatting/generated.rs @@ -1,7 +1,10 @@ +use crate::Config; + /// Returns `true` if the given span is a part of generated files. -pub(super) fn is_generated_file(original_snippet: &str) -> bool { +pub(super) fn is_generated_file(original_snippet: &str, config: &Config) -> bool { original_snippet .lines() - .take(5) // looking for marker only in the beginning of the file + // looking for marker only in the beginning of the file + .take(config.generated_marker_line_search_limit()) .any(|line| line.contains("@generated")) } diff --git a/src/tools/rustfmt/src/ignore_path.rs b/src/tools/rustfmt/src/ignore_path.rs index 7b5697bec3e..5c25f233ce3 100644 --- a/src/tools/rustfmt/src/ignore_path.rs +++ b/src/tools/rustfmt/src/ignore_path.rs @@ -49,4 +49,22 @@ mod test { assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); } + + #[nightly_only_test] + #[test] + fn test_negated_ignore_path_set() { + use crate::config::{Config, FileName}; + use crate::ignore_path::IgnorePathSet; + use std::path::{Path, PathBuf}; + + let config = Config::from_toml( + r#"ignore = ["foo.rs", "bar_dir/*", "!bar_dir/*/what.rs"]"#, + Path::new(""), + ) + .unwrap(); + let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/what.rs")))); + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz/a.rs")))); + assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz/what.rs")))); + } } diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs index 2da746295fc..12c178e136f 100644 --- a/src/tools/rustfmt/src/imports.rs +++ b/src/tools/rustfmt/src/imports.rs @@ -685,9 +685,9 @@ impl UseTree { let prefix = &self.path[..self.path.len() - 1]; let mut result = vec![]; for nested_use_tree in list { - for flattend in &mut nested_use_tree.clone().flatten(import_granularity) { + for flattened in &mut nested_use_tree.clone().flatten(import_granularity) { let mut new_path = prefix.to_vec(); - new_path.append(&mut flattend.path); + new_path.append(&mut flattened.path); result.push(UseTree { path: new_path, span: self.span, diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index e869787b394..c8ea104e9d6 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -656,9 +656,16 @@ impl<'a> FmtVisitor<'a> { } let context = self.get_context(); - // 1 = ',' - let shape = self.shape().sub_width(1)?; - let attrs_str = field.attrs.rewrite(&context, shape)?; + let shape = self.shape(); + let attrs_str = if context.config.version() == Version::Two { + field.attrs.rewrite(&context, shape)? + } else { + // Version::One formatting that was off by 1. See issue #5801 + field.attrs.rewrite(&context, shape.sub_width(1)?)? + }; + // sub_width(1) to take the trailing comma into account + let shape = shape.sub_width(1)?; + let lo = field .attrs .last() @@ -836,13 +843,15 @@ pub(crate) fn format_impl( if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { result.push_str(&where_clause_str); - if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { - // if the where_clause contains extra comments AND - // there is only one where-clause predicate - // recover the suppressed comma in single line where_clause formatting + if where_clause_str.contains('\n') { + // If there is only one where-clause predicate + // and the where-clause spans multiple lines, + // then recover the suppressed comma in single line where-clause formatting if generics.where_clause.predicates.len() == 1 { result.push(','); } + } + if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { result.push_str(&format!("{sep}{{{sep}}}")); } else { result.push_str(" {}"); @@ -1161,9 +1170,9 @@ pub(crate) fn format_trait( // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. if !bounds.is_empty() { - let ident_hi = context - .snippet_provider - .span_after(item.span, item.ident.as_str()); + // Retrieve *unnormalized* ident (See #6069) + let source_ident = context.snippet(item.ident.span); + let ident_hi = context.snippet_provider.span_after(item.span, source_ident); let bound_hi = bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(snippet) { @@ -1906,6 +1915,7 @@ pub(crate) fn rewrite_struct_field( pub(crate) struct StaticParts<'a> { prefix: &'a str, + safety: ast::Safety, vis: &'a ast::Visibility, ident: symbol::Ident, ty: &'a ast::Ty, @@ -1917,11 +1927,12 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, ty, mutability, expr) = match &item.kind { - ast::ItemKind::Static(s) => (None, "static", &s.ty, s.mutability, &s.expr), + let (defaultness, prefix, safety, ty, mutability, expr) = match &item.kind { + ast::ItemKind::Static(s) => (None, "static", s.safety, &s.ty, s.mutability, &s.expr), ast::ItemKind::Const(c) => ( Some(c.defaultness), "const", + ast::Safety::Default, &c.ty, ast::Mutability::Not, &c.expr, @@ -1930,6 +1941,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix, + safety, vis: &item.vis, ident: item.ident, ty, @@ -1947,6 +1959,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix: "const", + safety: ast::Safety::Default, vis: &ti.vis, ident: ti.ident, ty, @@ -1964,6 +1977,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix: "const", + safety: ast::Safety::Default, vis: &ii.vis, ident: ii.ident, ty, @@ -1980,11 +1994,13 @@ fn rewrite_static( static_parts: &StaticParts<'_>, offset: Indent, ) -> Option<String> { + println!("rewriting static"); let colon = colon_spaces(context.config); let mut prefix = format!( - "{}{}{} {}{}{}", + "{}{}{}{} {}{}{}", format_visibility(context, static_parts.vis), static_parts.defaultness.map_or("", format_defaultness), + format_safety(static_parts.safety), static_parts.prefix, format_mutability(static_parts.mutability), rewrite_ident(context, static_parts.ident), @@ -2483,7 +2499,7 @@ fn rewrite_fn_base( || context.config.indent_style() == IndentStyle::Visual { let indent = if param_str.is_empty() { - // Aligning with non-existent params looks silly. + // Aligning with nonexistent params looks silly. force_new_line_for_brace = true; indent + 4 } else { @@ -2498,7 +2514,7 @@ fn rewrite_fn_base( } else { let mut ret_shape = Shape::indented(indent, context.config); if param_str.is_empty() { - // Aligning with non-existent params looks silly. + // Aligning with nonexistent params looks silly. force_new_line_for_brace = true; ret_shape = if context.use_block_indent() { ret_shape.offset_left(4).unwrap_or(ret_shape) @@ -3329,10 +3345,12 @@ impl Rewrite for ast::ForeignItem { // FIXME(#21): we're dropping potential comments in between the // function kw here. let vis = format_visibility(context, &self.vis); + let safety = format_safety(static_foreign_item.safety); let mut_str = format_mutability(static_foreign_item.mutability); let prefix = format!( - "{}static {}{}:", + "{}{}static {}{}:", vis, + safety, mut_str, rewrite_ident(context, self.ident) ); diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 877d057a34b..ff2b14af078 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -5,9 +5,6 @@ #![allow(clippy::match_like_matches_macro)] #![allow(unreachable_pub)] -#[cfg(test)] -#[macro_use] -extern crate lazy_static; #[macro_use] extern crate tracing; @@ -62,6 +59,13 @@ pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines}; #[macro_use] mod utils; +macro_rules! static_regex { + ($re:literal) => {{ + static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new(); + RE.get_or_init(|| ::regex::Regex::new($re).unwrap()) + }}; +} + mod attr; mod chains; mod closures; @@ -258,8 +262,8 @@ impl FormatReport { self.internal .borrow() .0 - .iter() - .map(|(_, errors)| errors.len()) + .values() + .map(|errors| errors.len()) .sum() } @@ -305,7 +309,7 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option< let mut out: Vec<u8> = Vec::with_capacity(snippet.len() * 2); config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); - config.set().hide_parse_errors(true); + config.set().show_parse_errors(false); if is_macro_def { config.set().error_on_unformatted(true); } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 6b24b1aec5d..a0582b061c0 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -25,6 +25,7 @@ use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, }; use crate::config::lists::*; +use crate::config::Version; use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind}; use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::overflow; @@ -389,7 +390,7 @@ fn rewrite_empty_macro_def_body( stmts: vec![].into(), id: rustc_ast::node_id::DUMMY_NODE_ID, rules: ast::BlockCheckMode::Default, - span: span, + span, tokens: None, could_be_bare_literal: false, }; @@ -1245,8 +1246,16 @@ impl MacroBranch { return None; } - // 5 = " => {" - let mut result = format_macro_args(context, self.args.clone(), shape.sub_width(5)?)?; + let old_body = context.snippet(self.body).trim(); + let has_block_body = old_body.starts_with('{'); + let mut prefix_width = 5; // 5 = " => {" + if context.config.version() == Version::Two { + if has_block_body { + prefix_width = 6; // 6 = " => {{" + } + } + let mut result = + format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?; if multi_branch_style { result += " =>"; @@ -1264,12 +1273,10 @@ impl MacroBranch { // `$$`). We'll try and format like an AST node, but we'll substitute // variables for new names with the same length first. - let old_body = context.snippet(self.body).trim(); let (body_str, substs) = replace_names(old_body)?; - let has_block_body = old_body.starts_with('{'); let mut config = context.config.clone(); - config.set().hide_parse_errors(true); + config.set().show_parse_errors(false); result += " {"; diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index e68903c8715..e4fa077073c 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -5,7 +5,7 @@ use std::iter::repeat; use rustc_ast::{ast, ptr, MatchKind}; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; +use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented}; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version}; use crate::expr::{ @@ -104,6 +104,10 @@ pub(crate) fn rewrite_match( let inner_attrs_str = if inner_attrs.is_empty() { String::new() } else { + let shape = match context.config.version() { + Version::One => shape, + _ => shape.block_indent(context.config.tab_spaces()), + }; inner_attrs .rewrite(context, shape) .map(|s| format!("{}{}\n", nested_indent_str, s))? @@ -352,10 +356,10 @@ fn flatten_arm_body<'a>( (true, body) } } else { - let cond_becomes_muti_line = opt_shape + let cond_becomes_multi_line = opt_shape .and_then(|shape| rewrite_cond(context, expr, shape)) .map_or(false, |cond| cond.contains('\n')); - if cond_becomes_muti_line { + if cond_becomes_multi_line { (false, &*body) } else { (can_extend(expr), &*expr) @@ -415,7 +419,11 @@ fn rewrite_match_body( let arrow_snippet = context.snippet(arrow_span).trim(); // search for the arrow starting from the end of the snippet since there may be a match // expression within the guard - let arrow_index = arrow_snippet.rfind("=>").unwrap(); + let arrow_index = if context.config.version() == Version::One { + arrow_snippet.rfind("=>").unwrap() + } else { + arrow_snippet.find_last_uncommented("=>").unwrap() + }; // 2 = `=>` let comment_str = arrow_snippet[arrow_index + 2..].trim(); if comment_str.is_empty() { @@ -464,8 +472,8 @@ fn rewrite_match_body( }; let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), _ if body_prefix.is_empty() => "".to_owned(), + ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), _ if forbid_same_line || !arrow_comment.is_empty() => { format!("{}{}", alt_block_sep, body_prefix) } diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index f46583b1c89..c44f3788d97 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -8,8 +8,8 @@ use rustc_ast::{ast, ptr}; use rustc_span::Span; use crate::closures; -use crate::config::lists::*; use crate::config::Version; +use crate::config::{lists::*, Config}; use crate::expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, rewrite_cond, @@ -60,6 +60,13 @@ const SPECIAL_CASE_MACROS: &[(&str, usize)] = &[ ("debug_assert_ne!", 2), ]; +/// Additional special case macros for version 2; these are separated to avoid breaking changes in +/// version 1. +const SPECIAL_CASE_MACROS_V2: &[(&str, usize)] = &[ + // From the `log` crate. + ("trace!", 0), +]; + const SPECIAL_CASE_ATTR: &[(&str, usize)] = &[ // From the `failure` crate. ("fail", 0), @@ -182,12 +189,17 @@ impl<'a> OverflowableItem<'a> { } } - fn special_cases(&self) -> &'static [(&'static str, usize)] { - match self { + fn special_cases(&self, config: &Config) -> impl Iterator<Item = &(&'static str, usize)> { + let base_cases = match self { OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS, OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR, _ => &[], - } + }; + let additional_cases = match (self, config.version()) { + (OverflowableItem::MacroArg(..), Version::Two) => SPECIAL_CASE_MACROS_V2, + _ => &[], + }; + base_cases.iter().chain(additional_cases) } } @@ -511,7 +523,7 @@ impl<'a> Context<'a> { // However, when the inner function has a prefix or a suffix // (e.g., `foo() as u32`), this budget reduction may produce poorly // formatted code, where a prefix or a suffix being left on its own - // line. Here we explicitlly check those cases. + // line. Here we explicitly check those cases. if count_newlines(overflowed) == 1 { let rw = self .items @@ -551,7 +563,7 @@ impl<'a> Context<'a> { if tactic == DefinitiveListTactic::Vertical { if let Some((all_simple, num_args_before)) = - maybe_get_args_offset(self.ident, &self.items) + maybe_get_args_offset(self.ident, &self.items, &self.context.config) { let one_line = all_simple && definitive_tactic( @@ -771,11 +783,11 @@ fn no_long_items(list: &[ListItem], short_array_element_width_threshold: usize) pub(crate) fn maybe_get_args_offset( callee_str: &str, args: &[OverflowableItem<'_>], + config: &Config, ) -> Option<(bool, usize)> { if let Some(&(_, num_args_before)) = args .get(0)? - .special_cases() - .iter() + .special_cases(config) .find(|&&(s, _)| s == callee_str) { let all_simple = args.len() > num_args_before diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs index 7026935294a..7baac247e22 100644 --- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs +++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs @@ -31,7 +31,6 @@ pub(crate) fn parse_lazy_static( } } } - while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index f4fbabaf6c9..05cf467167c 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -97,7 +97,7 @@ fn default_dcx( source_map: Lrc<SourceMap>, ignore_path_set: Lrc<IgnorePathSet>, can_reset: Lrc<AtomicBool>, - hide_parse_errors: bool, + show_parse_errors: bool, color: Color, ) -> DiagCtxt { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); @@ -116,7 +116,7 @@ fn default_dcx( .sm(Some(source_map.clone())), ); - let emitter: Box<DynEmitter> = if hide_parse_errors { + let emitter: Box<DynEmitter> = if !show_parse_errors { Box::new(SilentEmitter { fallback_bundle, fatal_dcx: DiagCtxt::new(emitter), @@ -148,7 +148,7 @@ impl ParseSess { Lrc::clone(&source_map), Lrc::clone(&ignore_path_set), Lrc::clone(&can_reset_errors), - config.hide_parse_errors(), + config.show_parse_errors(), config.color(), ); let raw_psess = RawParseSess::with_dcx(dcx, source_map); @@ -164,7 +164,7 @@ impl ParseSess { /// /// * `id` - The name of the module /// * `relative` - If Some(symbol), the symbol name is a directory relative to the dir_path. - /// If relative is Some, resolve the submodle at {dir_path}/{symbol}/{id}.rs + /// If relative is Some, resolve the submodule at {dir_path}/{symbol}/{id}.rs /// or {dir_path}/{symbol}/{id}/mod.rs. if None, resolve the module at {dir_path}/{id}.rs. /// * `dir_path` - Module resolution will occur relative to this directory. pub(crate) fn default_submod_path( @@ -175,7 +175,7 @@ impl ParseSess { ) -> Result<ModulePathSuccess, ModError<'_>> { rustc_expand::module::default_submod_path(&self.raw_psess, id, relative, dir_path).or_else( |e| { - // If resloving a module relative to {dir_path}/{symbol} fails because a file + // If resolving a module relative to {dir_path}/{symbol} fails because a file // could not be found, then try to resolve the module relative to {dir_path}. // If we still can't find the module after searching for it in {dir_path}, // surface the original error. diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs index 2b43ec94b6b..5eea8021b32 100644 --- a/src/tools/rustfmt/src/source_file.rs +++ b/src/tools/rustfmt/src/source_file.rs @@ -33,7 +33,7 @@ where let mut emitter = create_emitter(config); emitter.emit_header(out)?; - for &(ref filename, ref text) in source_file { + for (filename, text) in source_file { write_file( None, filename, diff --git a/src/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs index 80b61c88a00..e4a390ada66 100644 --- a/src/tools/rustfmt/src/test/configuration_snippet.rs +++ b/src/tools/rustfmt/src/test/configuration_snippet.rs @@ -24,19 +24,13 @@ impl ConfigurationSection { fn get_section<I: Iterator<Item = String>>( file: &mut Enumerate<I>, ) -> Option<ConfigurationSection> { - lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern"); - // Configuration values, which will be passed to `from_str`: - // - // - must be prefixed with `####` - // - must be wrapped in backticks - // - may by wrapped in double quotes (which will be stripped) - static ref CONFIG_VALUE_REGEX: regex::Regex = - regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#) - .expect("failed creating configuration value pattern"); - } - + let config_name_regex = static_regex!(r"^## `([^`]+)`"); + // Configuration values, which will be passed to `from_str`: + // + // - must be prefixed with `####` + // - must be wrapped in backticks + // - may by wrapped in double quotes (which will be stripped) + let config_value_regex = static_regex!(r#"^#### `"?([^`]+?)"?`"#); loop { match file.next() { Some((i, line)) => { @@ -53,9 +47,9 @@ impl ConfigurationSection { let start_line = (i + 2) as u32; return Some(ConfigurationSection::CodeBlock((block, start_line))); - } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + } else if let Some(c) = config_name_regex.captures(&line) { return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); - } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + } else if let Some(c) = config_value_regex.captures(&line) { return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); } } @@ -208,7 +202,7 @@ impl ConfigCodeBlock { } // Extract a code block from the iterator. Behavior: - // - Rust code blocks are identifed by lines beginning with "```rust". + // - Rust code blocks are identified by lines beginning with "```rust". // - One explicit configuration setting is supported per code block. // - Rust code blocks with no configuration setting are illegal and cause an // assertion failure, unless the snippet begins with #![rustfmt::skip]. diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index 47f89c1871a..7c563801c32 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -332,7 +332,7 @@ fn assert_stdin_output( let mut session = Session::new(config, Some(&mut buf)); session.format(input).unwrap(); let errors = ReportedErrors { - has_diff: has_diff, + has_diff, ..Default::default() }; assert_eq!(session.errors, errors); @@ -390,6 +390,26 @@ fn self_tests() { path.push("main.rs"); files.push(path); } + // for crates that need to be included but lies outside src + let external_crates = vec!["check_diff", "config_proc_macro"]; + for external_crate in external_crates { + let mut path = PathBuf::from(external_crate); + path.push("src"); + let directory = fs::read_dir(&path).unwrap(); + let search_files = directory.filter_map(|file| { + file.ok().and_then(|f| { + let name = f.file_name(); + if matches!(name.as_os_str().to_str(), Some("main.rs" | "lib.rs")) { + Some(f.path()) + } else { + None + } + }) + }); + for file in search_files { + files.push(file); + } + } files.push(PathBuf::from("src/lib.rs")); let (reports, count, fails) = check_files(files, &Some(PathBuf::from("rustfmt.toml"))); @@ -835,7 +855,7 @@ fn handle_result( // Ignore LF and CRLF difference for Windows. if !string_eq_ignore_newline_repr(&fmt_text, &text) { if std::env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") { - std::fs::write(file_name, fmt_text).unwrap(); + std::fs::write(target, fmt_text).unwrap(); continue; } let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index c2c192738c9..c12f271bc5d 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -43,11 +43,13 @@ pub(crate) fn rewrite_path( ) -> Option<String> { let skip_count = qself.as_ref().map_or(0, |x| x.position); - let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { - "::".to_owned() - } else { - String::new() - }; + // 32 covers almost all path lengths measured when compiling core, and there isn't a big + // downside from allocating slightly more than necessary. + let mut result = String::with_capacity(32); + + if path.is_global() && qself.is_none() && path_context != PathContext::Import { + result.push_str("::"); + } let mut span_lo = path.span.lo(); @@ -693,10 +695,12 @@ impl Rewrite for ast::Ty { }; let mut res = bounds.rewrite(context, shape)?; // We may have falsely removed a trailing `+` inside macro call. - if context.inside_macro() && bounds.len() == 1 { - if context.snippet(self.span).ends_with('+') && !res.ends_with('+') { - res.push('+'); - } + if context.inside_macro() + && bounds.len() == 1 + && context.snippet(self.span).ends_with('+') + && !res.ends_with('+') + { + res.push('+'); } Some(format!("{prefix}{res}")) } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 7a0c68c214c..1de9f5a9524 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -81,7 +81,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) snippet_provider: &'a SnippetProvider, pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip - /// Both bounds are inclusifs. + /// Both bounds are inclusive. pub(crate) skipped_range: Rc<RefCell<Vec<(usize, usize)>>>, pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, diff --git a/src/tools/rustfmt/tests/config/issue-5801-v1.toml b/src/tools/rustfmt/tests/config/issue-5801-v1.toml new file mode 100644 index 00000000000..8695df0099e --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue-5801-v1.toml @@ -0,0 +1,3 @@ +max_width = 120 +version = "One" +attr_fn_like_width = 120 \ No newline at end of file diff --git a/src/tools/rustfmt/tests/config/issue-5801-v2.toml b/src/tools/rustfmt/tests/config/issue-5801-v2.toml new file mode 100644 index 00000000000..948f4fb66bf --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue-5801-v2.toml @@ -0,0 +1,3 @@ +max_width = 120 +version = "Two" +attr_fn_like_width = 120 \ No newline at end of file diff --git a/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs index 3122e4f220f..f102bf9d181 100644 --- a/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs +++ b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs @@ -6,4 +6,4 @@ mod one; fn main() {println!("Hello, world!"); } -// trailing commet +// trailing comment diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs index e66fad1e7fa..58cf0e5e4db 100644 --- a/src/tools/rustfmt/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -176,7 +176,14 @@ fn rustfmt_emits_error_on_line_overflow_true() { #[test] #[allow(non_snake_case)] fn dont_emit_ICE() { - let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs", "tests/target/issue_6082.rs"]; + let files = [ + "tests/target/issue_5728.rs", + "tests/target/issue_5729.rs", + "tests/target/issue-5885.rs", + "tests/target/issue_6082.rs", + "tests/target/issue_6069.rs", + "tests/target/issue-6105.rs", + ]; for file in files { let args = [file]; @@ -184,3 +191,19 @@ fn dont_emit_ICE() { assert!(!stderr.contains("thread 'main' panicked")); } } + +#[test] +fn rustfmt_emits_error_when_control_brace_style_is_always_next_line() { + // See also https://github.com/rust-lang/rustfmt/issues/5912 + let args = [ + "--config=color=Never", + "--config", + "control_brace_style=AlwaysNextLine", + "--config", + "match_arm_blocks=false", + "tests/target/issue_5912.rs", + ]; + + let (_stdout, stderr) = rustfmt(&args); + assert!(!stderr.contains("error[internal]: left behind trailing whitespace")) +} diff --git a/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs new file mode 100644 index 00000000000..fb0576a4822 --- /dev/null +++ b/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs @@ -0,0 +1,10 @@ +// rustfmt-version: Two +fn main() { + match a { + _ => + // comment with => + { + println!("A") + } + } +} diff --git a/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs new file mode 100644 index 00000000000..fc696b309f2 --- /dev/null +++ b/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs @@ -0,0 +1,14 @@ +// rustfmt-version: Two +fn main() { + match a { + _ => // comment with => + match b { + // one goes to => + one => { + println("1"); + } + // two goes to => + two => { println("2"); } + } + } +} diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs new file mode 100644 index 00000000000..be03849fe10 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs @@ -0,0 +1,10 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 15 + +fn main() +{ + println!("hello, world") + ; +} + +// @generated \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs new file mode 100644 index 00000000000..abb97e6259f --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs @@ -0,0 +1,10 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 1 + +fn main() +{ + println!("hello, world") + ; +} + +// @generated \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs new file mode 100644 index 00000000000..f6978d0f355 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs @@ -0,0 +1,9 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 0 + +// @generated +fn main() { + println!("hello, world") + ; +} +// @generated diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs new file mode 100644 index 00000000000..53cc116ec2b --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs @@ -0,0 +1,10 @@ +// rustfmt-format_generated_files: true +// rustfmt-generated_marker_line_search_limit: 20 + +fn main() +{ + println!("hello, world") + ; +} + +// @generated diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs new file mode 100644 index 00000000000..8eff1a3b0ee --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs @@ -0,0 +1,9 @@ +// rustfmt-format_generated_files: true + +fn main() +{ + println!("hello, world") + ; +} + +// @generated \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue-3805.rs b/src/tools/rustfmt/tests/source/issue-3805.rs new file mode 100644 index 00000000000..a0289b57974 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-3805.rs @@ -0,0 +1,65 @@ +// rustfmt-version: Two +// rustfmt-format_macro_matchers: true + +// From original issue example - Line length 101 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{ +return; +}}; +} + +// Spaces between the `{` and `}` +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => { { +return; +} }; +} + +// Multi `{}` +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{{{ +return; +}}}}; +} + +// Multi `{}` with spaces +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => { { { { +return; +} } } }; +} + +// Line length 102 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{ +return; +}}; +} + +// Line length 103 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{ +return; +}}; +} + +// With extended macro body - Line length 101 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{ +let VAR = "VALUE"; return VAR; +}}; +} + +// With extended macro body - Line length 102 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{ +let VAR = "VALUE"; return VAR; +}}; +} + +// With extended macro body - Line length 103 +macro_rules! test { +($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{ +let VAR = "VALUE"; return VAR; +}}; +} diff --git a/src/tools/rustfmt/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs new file mode 100644 index 00000000000..59902c7bcce --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-5801-v1.toml + +pub enum Severity { + #[something(AAAAAAAAAAAAA, BBBBBBBBBBBBBB, CCCCCCCCCCCCCCCC, DDDDDDDDDDDDD, EEEEEEEEEEEE, FFFFFFFFFFF, GGGGGGGGGGG)] + AttrsWillWrap, + #[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)] + AttrsWontWrap, +} diff --git a/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs new file mode 100644 index 00000000000..5847afd9560 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs @@ -0,0 +1,17 @@ +// rustfmt-comment_width: 120 +// rustfmt-wrap_comments: true +// rustfmt-max_width: 120 +// rustfmt-version: One + +/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine +fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String { + unimplemented!() +} + +pub enum Severity { + /// In version one, the below line got wrapped prematurely as we subtracted 1 to account for `,`. See issue #5801. + /// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still. + Error, + /// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem. + Warning, +} diff --git a/src/tools/rustfmt/tests/source/issue-5987/two.rs b/src/tools/rustfmt/tests/source/issue-5987/two.rs new file mode 100644 index 00000000000..e20026b5565 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5987/two.rs @@ -0,0 +1,13 @@ +// rustfmt-version: Two + +fn main() { + trace!( + "get some longer length in here yes yes {} {}", + "hello", + "world" + ); + debug!( + "get some longer length in here yes yes {} {}", + "hello", "world" + ); +} diff --git a/src/tools/rustfmt/tests/source/issue-6059/repro.rs b/src/tools/rustfmt/tests/source/issue-6059/repro.rs new file mode 100644 index 00000000000..1dc62cc8d26 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-6059/repro.rs @@ -0,0 +1,3 @@ +fn float_range_tests() { + self.coords.x -= rng.gen_range(-self.radius / 2. .. self.radius / 2.); +} diff --git a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs new file mode 100644 index 00000000000..2ac2e0361c3 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs @@ -0,0 +1,20 @@ +// rustfmt-version: One + +pub fn main() { +let a = Some(12); +match a { +#![attr1] +#![attr2] +#![attr3] +_ => None, +} + +{ +match a { +#![attr1] +#![attr2] +#![attr3] +_ => None, +} +} +} diff --git a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs new file mode 100644 index 00000000000..c1bf1ad4bf8 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs @@ -0,0 +1,20 @@ +// rustfmt-version: Two + +pub fn main() { +let a = Some(12); +match a { +#![attr1] +#![attr2] +#![attr3] +_ => None, +} + +{ +match a { +#![attr1] +#![attr2] +#![attr3] +_ => None, +} +} +} diff --git a/src/tools/rustfmt/tests/source/issue_5912.rs b/src/tools/rustfmt/tests/source/issue_5912.rs new file mode 100644 index 00000000000..2265fd2146c --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_5912.rs @@ -0,0 +1,15 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-control_brace_style: AlwaysNextLine + +fn foo() { + match 0 { + 0 => { + aaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb + } + _ => 2, + } +} diff --git a/src/tools/rustfmt/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs index cb2859e805d..c589ab75cd3 100644 --- a/src/tools/rustfmt/tests/source/let_else.rs +++ b/src/tools/rustfmt/tests/source/let_else.rs @@ -117,8 +117,8 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n // Break after the `=` and put the initializer expr on it's own line. // Because the initializer expr is multi-lined the else is placed on it's own line. // The initializer expr has a length of 91, which when indented on the next line - // The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be - // before we start running into max_width issues. I suspect this is becuase the shape is + // The `(indent)init` line has a length of 99. This is the max length that the `init` can be + // before we start running into max_width issues. I suspect this is because the shape is // accounting for the `;` at the end of the `let-else` statement. let Some(x) = some_really_really_really_really_really_really_really_really_really_really_long_name______I else {return}; @@ -127,7 +127,7 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n // Post Formatting: // Max length issues prevent us from formatting. // The initializer expr has a length of 92, which if it would be indented on the next line - // the `(indent)init` line has a lengh of 100 which == max_width of 100. + // the `(indent)init` line has a length of 100 which == max_width of 100. // One might expect formatting to succeed, but I suspect the reason we hit max_width issues is // because the Shape is accounting for the `;` at the end of the `let-else` statement. let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return}; diff --git a/src/tools/rustfmt/tests/source/no_arg_with_commnet.rs b/src/tools/rustfmt/tests/source/no_arg_with_commnet.rs index ea4ee0f1eee..41c3c6bea48 100644 --- a/src/tools/rustfmt/tests/source/no_arg_with_commnet.rs +++ b/src/tools/rustfmt/tests/source/no_arg_with_commnet.rs @@ -1,2 +1,2 @@ -fn foo( /* cooment */ +fn foo( /* comment */ ) {} diff --git a/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs new file mode 100644 index 00000000000..deffdbeeaaf --- /dev/null +++ b/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs @@ -0,0 +1,10 @@ +// rustfmt-version: Two +fn main() { + match a { + _ => + // comment with => + { + println!("A") + } + } +} diff --git a/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs new file mode 100644 index 00000000000..b0443411816 --- /dev/null +++ b/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs @@ -0,0 +1,19 @@ +// rustfmt-version: Two +fn main() { + match a { + _ => + // comment with => + { + match b { + // one goes to => + one => { + println("1"); + } + // two goes to => + two => { + println("2"); + } + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs new file mode 100644 index 00000000000..be03849fe10 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs @@ -0,0 +1,10 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 15 + +fn main() +{ + println!("hello, world") + ; +} + +// @generated \ No newline at end of file diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs new file mode 100644 index 00000000000..93405896a1d --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs @@ -0,0 +1,8 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 1 + +fn main() { + println!("hello, world"); +} + +// @generated diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs new file mode 100644 index 00000000000..6acd46ed2eb --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs @@ -0,0 +1,8 @@ +// rustfmt-format_generated_files: false +// rustfmt-generated_marker_line_search_limit: 0 + +// @generated +fn main() { + println!("hello, world"); +} +// @generated diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs new file mode 100644 index 00000000000..03bfdfd1c59 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs @@ -0,0 +1,8 @@ +// rustfmt-format_generated_files: true +// rustfmt-generated_marker_line_search_limit: 20 + +fn main() { + println!("hello, world"); +} + +// @generated diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs new file mode 100644 index 00000000000..3b6280b350e --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs @@ -0,0 +1,7 @@ +// rustfmt-format_generated_files: true + +fn main() { + println!("hello, world"); +} + +// @generated diff --git a/src/tools/rustfmt/tests/target/impl.rs b/src/tools/rustfmt/tests/target/impl.rs index f37fbcf1fcb..10de0ecde56 100644 --- a/src/tools/rustfmt/tests/target/impl.rs +++ b/src/tools/rustfmt/tests/target/impl.rs @@ -32,6 +32,11 @@ where { } +// #5941 +impl T where (): Clone // Should not add comma to comment +{ +} + // #1823 default impl Trait for X {} default unsafe impl Trait for Y {} diff --git a/src/tools/rustfmt/tests/target/issue-3805.rs b/src/tools/rustfmt/tests/target/issue-3805.rs new file mode 100644 index 00000000000..a247a43fe6d --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-3805.rs @@ -0,0 +1,94 @@ +// rustfmt-version: Two +// rustfmt-format_macro_matchers: true + +// From original issue example - Line length 101 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr + ) => {{ + return; + }}; +} + +// Spaces between the `{` and `}` +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr + ) => {{ + return; + }}; +} + +// Multi `{}` +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr + ) => {{ + { + { + return; + } + } + }}; +} + +// Multi `{}` with spaces +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr + ) => {{ + { + { + return; + } + } + }}; +} + +// Line length 102 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr + ) => {{ + return; + }}; +} + +// Line length 103 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr + ) => {{ + return; + }}; +} + +// With extended macro body - Line length 101 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr + ) => {{ + let VAR = "VALUE"; + return VAR; + }}; +} + +// With extended macro body - Line length 102 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr + ) => {{ + let VAR = "VALUE"; + return VAR; + }}; +} + +// With extended macro body - Line length 103 +macro_rules! test { + ( + $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr + ) => {{ + let VAR = "VALUE"; + return VAR; + }}; +} diff --git a/src/tools/rustfmt/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs new file mode 100644 index 00000000000..e3b6f3b37f5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-5801-v2.toml + +pub enum Severity { + #[something(AAAAAAAAAAAAA, BBBBBBBBBBBBBB, CCCCCCCCCCCCCCCC, DDDDDDDDDDDDD, EEEEEEEEEEEE, FFFFFFFFFFF, GGGGGGGGGGG)] + AttrsWillWrap, + #[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)] + AttrsWontWrap, +} diff --git a/src/tools/rustfmt/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs new file mode 100644 index 00000000000..89676666225 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs @@ -0,0 +1,16 @@ +// rustfmt-config: issue-5801-v1.toml + +pub enum Severity { + #[something( + AAAAAAAAAAAAA, + BBBBBBBBBBBBBB, + CCCCCCCCCCCCCCCC, + DDDDDDDDDDDDD, + EEEEEEEEEEEE, + FFFFFFFFFFF, + GGGGGGGGGGG + )] + AttrsWillWrap, + #[something_else(hhhhhhhhhhhhhhhh, iiiiiiiiiiiiiiii, jjjjjjjjjjjjjjj, kkkkkkkkkkkkk, llllllllllll, mmmmmmmmmmmmmm)] + AttrsWontWrap, +} diff --git a/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs new file mode 100644 index 00000000000..9f294751108 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs @@ -0,0 +1,16 @@ +// rustfmt-comment_width: 120 +// rustfmt-wrap_comments: true +// rustfmt-max_width: 120 +// rustfmt-version: Two + +/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine +fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String { + unimplemented!() +} + +pub enum Severity { + /// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still. + Error, + /// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem. + Warning, +} diff --git a/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs new file mode 100644 index 00000000000..dd839dd4548 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs @@ -0,0 +1,18 @@ +// rustfmt-comment_width: 120 +// rustfmt-wrap_comments: true +// rustfmt-max_width: 120 +// rustfmt-version: One + +/// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine +fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String { + unimplemented!() +} + +pub enum Severity { + /// In version one, the below line got wrapped prematurely as we subtracted 1 to account for `,`. See issue #5801. + /// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines + /// still. + Error, + /// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem. + Warning, +} diff --git a/src/tools/rustfmt/tests/target/issue-5885.rs b/src/tools/rustfmt/tests/target/issue-5885.rs new file mode 100644 index 00000000000..85a659cbb47 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5885.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", builtin # offset_of(A, 0. 1.1.1)); +} diff --git a/src/tools/rustfmt/tests/target/issue-5987/one.rs b/src/tools/rustfmt/tests/target/issue-5987/one.rs new file mode 100644 index 00000000000..3c995ed28ba --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5987/one.rs @@ -0,0 +1,13 @@ +// rustfmt-version: One + +fn main() { + trace!( + "get some longer length in here yes yes {} {}", + "hello", + "world" + ); + debug!( + "get some longer length in here yes yes {} {}", + "hello", "world" + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-5987/two.rs b/src/tools/rustfmt/tests/target/issue-5987/two.rs new file mode 100644 index 00000000000..8fd92fc179e --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5987/two.rs @@ -0,0 +1,12 @@ +// rustfmt-version: Two + +fn main() { + trace!( + "get some longer length in here yes yes {} {}", + "hello", "world" + ); + debug!( + "get some longer length in here yes yes {} {}", + "hello", "world" + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-6059/additional.rs b/src/tools/rustfmt/tests/target/issue-6059/additional.rs new file mode 100644 index 00000000000..fe708dcbdd3 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6059/additional.rs @@ -0,0 +1,6 @@ +fn float_range_tests() { + let _range = 3. / 2. ..4.; + let _range = 3.0 / 2. ..4.0; + let _range = 3.0 / 2.0..4.0; + let _range = 3. / 2.0..4.0; +} diff --git a/src/tools/rustfmt/tests/target/issue-6059/repro.rs b/src/tools/rustfmt/tests/target/issue-6059/repro.rs new file mode 100644 index 00000000000..e8744c9ffcf --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6059/repro.rs @@ -0,0 +1,3 @@ +fn float_range_tests() { + self.coords.x -= rng.gen_range(-self.radius / 2. ..self.radius / 2.); +} diff --git a/src/tools/rustfmt/tests/target/issue-6105.rs b/src/tools/rustfmt/tests/target/issue-6105.rs new file mode 100644 index 00000000000..1eb0ce89f78 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6105.rs @@ -0,0 +1 @@ +const _: () = builtin # offset_of(x, x); diff --git a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs new file mode 100644 index 00000000000..75800012c63 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs @@ -0,0 +1,20 @@ +// rustfmt-version: One + +pub fn main() { + let a = Some(12); + match a { + #![attr1] + #![attr2] + #![attr3] + _ => None, + } + + { + match a { + #![attr1] + #![attr2] + #![attr3] + _ => None, + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs new file mode 100644 index 00000000000..5e4220e7306 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs @@ -0,0 +1,20 @@ +// rustfmt-version: Two + +pub fn main() { + let a = Some(12); + match a { + #![attr1] + #![attr2] + #![attr3] + _ => None, + } + + { + match a { + #![attr1] + #![attr2] + #![attr3] + _ => None, + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue_5912.rs b/src/tools/rustfmt/tests/target/issue_5912.rs new file mode 100644 index 00000000000..835f2aba971 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5912.rs @@ -0,0 +1,15 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-control_brace_style: AlwaysNextLine + +fn foo() { + match 0 + { + 0 => + aaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb + + bbbbbbbbbbbbbbbbbbbbbbbbb, + _ => 2, + } +} diff --git a/src/tools/rustfmt/tests/target/issue_6069.rs b/src/tools/rustfmt/tests/target/issue_6069.rs new file mode 100644 index 00000000000..d866ce7c646 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_6069.rs @@ -0,0 +1,3 @@ +// `Foó` as written here ends with ASCII 6F `'o'` followed by `'\u{0301}'` COMBINING ACUTE ACCENT. +// The compiler normalizes that combination to NFC form, `'\u{00F3}'` LATIN SMALL LETTER O WITH ACUTE. +trait Foó: Bar {} diff --git a/src/tools/rustfmt/tests/target/issue_6158.rs b/src/tools/rustfmt/tests/target/issue_6158.rs new file mode 100644 index 00000000000..82bb7d9fa05 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_6158.rs @@ -0,0 +1,7 @@ +fn main() { + const { + #![allow(clippy::assertions_on_constants)] + + assert!(1 < 2); + } +} diff --git a/src/tools/rustfmt/tests/target/issue_6159.rs b/src/tools/rustfmt/tests/target/issue_6159.rs new file mode 100644 index 00000000000..49fd539d3ef --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_6159.rs @@ -0,0 +1,3 @@ +fn main() { + builtin # type_ascribe(10, usize) +} diff --git a/src/tools/rustfmt/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs index f6560e85462..528d2929734 100644 --- a/src/tools/rustfmt/tests/target/let_else.rs +++ b/src/tools/rustfmt/tests/target/let_else.rs @@ -180,8 +180,8 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n // Break after the `=` and put the initializer expr on it's own line. // Because the initializer expr is multi-lined the else is placed on it's own line. // The initializer expr has a length of 91, which when indented on the next line - // The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be - // before we start running into max_width issues. I suspect this is becuase the shape is + // The `(indent)init` line has a length of 99. This is the max length that the `init` can be + // before we start running into max_width issues. I suspect this is because the shape is // accounting for the `;` at the end of the `let-else` statement. let Some(x) = some_really_really_really_really_really_really_really_really_really_really_long_name______I @@ -194,7 +194,7 @@ fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_n // Post Formatting: // Max length issues prevent us from formatting. // The initializer expr has a length of 92, which if it would be indented on the next line - // the `(indent)init` line has a lengh of 100 which == max_width of 100. + // the `(indent)init` line has a length of 100 which == max_width of 100. // One might expect formatting to succeed, but I suspect the reason we hit max_width issues is // because the Shape is accounting for the `;` at the end of the `let-else` statement. let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return}; diff --git a/src/tools/rustfmt/tests/target/no_arg_with_commnet.rs b/src/tools/rustfmt/tests/target/no_arg_with_commnet.rs index 69f61b60f29..21802d87f47 100644 --- a/src/tools/rustfmt/tests/target/no_arg_with_commnet.rs +++ b/src/tools/rustfmt/tests/target/no_arg_with_commnet.rs @@ -1 +1 @@ -fn foo(/* cooment */) {} +fn foo(/* comment */) {} diff --git a/src/tools/rustfmt/tests/target/unsafe_attributes.rs b/src/tools/rustfmt/tests/target/unsafe_attributes.rs new file mode 100644 index 00000000000..a05bedc751a --- /dev/null +++ b/src/tools/rustfmt/tests/target/unsafe_attributes.rs @@ -0,0 +1,34 @@ +#![feature(unsafe_attributes)] +// https://github.com/rust-lang/rust/issues/123757 +// +#![simple_ident] +#![simple::path] +#![simple_ident_expr = ""] +#![simple::path::Expr = ""] +#![simple_ident_tt(a b c)] +#![simple_ident_tt[a b c]] +#![simple_ident_tt{a b c}] +#![simple::path::tt(a b c)] +#![simple::path::tt[a b c]] +#![simple::path::tt{a b c}] +#![unsafe(simple_ident)] +#![unsafe(simple::path)] +#![unsafe(simple_ident_expr = "")] +#![unsafe(simple::path::Expr = "")] +#![unsafe(simple_ident_tt(a b c))] +#![unsafe(simple_ident_tt[a b c])] +#![unsafe(simple_ident_tt{a b c})] +#![unsafe(simple::path::tt(a b c))] +#![unsafe(simple::path::tt[a b c])] +#![unsafe(simple::path::tt{a b c})] +// I don't think `safe` attributes are a thing, but adding these formatting cases here just in case +#![safe(simple_ident)] +#![safe(simple::path)] +#![safe(simple_ident_expr = "")] +#![safe(simple::path::Expr = "")] +#![safe(simple_ident_tt(a b c))] +#![safe(simple_ident_tt[a b c])] +#![safe(simple_ident_tt{a b c})] +#![safe(simple::path::tt(a b c))] +#![safe(simple::path::tt[a b c])] +#![safe(simple::path::tt{a b c})] diff --git a/src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs b/src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs new file mode 100644 index 00000000000..66b4e1604d8 --- /dev/null +++ b/src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs @@ -0,0 +1,18 @@ +// See tracking issue for unsafe_extern_blocks +// https://github.com/rust-lang/rust/issues/123743 + +#![feature(unsafe_extern_blocks)] + +safe static TEST1: i32; + +unsafe extern "C" { + safe static TEST2: i32; + unsafe static TEST3: i32; + static TEST4: i32; + + pub safe static TEST5: i32; + pub unsafe static TEST6: i32; + pub static TEST7: i32; + + safe fn test1(i: i32); +} diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 63963b0bd1c..f39438bd9ac 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -13,6 +13,7 @@ ignore = "0.4.18" semver = "1.0" termcolor = "1.1.3" rustc-hash = "1.1.0" +fluent-syntax = "0.11.1" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index f3241354049..c3a94d17cd9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -14,7 +14,6 @@ run-make/compiler-lookup-paths-2/Makefile run-make/compiler-lookup-paths/Makefile run-make/compiler-rt-works-on-mingw/Makefile run-make/crate-hash-rustc-version/Makefile -run-make/crate-name-priority/Makefile run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile @@ -31,7 +30,6 @@ run-make/emit-shared-files/Makefile run-make/emit-stack-sizes/Makefile run-make/emit-to-stdout/Makefile run-make/env-dep-info/Makefile -run-make/error-writing-dependencies/Makefile run-make/export-executable-symbols/Makefile run-make/extern-diff-internal-name/Makefile run-make/extern-flag-disambiguates/Makefile @@ -54,7 +52,6 @@ run-make/foreign-rust-exceptions/Makefile run-make/include_bytes_deps/Makefile run-make/incr-add-rust-src-component/Makefile run-make/incr-foreign-head-span/Makefile -run-make/inline-always-many-cgu/Makefile run-make/interdependent-c-libraries/Makefile run-make/intrinsic-unreachable/Makefile run-make/invalid-library/Makefile @@ -154,7 +151,6 @@ run-make/raw-dylib-inline-cross-dylib/Makefile run-make/raw-dylib-link-ordinal/Makefile run-make/raw-dylib-stdcall-ordinal/Makefile run-make/redundant-libs/Makefile -run-make/relocation-model/Makefile run-make/relro-levels/Makefile run-make/remap-path-prefix-dwarf/Makefile run-make/remap-path-prefix/Makefile diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs new file mode 100644 index 00000000000..3a1fb6daf48 --- /dev/null +++ b/src/tools/tidy/src/fluent_period.rs @@ -0,0 +1,84 @@ +//! Checks that no Fluent messages or attributes end in periods (except ellipses) + +use fluent_syntax::ast::{Entry, PatternElement}; + +use crate::walk::{filter_dirs, walk}; +use std::path::Path; + +fn filter_fluent(path: &Path) -> bool { + if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } +} + +/// Messages allowed to have `.` at their end. +/// +/// These should probably be reworked eventually. +const ALLOWLIST: &[&str] = &[ + "const_eval_long_running", + "const_eval_validation_failure_note", + "driver_impl_ice", + "incremental_corrupt_file", + "mir_build_pointer_pattern", +]; + +fn check_period(filename: &str, contents: &str, bad: &mut bool) { + if filename.contains("codegen") { + // FIXME: Too many codegen messages have periods right now... + return; + } + + let (Ok(parse) | Err((parse, _))) = fluent_syntax::parser::parse(contents); + for entry in &parse.body { + if let Entry::Message(m) = entry { + if ALLOWLIST.contains(&m.id.name) { + continue; + } + + if let Some(pat) = &m.value { + if let Some(PatternElement::TextElement { value }) = pat.elements.last() { + // We don't care about ellipses. + if value.ends_with(".") && !value.ends_with("...") { + let ll = find_line(contents, *value); + let name = m.id.name; + tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period"); + } + } + } + + for attr in &m.attributes { + // Teach notes usually have long messages. + if attr.id.name == "teach_note" { + continue; + } + + if let Some(PatternElement::TextElement { value }) = attr.value.elements.last() { + if value.ends_with(".") && !value.ends_with("...") { + let ll = find_line(contents, *value); + let name = attr.id.name; + tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period"); + } + } + } + } + } +} + +/// Evil cursed bad hack. Requires that `value` be a substr (in memory) of `contents`. +fn find_line(haystack: &str, needle: &str) -> usize { + for (ll, line) in haystack.lines().enumerate() { + if line.as_ptr() > needle.as_ptr() { + return ll; + } + } + + 1 +} + +pub fn check(path: &Path, bad: &mut bool) { + walk( + path, + |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), + &mut |ent, contents| { + check_period(ent.path().to_str().unwrap(), contents, bad); + }, + ); +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index ae9d2b8b8dc..ecd32727fa0 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -72,6 +72,7 @@ pub mod ext_tool_checks; pub mod extdeps; pub mod features; pub mod fluent_alphabetical; +pub mod fluent_period; mod fluent_used; pub(crate) mod iter_header; pub mod known_bug; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 1d2b2e4d034..ec6fc1f07f1 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -115,6 +115,7 @@ fn main() { // Checks that only make sense for the compiler. check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); check!(fluent_alphabetical, &compiler_path, bless); + check!(fluent_period, &compiler_path); check!(target_policy, &root_path); // Checks that only make sense for the std libs. diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index 280b6d4a228..eeff1a070b4 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -1,10 +1,13 @@ +//@ revisions: base d32 neon //@ assembly-output: emit-asm //@ compile-flags: --target armv7-unknown-linux-gnueabihf -//@ compile-flags: -C target-feature=+neon //@ compile-flags: -C opt-level=0 +//@[d32] compile-flags: -C target-feature=+d32 +//@[neon] compile-flags: -C target-feature=+neon --cfg d32 +//@[neon] filecheck-flags: --check-prefix d32 //@ needs-llvm-components: arm -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -38,6 +41,8 @@ pub struct i32x2(i32, i32); #[repr(simd)] pub struct i64x1(i64); #[repr(simd)] +pub struct f16x4(f16, f16, f16, f16); +#[repr(simd)] pub struct f32x2(f32, f32); #[repr(simd)] pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); @@ -48,11 +53,14 @@ pub struct i32x4(i32, i32, i32, i32); #[repr(simd)] pub struct i64x2(i64, i64); #[repr(simd)] +pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +#[repr(simd)] pub struct f32x4(f32, f32, f32, f32); impl Copy for i8 {} impl Copy for i16 {} impl Copy for i32 {} +impl Copy for f16 {} impl Copy for f32 {} impl Copy for i64 {} impl Copy for f64 {} @@ -61,11 +69,13 @@ impl Copy for i8x8 {} impl Copy for i16x4 {} impl Copy for i32x2 {} impl Copy for i64x1 {} +impl Copy for f16x4 {} impl Copy for f32x2 {} impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} impl Copy for i64x2 {} +impl Copy for f16x8 {} impl Copy for f32x4 {} extern "C" { @@ -152,6 +162,12 @@ check!(reg_i16 i16 reg "mov"); // CHECK: @NO_APP check!(reg_i32 i32 reg "mov"); +// CHECK-LABEL: reg_f16: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_f16 f16 reg "mov"); + // CHECK-LABEL: reg_f32: // CHECK: @APP // CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} @@ -170,6 +186,12 @@ check!(reg_ptr ptr reg "mov"); // CHECK: @NO_APP check!(sreg_i32 i32 sreg "vmov.f32"); +// CHECK-LABEL: sreg_f16: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_f16 f16 sreg "vmov.f32"); + // CHECK-LABEL: sreg_f32: // CHECK: @APP // CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} @@ -188,52 +210,72 @@ check!(sreg_ptr ptr sreg "vmov.f32"); // CHECK: @NO_APP check!(sreg_low16_i32 i32 sreg_low16 "vmov.f32"); -// CHECK-LABEL: sreg_low16_f32: +// CHECK-LABEL: sreg_low16_f16: // CHECK: @APP // CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} // CHECK: @NO_APP -check!(sreg_low16_f32 f32 sreg_low16 "vmov.f32"); +check!(sreg_low16_f16 f16 sreg_low16 "vmov.f32"); -// CHECK-LABEL: dreg_i64: +// CHECK-LABEL: sreg_low16_f32: // CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} // CHECK: @NO_APP +check!(sreg_low16_f32 f32 sreg_low16 "vmov.f32"); + +// d32-LABEL: dreg_i64: +// d32: @APP +// d32: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// d32: @NO_APP +#[cfg(d32)] check!(dreg_i64 i64 dreg "vmov.f64"); -// CHECK-LABEL: dreg_f64: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// d32-LABEL: dreg_f64: +// d32: @APP +// d32: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// d32: @NO_APP +#[cfg(d32)] check!(dreg_f64 f64 dreg "vmov.f64"); -// CHECK-LABEL: dreg_i8x8: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_i8x8: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_i8x8 i8x8 dreg "vmov.f64"); -// CHECK-LABEL: dreg_i16x4: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_i16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_i16x4 i16x4 dreg "vmov.f64"); -// CHECK-LABEL: dreg_i32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_i32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_i32x2 i32x2 dreg "vmov.f64"); -// CHECK-LABEL: dreg_i64x1: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_i64x1: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_i64x1 i64x1 dreg "vmov.f64"); -// CHECK-LABEL: dreg_f32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_f16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(dreg_f16x4 f16x4 dreg "vmov.f64"); + +// neon-LABEL: dreg_f32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_f32x2 f32x2 dreg "vmov.f64"); // CHECK-LABEL: dreg_low16_i64: @@ -248,34 +290,46 @@ check!(dreg_low16_i64 i64 dreg_low16 "vmov.f64"); // CHECK: @NO_APP check!(dreg_low16_f64 f64 dreg_low16 "vmov.f64"); -// CHECK-LABEL: dreg_low16_i8x8: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low16_i8x8: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low16_i8x8 i8x8 dreg_low16 "vmov.f64"); -// CHECK-LABEL: dreg_low16_i16x4: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low16_i16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low16_i16x4 i16x4 dreg_low16 "vmov.f64"); -// CHECK-LABEL: dreg_low16_i32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low16_i32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low16_i32x2 i32x2 dreg_low16 "vmov.f64"); -// CHECK-LABEL: dreg_low16_i64x1: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low16_i64x1: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low16_i64x1 i64x1 dreg_low16 "vmov.f64"); -// CHECK-LABEL: dreg_low16_f32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low16_f16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(dreg_low16_f16x4 f16x4 dreg_low16 "vmov.f64"); + +// neon-LABEL: dreg_low16_f32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low16_f32x2 f32x2 dreg_low16 "vmov.f64"); // CHECK-LABEL: dreg_low8_i64: @@ -290,124 +344,172 @@ check!(dreg_low8_i64 i64 dreg_low8 "vmov.f64"); // CHECK: @NO_APP check!(dreg_low8_f64 f64 dreg_low8 "vmov.f64"); -// CHECK-LABEL: dreg_low8_i8x8: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low8_i8x8: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low8_i8x8 i8x8 dreg_low8 "vmov.f64"); -// CHECK-LABEL: dreg_low8_i16x4: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low8_i16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low8_i16x4 i16x4 dreg_low8 "vmov.f64"); -// CHECK-LABEL: dreg_low8_i32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low8_i32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low8_i32x2 i32x2 dreg_low8 "vmov.f64"); -// CHECK-LABEL: dreg_low8_i64x1: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low8_i64x1: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low8_i64x1 i64x1 dreg_low8 "vmov.f64"); -// CHECK-LABEL: dreg_low8_f32x2: -// CHECK: @APP -// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: dreg_low8_f16x4: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(dreg_low8_f16x4 f16x4 dreg_low8 "vmov.f64"); + +// neon-LABEL: dreg_low8_f32x2: +// neon: @APP +// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(dreg_low8_f32x2 f32x2 dreg_low8 "vmov.f64"); -// CHECK-LABEL: qreg_i8x16: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_i8x16: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_i8x16 i8x16 qreg "vmov"); -// CHECK-LABEL: qreg_i16x8: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_i16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_i16x8 i16x8 qreg "vmov"); -// CHECK-LABEL: qreg_i32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_i32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_i32x4 i32x4 qreg "vmov"); -// CHECK-LABEL: qreg_i64x2: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_i64x2: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_i64x2 i64x2 qreg "vmov"); -// CHECK-LABEL: qreg_f32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_f16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(qreg_f16x8 f16x8 qreg "vmov"); + +// neon-LABEL: qreg_f32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_f32x4 f32x4 qreg "vmov"); -// CHECK-LABEL: qreg_low8_i8x16: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low8_i8x16: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low8_i8x16 i8x16 qreg_low8 "vmov"); -// CHECK-LABEL: qreg_low8_i16x8: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low8_i16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low8_i16x8 i16x8 qreg_low8 "vmov"); -// CHECK-LABEL: qreg_low8_i32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low8_i32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low8_i32x4 i32x4 qreg_low8 "vmov"); -// CHECK-LABEL: qreg_low8_i64x2: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low8_i64x2: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low8_i64x2 i64x2 qreg_low8 "vmov"); -// CHECK-LABEL: qreg_low8_f32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low8_f16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(qreg_low8_f16x8 f16x8 qreg_low8 "vmov"); + +// neon-LABEL: qreg_low8_f32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low8_f32x4 f32x4 qreg_low8 "vmov"); -// CHECK-LABEL: qreg_low4_i8x16: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low4_i8x16: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low4_i8x16 i8x16 qreg_low4 "vmov"); -// CHECK-LABEL: qreg_low4_i16x8: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low4_i16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low4_i16x8 i16x8 qreg_low4 "vmov"); -// CHECK-LABEL: qreg_low4_i32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low4_i32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low4_i32x4 i32x4 qreg_low4 "vmov"); -// CHECK-LABEL: qreg_low4_i64x2: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low4_i64x2: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low4_i64x2 i64x2 qreg_low4 "vmov"); -// CHECK-LABEL: qreg_low4_f32x4: -// CHECK: @APP -// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} -// CHECK: @NO_APP +// neon-LABEL: qreg_low4_f16x8: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] +check!(qreg_low4_f16x8 f16x8 qreg_low4 "vmov"); + +// neon-LABEL: qreg_low4_f32x4: +// neon: @APP +// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// neon: @NO_APP +#[cfg(neon)] check!(qreg_low4_f32x4 f32x4 qreg_low4 "vmov"); // CHECK-LABEL: r0_i8: @@ -428,6 +530,12 @@ check_reg!(r0_i16 i16 "r0" "mov"); // CHECK: @NO_APP check_reg!(r0_i32 i32 "r0" "mov"); +// CHECK-LABEL: r0_f16: +// CHECK: @APP +// CHECK: mov r0, r0 +// CHECK: @NO_APP +check_reg!(r0_f16 f16 "r0" "mov"); + // CHECK-LABEL: r0_f32: // CHECK: @APP // CHECK: mov r0, r0 @@ -446,6 +554,12 @@ check_reg!(r0_ptr ptr "r0" "mov"); // CHECK: @NO_APP check_reg!(s0_i32 i32 "s0" "vmov.f32"); +// CHECK-LABEL: s0_f16: +// CHECK: @APP +// CHECK: vmov.f32 s0, s0 +// CHECK: @NO_APP +check_reg!(s0_f16 f16 "s0" "vmov.f32"); + // CHECK-LABEL: s0_f32: // CHECK: @APP // CHECK: vmov.f32 s0, s0 @@ -458,74 +572,101 @@ check_reg!(s0_f32 f32 "s0" "vmov.f32"); // CHECK: @NO_APP check_reg!(s0_ptr ptr "s0" "vmov.f32"); -// CHECK-LABEL: d0_i64: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// FIXME(#126797): "d0" should work with `i64` and `f64` even when `d32` is disabled. +// d32-LABEL: d0_i64: +// d32: @APP +// d32: vmov.f64 d0, d0 +// d32: @NO_APP +#[cfg(d32)] check_reg!(d0_i64 i64 "d0" "vmov.f64"); -// CHECK-LABEL: d0_f64: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// d32-LABEL: d0_f64: +// d32: @APP +// d32: vmov.f64 d0, d0 +// d32: @NO_APP +#[cfg(d32)] check_reg!(d0_f64 f64 "d0" "vmov.f64"); -// CHECK-LABEL: d0_i8x8: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// neon-LABEL: d0_i8x8: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(d0_i8x8 i8x8 "d0" "vmov.f64"); -// CHECK-LABEL: d0_i16x4: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// neon-LABEL: d0_i16x4: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(d0_i16x4 i16x4 "d0" "vmov.f64"); -// CHECK-LABEL: d0_i32x2: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// neon-LABEL: d0_i32x2: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(d0_i32x2 i32x2 "d0" "vmov.f64"); -// CHECK-LABEL: d0_i64x1: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// neon-LABEL: d0_i64x1: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(d0_i64x1 i64x1 "d0" "vmov.f64"); -// CHECK-LABEL: d0_f32x2: -// CHECK: @APP -// CHECK: vmov.f64 d0, d0 -// CHECK: @NO_APP +// neon-LABEL: d0_f16x4: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] +check_reg!(d0_f16x4 f16x4 "d0" "vmov.f64"); + +// neon-LABEL: d0_f32x2: +// neon: @APP +// neon: vmov.f64 d0, d0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(d0_f32x2 f32x2 "d0" "vmov.f64"); -// CHECK-LABEL: q0_i8x16: -// CHECK: @APP -// CHECK: vorr q0, q0, q0 -// CHECK: @NO_APP +// neon-LABEL: q0_i8x16: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(q0_i8x16 i8x16 "q0" "vmov"); -// CHECK-LABEL: q0_i16x8: -// CHECK: @APP -// CHECK: vorr q0, q0, q0 -// CHECK: @NO_APP +// neon-LABEL: q0_i16x8: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(q0_i16x8 i16x8 "q0" "vmov"); -// CHECK-LABEL: q0_i32x4: -// CHECK: @APP -// CHECK: vorr q0, q0, q0 -// CHECK: @NO_APP +// neon-LABEL: q0_i32x4: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(q0_i32x4 i32x4 "q0" "vmov"); -// CHECK-LABEL: q0_i64x2: -// CHECK: @APP -// CHECK: vorr q0, q0, q0 -// CHECK: @NO_APP +// neon-LABEL: q0_i64x2: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(q0_i64x2 i64x2 "q0" "vmov"); -// CHECK-LABEL: q0_f32x4: -// CHECK: @APP -// CHECK: vorr q0, q0, q0 -// CHECK: @NO_APP +// neon-LABEL: q0_f16x8: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] +check_reg!(q0_f16x8 f16x8 "q0" "vmov"); + +// neon-LABEL: q0_f32x4: +// neon: @APP +// neon: vorr q0, q0, q0 +// neon: @NO_APP +#[cfg(neon)] check_reg!(q0_f32x4 f32x4 "q0" "vmov"); diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs index 0d1f8305d37..51b3aaf99d9 100644 --- a/tests/assembly/asm/riscv-types.rs +++ b/tests/assembly/asm/riscv-types.rs @@ -1,12 +1,34 @@ -//@ revisions: riscv64 riscv32 +//@ revisions: riscv64 riscv32 riscv64-zfhmin riscv32-zfhmin riscv64-zfh riscv32-zfh //@ assembly-output: emit-asm + //@[riscv64] compile-flags: --target riscv64imac-unknown-none-elf //@[riscv64] needs-llvm-components: riscv + //@[riscv32] compile-flags: --target riscv32imac-unknown-none-elf //@[riscv32] needs-llvm-components: riscv + +//@[riscv64-zfhmin] compile-flags: --target riscv64imac-unknown-none-elf --cfg riscv64 +//@[riscv64-zfhmin] needs-llvm-components: riscv +//@[riscv64-zfhmin] compile-flags: -C target-feature=+zfhmin +//@[riscv64-zfhmin] filecheck-flags: --check-prefix riscv64 + +//@[riscv32-zfhmin] compile-flags: --target riscv32imac-unknown-none-elf +//@[riscv32-zfhmin] needs-llvm-components: riscv +//@[riscv32-zfhmin] compile-flags: -C target-feature=+zfhmin + +//@[riscv64-zfh] compile-flags: --target riscv64imac-unknown-none-elf --cfg riscv64 +//@[riscv64-zfh] needs-llvm-components: riscv +//@[riscv64-zfh] compile-flags: -C target-feature=+zfh +//@[riscv64-zfh] filecheck-flags: --check-prefix riscv64 --check-prefix zfhmin + +//@[riscv32-zfh] compile-flags: --target riscv32imac-unknown-none-elf +//@[riscv32-zfh] needs-llvm-components: riscv +//@[riscv32-zfh] compile-flags: -C target-feature=+zfh +//@[riscv32-zfh] filecheck-flags: --check-prefix zfhmin + //@ compile-flags: -C target-feature=+d -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, f16)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] @@ -33,6 +55,7 @@ type ptr = *mut u8; impl Copy for i8 {} impl Copy for i16 {} +impl Copy for f16 {} impl Copy for i32 {} impl Copy for f32 {} impl Copy for i64 {} @@ -103,6 +126,12 @@ macro_rules! check_reg { // CHECK: #NO_APP check!(reg_i8 i8 reg "mv"); +// CHECK-LABEL: reg_f16: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_f16 f16 reg "mv"); + // CHECK-LABEL: reg_i16: // CHECK: #APP // CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} @@ -141,6 +170,14 @@ check!(reg_f64 f64 reg "mv"); // CHECK: #NO_APP check!(reg_ptr ptr reg "mv"); +// CHECK-LABEL: freg_f16: +// zfhmin-NOT: or +// CHECK: #APP +// CHECK: fmv.s f{{[a-z0-9]+}}, f{{[a-z0-9]+}} +// CHECK: #NO_APP +// zfhmin-NOT: or +check!(freg_f16 f16 freg "fmv.s"); + // CHECK-LABEL: freg_f32: // CHECK: #APP // CHECK: fmv.s f{{[a-z0-9]+}}, f{{[a-z0-9]+}} @@ -165,6 +202,12 @@ check_reg!(a0_i8 i8 "a0" "mv"); // CHECK: #NO_APP check_reg!(a0_i16 i16 "a0" "mv"); +// CHECK-LABEL: a0_f16: +// CHECK: #APP +// CHECK: mv a0, a0 +// CHECK: #NO_APP +check_reg!(a0_f16 f16 "a0" "mv"); + // CHECK-LABEL: a0_i32: // CHECK: #APP // CHECK: mv a0, a0 @@ -197,6 +240,14 @@ check_reg!(a0_f64 f64 "a0" "mv"); // CHECK: #NO_APP check_reg!(a0_ptr ptr "a0" "mv"); +// CHECK-LABEL: fa0_f16: +// zfhmin-NOT: or +// CHECK: #APP +// CHECK: fmv.s fa0, fa0 +// CHECK: #NO_APP +// zfhmin-NOT: or +check_reg!(fa0_f16 f16 "fa0" "fmv.s"); + // CHECK-LABEL: fa0_f32: // CHECK: #APP // CHECK: fmv.s fa0, fa0 diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 21fad22f58f..156947f4e21 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -22,19 +22,19 @@ Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro::main::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) -- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(2), rhs = Zero Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) -- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) - = (c1 + (c2 + c3)) + = (c1 + (c2 + Zero)) diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index f2efd550591..0f2b4e01748 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -30,19 +30,19 @@ Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) -- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(2), rhs = Zero Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 18, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) -- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) - = (c1 + (c2 + c3)) + = (c1 + (c2 + Zero)) diff --git a/tests/crashes/120503.rs b/tests/crashes/120503.rs deleted file mode 100644 index 28f1e3dfd94..00000000000 --- a/tests/crashes/120503.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #120503 -#![feature(effects)] - -trait MyTrait {} - -impl MyTrait for i32 { - async const fn bar(&self) { - main8().await; - } -} diff --git a/tests/crashes/121536.rs b/tests/crashes/121536.rs deleted file mode 100644 index 000e7cb15eb..00000000000 --- a/tests/crashes/121536.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #121536 -#![feature(effects)] - -#[derive(Debug, Clone, Copy)] -pub struct Vec3 { - pub x: f32, - pub y: f32, - pub z: f32, -} - -impl std::ops::Add<Vec3> for Vec3 { - type Output = Vec3; - const fn add(self, b: Vec3) -> Self::Output { - Vec3 { - x: self.x + b.x, - y: self.y + b.y, - z: self.z + b.z, - } - } -} diff --git a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff new file mode 100644 index 00000000000..757ab959813 --- /dev/null +++ b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-abort.diff @@ -0,0 +1,134 @@ +- // MIR for `cast_pointer_eq` before GVN ++ // MIR for `cast_pointer_eq` after GVN + + fn cast_pointer_eq(_1: *mut u8, _2: *mut u32, _3: *mut u32, _4: *mut [u32]) -> () { + debug p1 => _1; + debug p2 => _2; + debug p3 => _3; + debug p4 => _4; + let mut _0: (); + let _5: *const u32; + let mut _6: *mut u8; + let mut _8: *const u32; + let mut _9: *mut u32; + let mut _11: *const u32; + let mut _12: *mut u32; + let mut _14: *mut [u32]; + let mut _16: *const u32; + let mut _17: *const u32; + let mut _19: *const u32; + let mut _20: *const u32; + let mut _22: *const u32; + let mut _23: *const u32; + scope 1 { + debug m1 => _5; + let _7: *const u32; + scope 2 { + debug m2 => _7; + let _10: *const u32; + scope 3 { + debug m3 => _10; + let _13: *const u32; + scope 4 { + debug m4 => _13; + let _15: bool; + scope 5 { + debug eq_different_thing => _15; + let _18: bool; + scope 6 { + debug eq_optimize => _18; + let _21: bool; + scope 7 { + debug eq_thin_fat => _21; + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_5); ++ nop; + StorageLive(_6); + _6 = _1; +- _5 = move _6 as *const u32 (PtrToPtr); ++ _5 = _1 as *const u32 (PtrToPtr); + StorageDead(_6); + StorageLive(_7); +- StorageLive(_8); ++ nop; + StorageLive(_9); + _9 = _2; +- _8 = move _9 as *const u32 (PtrToPtr); ++ _8 = _2 as *const u32 (PtrToPtr); + StorageDead(_9); +- _7 = move _8 as *const u32 (PtrToPtr); +- StorageDead(_8); ++ _7 = _8; ++ nop; + StorageLive(_10); +- StorageLive(_11); ++ nop; + StorageLive(_12); + _12 = _3; +- _11 = move _12 as *const u32 (PtrToPtr); ++ _11 = _3 as *const u32 (PtrToPtr); + StorageDead(_12); +- _10 = move _11 as *const u32 (PtrToPtr); +- StorageDead(_11); +- StorageLive(_13); ++ _10 = _11; ++ nop; ++ nop; + StorageLive(_14); + _14 = _4; +- _13 = move _14 as *const u32 (PtrToPtr); ++ _13 = _4 as *const u32 (PtrToPtr); + StorageDead(_14); + StorageLive(_15); + StorageLive(_16); + _16 = _5; + StorageLive(_17); +- _17 = _7; +- _15 = Eq(move _16, move _17); ++ _17 = _8; ++ _15 = Eq(_5, _8); + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + StorageLive(_19); +- _19 = _7; ++ _19 = _8; + StorageLive(_20); +- _20 = _10; +- _18 = Eq(move _19, move _20); ++ _20 = _11; ++ _18 = Eq(_2, _3); + StorageDead(_20); + StorageDead(_19); + StorageLive(_21); + StorageLive(_22); +- _22 = _10; ++ _22 = _11; + StorageLive(_23); + _23 = _13; +- _21 = Eq(move _22, move _23); ++ _21 = Eq(_11, _13); + StorageDead(_23); + StorageDead(_22); + _0 = const (); + StorageDead(_21); + StorageDead(_18); + StorageDead(_15); +- StorageDead(_13); ++ nop; + StorageDead(_10); + StorageDead(_7); +- StorageDead(_5); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff new file mode 100644 index 00000000000..757ab959813 --- /dev/null +++ b/tests/mir-opt/gvn.cast_pointer_eq.GVN.panic-unwind.diff @@ -0,0 +1,134 @@ +- // MIR for `cast_pointer_eq` before GVN ++ // MIR for `cast_pointer_eq` after GVN + + fn cast_pointer_eq(_1: *mut u8, _2: *mut u32, _3: *mut u32, _4: *mut [u32]) -> () { + debug p1 => _1; + debug p2 => _2; + debug p3 => _3; + debug p4 => _4; + let mut _0: (); + let _5: *const u32; + let mut _6: *mut u8; + let mut _8: *const u32; + let mut _9: *mut u32; + let mut _11: *const u32; + let mut _12: *mut u32; + let mut _14: *mut [u32]; + let mut _16: *const u32; + let mut _17: *const u32; + let mut _19: *const u32; + let mut _20: *const u32; + let mut _22: *const u32; + let mut _23: *const u32; + scope 1 { + debug m1 => _5; + let _7: *const u32; + scope 2 { + debug m2 => _7; + let _10: *const u32; + scope 3 { + debug m3 => _10; + let _13: *const u32; + scope 4 { + debug m4 => _13; + let _15: bool; + scope 5 { + debug eq_different_thing => _15; + let _18: bool; + scope 6 { + debug eq_optimize => _18; + let _21: bool; + scope 7 { + debug eq_thin_fat => _21; + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_5); ++ nop; + StorageLive(_6); + _6 = _1; +- _5 = move _6 as *const u32 (PtrToPtr); ++ _5 = _1 as *const u32 (PtrToPtr); + StorageDead(_6); + StorageLive(_7); +- StorageLive(_8); ++ nop; + StorageLive(_9); + _9 = _2; +- _8 = move _9 as *const u32 (PtrToPtr); ++ _8 = _2 as *const u32 (PtrToPtr); + StorageDead(_9); +- _7 = move _8 as *const u32 (PtrToPtr); +- StorageDead(_8); ++ _7 = _8; ++ nop; + StorageLive(_10); +- StorageLive(_11); ++ nop; + StorageLive(_12); + _12 = _3; +- _11 = move _12 as *const u32 (PtrToPtr); ++ _11 = _3 as *const u32 (PtrToPtr); + StorageDead(_12); +- _10 = move _11 as *const u32 (PtrToPtr); +- StorageDead(_11); +- StorageLive(_13); ++ _10 = _11; ++ nop; ++ nop; + StorageLive(_14); + _14 = _4; +- _13 = move _14 as *const u32 (PtrToPtr); ++ _13 = _4 as *const u32 (PtrToPtr); + StorageDead(_14); + StorageLive(_15); + StorageLive(_16); + _16 = _5; + StorageLive(_17); +- _17 = _7; +- _15 = Eq(move _16, move _17); ++ _17 = _8; ++ _15 = Eq(_5, _8); + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + StorageLive(_19); +- _19 = _7; ++ _19 = _8; + StorageLive(_20); +- _20 = _10; +- _18 = Eq(move _19, move _20); ++ _20 = _11; ++ _18 = Eq(_2, _3); + StorageDead(_20); + StorageDead(_19); + StorageLive(_21); + StorageLive(_22); +- _22 = _10; ++ _22 = _11; + StorageLive(_23); + _23 = _13; +- _21 = Eq(move _22, move _23); ++ _21 = Eq(_11, _13); + StorageDead(_23); + StorageDead(_22); + _0 = const (); + StorageDead(_21); + StorageDead(_18); + StorageDead(_15); +- StorageDead(_13); ++ nop; + StorageDead(_10); + StorageDead(_7); +- StorageDead(_5); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff new file mode 100644 index 00000000000..8133f6e0b00 --- /dev/null +++ b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-abort.diff @@ -0,0 +1,47 @@ +- // MIR for `cast_pointer_then_transmute` before GVN ++ // MIR for `cast_pointer_then_transmute` after GVN + + fn cast_pointer_then_transmute(_1: *mut u32, _2: *mut [u8]) -> () { + debug thin => _1; + debug fat => _2; + let mut _0: (); + let _3: usize; + let mut _4: *const (); + let mut _5: *mut u32; + let mut _7: *const (); + let mut _8: *mut [u8]; + scope 1 { + debug thin_addr => _3; + let _6: usize; + scope 2 { + debug fat_addr => _6; + } + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = move _5 as *const () (PtrToPtr); ++ _4 = _1 as *const () (PtrToPtr); + StorageDead(_5); +- _3 = move _4 as usize (Transmute); ++ _3 = _1 as usize (Transmute); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + _8 = _2; +- _7 = move _8 as *const () (PtrToPtr); ++ _7 = _2 as *const () (PtrToPtr); + StorageDead(_8); + _6 = move _7 as usize (Transmute); + StorageDead(_7); + _0 = const (); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff new file mode 100644 index 00000000000..8133f6e0b00 --- /dev/null +++ b/tests/mir-opt/gvn.cast_pointer_then_transmute.GVN.panic-unwind.diff @@ -0,0 +1,47 @@ +- // MIR for `cast_pointer_then_transmute` before GVN ++ // MIR for `cast_pointer_then_transmute` after GVN + + fn cast_pointer_then_transmute(_1: *mut u32, _2: *mut [u8]) -> () { + debug thin => _1; + debug fat => _2; + let mut _0: (); + let _3: usize; + let mut _4: *const (); + let mut _5: *mut u32; + let mut _7: *const (); + let mut _8: *mut [u8]; + scope 1 { + debug thin_addr => _3; + let _6: usize; + scope 2 { + debug fat_addr => _6; + } + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = move _5 as *const () (PtrToPtr); ++ _4 = _1 as *const () (PtrToPtr); + StorageDead(_5); +- _3 = move _4 as usize (Transmute); ++ _3 = _1 as usize (Transmute); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + _8 = _2; +- _7 = move _8 as *const () (PtrToPtr); ++ _7 = _2 as *const () (PtrToPtr); + StorageDead(_8); + _6 = move _7 as usize (Transmute); + StorageDead(_7); + _0 = const (); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 8bc2550b8f5..86f42d23f38 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -883,6 +883,49 @@ fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A, } } +fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) { + // CHECK-LABEL: fn cast_pointer_eq + // CHECK: debug p1 => [[P1:_1]]; + // CHECK: debug p2 => [[P2:_2]]; + // CHECK: debug p3 => [[P3:_3]]; + // CHECK: debug p4 => [[P4:_4]]; + + // CHECK: [[M1:_.+]] = [[P1]] as *const u32 (PtrToPtr); + // CHECK: [[M2:_.+]] = [[P2]] as *const u32 (PtrToPtr); + // CHECK: [[M3:_.+]] = [[P3]] as *const u32 (PtrToPtr); + // CHECK: [[M4:_.+]] = [[P4]] as *const u32 (PtrToPtr); + let m1 = p1 as *const u32; + let m2 = p2 as *const u32; + let m3 = p3 as *const u32; + let m4 = p4 as *const u32; + + // CHECK-NOT: Eq + // CHECK: Eq([[M1]], [[M2]]) + // CHECK-NOT: Eq + // CHECK: Eq([[P2]], [[P3]]) + // CHECK-NOT: Eq + // CHECK: Eq([[M3]], [[M4]]) + // CHECK-NOT: Eq + let eq_different_thing = m1 == m2; + let eq_optimize = m2 == m3; + let eq_thin_fat = m3 == m4; + + // CHECK: _0 = const (); +} + +// Transmuting can skip a pointer cast so long as it wasn't a fat-to-thin cast. +unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) { + // CHECK-LABEL: fn cast_pointer_then_transmute + + // CHECK: [[UNUSED:_.+]] = _1 as *const () (PtrToPtr); + // CHECK: = _1 as usize (Transmute); + let thin_addr: usize = std::intrinsics::transmute(thin as *const ()); + + // CHECK: [[TEMP2:_.+]] = _2 as *const () (PtrToPtr); + // CHECK: = move [[TEMP2]] as usize (Transmute); + let fat_addr: usize = std::intrinsics::transmute(fat as *const ()); +} + fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); @@ -950,3 +993,5 @@ fn identity<T>(x: T) -> T { // EMIT_MIR gvn.manual_slice_mut_len.GVN.diff // EMIT_MIR gvn.array_len.GVN.diff // EMIT_MIR gvn.generic_cast_metadata.GVN.diff +// EMIT_MIR gvn.cast_pointer_eq.GVN.diff +// EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff index 6c0c7a1d438..7aca2cb0007 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff @@ -15,10 +15,12 @@ let mut _10: bool; bb0: { - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_4); _4 = _1; - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -32,12 +34,14 @@ bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -+ _3 = Lt(_1, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(_1, const N); ++ switchInt(_3) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_8); _8 = _1; @@ -45,8 +49,8 @@ - _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable]; + _9 = const N; -+ _10 = Lt(_1, const N); -+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; ++ _10 = _3; ++ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; } bb3: { @@ -57,14 +61,16 @@ } bb4: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); _0 = const 42_u8; goto -> bb5; } bb5: { - StorageDead(_3); +- StorageDead(_3); ++ nop; return; } } diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff index ed41703c873..ed39c11319a 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff @@ -15,10 +15,12 @@ let mut _10: bool; bb0: { - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_4); _4 = _1; - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -32,12 +34,14 @@ bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -+ _3 = Lt(_1, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(_1, const N); ++ switchInt(_3) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_8); _8 = _1; @@ -45,8 +49,8 @@ - _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; + _9 = const N; -+ _10 = Lt(_1, const N); -+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; ++ _10 = _3; ++ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; } bb3: { @@ -57,14 +61,16 @@ } bb4: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); _0 = const 42_u8; goto -> bb5; } bb5: { - StorageDead(_3); +- StorageDead(_3); ++ nop; return; } } diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff index 80e8ea37f41..734d28e9546 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff @@ -18,10 +18,12 @@ let mut _13: bool; bb0: { - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_4); _4 = _1; - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -35,12 +37,14 @@ bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -+ _3 = Lt(_1, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(_1, const N); ++ switchInt(_3) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_8); _8 = _1; @@ -48,8 +52,8 @@ - _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable]; + _9 = const N; -+ _10 = Lt(_1, const N); -+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; ++ _10 = _3; ++ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable]; } bb3: { @@ -60,7 +64,8 @@ } bb4: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_11); _11 = const 0_usize; @@ -81,7 +86,8 @@ } bb6: { - StorageDead(_3); +- StorageDead(_3); ++ nop; return; } } diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff index 6e67a6c17ef..ec569ab5042 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff @@ -18,10 +18,12 @@ let mut _13: bool; bb0: { - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_4); _4 = _1; - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -35,12 +37,14 @@ bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -+ _3 = Lt(_1, move _5); - switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb4, otherwise: bb2]; ++ _3 = Lt(_1, const N); ++ switchInt(_3) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_8); _8 = _1; @@ -48,8 +52,8 @@ - _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; + _9 = const N; -+ _10 = Lt(_1, const N); -+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; ++ _10 = _3; ++ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue]; } bb3: { @@ -60,7 +64,8 @@ } bb4: { - StorageDead(_5); +- StorageDead(_5); ++ nop; StorageDead(_4); StorageLive(_11); _11 = const 0_usize; @@ -81,7 +86,8 @@ } bb6: { - StorageDead(_3); +- StorageDead(_3); ++ nop; return; } } diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs index caa598d067a..f7ed376726c 100644 --- a/tests/mir-opt/lower_array_len.rs +++ b/tests/mir-opt/lower_array_len.rs @@ -5,16 +5,20 @@ // EMIT_MIR lower_array_len.array_bound.GVN.diff pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 { // CHECK-LABEL: fn array_bound( - // CHECK: [[len:_.*]] = const N; - // CHECK: Lt(_1, move [[len]]); + // CHECK-NOT: Lt + // CHECK: Lt(_1, const N); + // CHECK-NOT: Lt if index < slice.len() { slice[index] } else { 42 } } // EMIT_MIR lower_array_len.array_bound_mut.GVN.diff pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 { // CHECK-LABEL: fn array_bound_mut( - // CHECK: [[len:_.*]] = const N; - // CHECK: Lt(_1, move [[len]]); + // CHECK-NOT: Lt + // CHECK: Lt(_1, const N); + // CHECK-NOT: Lt + // CHECK: Lt(const 0_usize, const N) + // CHECK-NOT: Lt if index < slice.len() { slice[index] } else { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index fbb887fe76a..79c5bcfe9cd 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -7,19 +7,90 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _11: std::slice::Iter<'_, T>; let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>; let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _37: std::option::Option<&T>; + let mut _39: &impl Fn(&T); + let mut _40: (&T,); + let _41: (); scope 1 { debug iter => _13; - let _17: &T; + let _38: &T; scope 2 { - debug x => _17; + debug x => _38; } scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + scope 18 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) { + let mut _14: *const *const T; + let mut _15: *const std::ptr::NonNull<T>; + let mut _20: bool; + let mut _21: *const T; + let _36: &T; + scope 19 { + let _16: std::ptr::NonNull<T>; + let _22: usize; + scope 20 { + } + scope 21 { + scope 25 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _17: std::ptr::NonNull<T>; + scope 26 (inlined NonNull::<T>::as_ptr) { + let mut _18: *const T; + } + scope 27 (inlined NonNull::<T>::as_ptr) { + let mut _19: *const T; + } + } + } + scope 22 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 23 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + scope 24 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) { + } + } + scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { + let _29: std::ptr::NonNull<T>; + scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { + let mut _23: *mut *const T; + let mut _24: *mut std::ptr::NonNull<T>; + let mut _25: std::ptr::NonNull<T>; + let mut _28: std::ptr::NonNull<T>; + let mut _30: *mut *const T; + let mut _31: *mut usize; + let mut _32: usize; + let mut _33: usize; + scope 30 { + scope 31 { + } + scope 32 { + scope 35 (inlined NonNull::<T>::sub) { + scope 36 (inlined core::num::<impl isize>::unchecked_neg) { + scope 37 (inlined core::ub_checks::check_language_ub) { + scope 38 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 39 (inlined NonNull::<T>::offset) { + let mut _26: *const T; + let mut _27: *const T; + } + } + } + scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) { + } + scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) { + } + } + } + scope 40 (inlined NonNull::<T>::as_ref::<'_>) { + let mut _34: std::ptr::NonNull<T>; + scope 41 (inlined NonNull::<T>::as_ptr) { + let mut _35: *const T; + } + scope 42 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) { + } + } + } + } } } scope 3 (inlined core::slice::<impl [T]>::iter) { @@ -107,45 +178,147 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { - StorageLive(_15); - StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable]; + StorageLive(_37); + StorageLive(_22); + StorageLive(_21); + StorageLive(_16); + StorageLive(_36); + StorageLive(_20); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6]; } bb5: { + StorageLive(_15); + StorageLive(_14); + _14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _15 = _14 as *const std::ptr::NonNull<T> (PtrToPtr); StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + _16 = (*_15); + StorageDead(_15); + StorageLive(_18); + StorageLive(_19); + StorageLive(_17); + _17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + _18 = (_17.0: *const T); + StorageDead(_17); + _19 = (_16.0: *const T); + _20 = Eq(_18, _19); + StorageDead(_19); + StorageDead(_18); + goto -> bb7; } bb6: { - StorageDead(_15); - StorageDead(_13); - drop(_2) -> [return: bb7, unwind unreachable]; + _21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _22 = _21 as usize (Transmute); + _20 = Eq(_22, const 0_usize); + goto -> bb7; } bb7: { - return; + switchInt(move _20) -> [0: bb8, otherwise: bb16]; } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (_17,); - _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable]; + StorageLive(_35); + StorageLive(_29); + StorageLive(_31); + StorageLive(_24); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb13]; } bb9: { - StorageDead(_19); - StorageDead(_18); - StorageDead(_15); - goto -> bb4; + StorageLive(_23); + _23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _24 = _23 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_23); + StorageLive(_28); + _25 = (*_24); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11]; } bb10: { - unreachable; + StorageLive(_27); + StorageLive(_26); + _26 = (_25.0: *const T); + _27 = Offset(move _26, const -1_isize); + StorageDead(_26); + _28 = NonNull::<T> { pointer: move _27 }; + StorageDead(_27); + goto -> bb12; + } + + bb11: { + _28 = _25; + goto -> bb12; + } + + bb12: { + (*_24) = move _28; + StorageDead(_28); + _29 = (*_24); + goto -> bb14; + } + + bb13: { + StorageLive(_30); + _30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _31 = _30 as *mut usize (PtrToPtr); + StorageDead(_30); + StorageLive(_33); + StorageLive(_32); + _32 = (*_31); + _33 = SubUnchecked(move _32, const 1_usize); + StorageDead(_32); + (*_31) = move _33; + StorageDead(_33); + _29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + goto -> bb14; + } + + bb14: { + StorageDead(_24); + StorageDead(_31); + StorageLive(_34); + _34 = _29; + _35 = (_34.0: *const T); + StorageDead(_34); + _36 = &(*_35); + StorageDead(_29); + StorageDead(_35); + _37 = Option::<&T>::Some(_36); + StorageDead(_20); + StorageDead(_36); + StorageDead(_16); + StorageDead(_21); + StorageDead(_22); + _38 = ((_37 as Some).0: &T); + StorageLive(_39); + _39 = &_2; + StorageLive(_40); + _40 = (_38,); + _41 = <impl Fn(&T) as Fn<(&T,)>>::call(move _39, move _40) -> [return: bb15, unwind unreachable]; + } + + bb15: { + StorageDead(_40); + StorageDead(_39); + StorageDead(_37); + goto -> bb4; + } + + bb16: { + StorageDead(_20); + StorageDead(_36); + StorageDead(_16); + StorageDead(_21); + StorageDead(_22); + StorageDead(_37); + StorageDead(_13); + drop(_2) -> [return: bb17, unwind unreachable]; + } + + bb17: { + return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index db9409f72ab..7c107a23f9e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -7,19 +7,90 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _11: std::slice::Iter<'_, T>; let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>; let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _37: std::option::Option<&T>; + let mut _39: &impl Fn(&T); + let mut _40: (&T,); + let _41: (); scope 1 { debug iter => _13; - let _17: &T; + let _38: &T; scope 2 { - debug x => _17; + debug x => _38; } scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + scope 18 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) { + let mut _14: *const *const T; + let mut _15: *const std::ptr::NonNull<T>; + let mut _20: bool; + let mut _21: *const T; + let _36: &T; + scope 19 { + let _16: std::ptr::NonNull<T>; + let _22: usize; + scope 20 { + } + scope 21 { + scope 25 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _17: std::ptr::NonNull<T>; + scope 26 (inlined NonNull::<T>::as_ptr) { + let mut _18: *const T; + } + scope 27 (inlined NonNull::<T>::as_ptr) { + let mut _19: *const T; + } + } + } + scope 22 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 23 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + scope 24 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) { + } + } + scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { + let _29: std::ptr::NonNull<T>; + scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { + let mut _23: *mut *const T; + let mut _24: *mut std::ptr::NonNull<T>; + let mut _25: std::ptr::NonNull<T>; + let mut _28: std::ptr::NonNull<T>; + let mut _30: *mut *const T; + let mut _31: *mut usize; + let mut _32: usize; + let mut _33: usize; + scope 30 { + scope 31 { + } + scope 32 { + scope 35 (inlined NonNull::<T>::sub) { + scope 36 (inlined core::num::<impl isize>::unchecked_neg) { + scope 37 (inlined core::ub_checks::check_language_ub) { + scope 38 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 39 (inlined NonNull::<T>::offset) { + let mut _26: *const T; + let mut _27: *const T; + } + } + } + scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) { + } + scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) { + } + } + } + scope 40 (inlined NonNull::<T>::as_ref::<'_>) { + let mut _34: std::ptr::NonNull<T>; + scope 41 (inlined NonNull::<T>::as_ptr) { + let mut _35: *const T; + } + scope 42 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) { + } + } + } + } } } scope 3 (inlined core::slice::<impl [T]>::iter) { @@ -107,53 +178,155 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { - StorageLive(_15); - StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11]; + StorageLive(_37); + StorageLive(_22); + StorageLive(_21); + StorageLive(_16); + StorageLive(_36); + StorageLive(_20); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6]; } bb5: { + StorageLive(_15); + StorageLive(_14); + _14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _15 = _14 as *const std::ptr::NonNull<T> (PtrToPtr); StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + _16 = (*_15); + StorageDead(_15); + StorageLive(_18); + StorageLive(_19); + StorageLive(_17); + _17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + _18 = (_17.0: *const T); + StorageDead(_17); + _19 = (_16.0: *const T); + _20 = Eq(_18, _19); + StorageDead(_19); + StorageDead(_18); + goto -> bb7; } bb6: { - StorageDead(_15); - StorageDead(_13); - drop(_2) -> [return: bb7, unwind continue]; + _21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _22 = _21 as usize (Transmute); + _20 = Eq(_22, const 0_usize); + goto -> bb7; } bb7: { - return; + switchInt(move _20) -> [0: bb8, otherwise: bb18]; } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (_17,); - _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + StorageLive(_35); + StorageLive(_29); + StorageLive(_31); + StorageLive(_24); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb13]; } bb9: { - StorageDead(_19); - StorageDead(_18); - StorageDead(_15); - goto -> bb4; + StorageLive(_23); + _23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _24 = _23 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_23); + StorageLive(_28); + _25 = (*_24); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11]; } bb10: { - unreachable; + StorageLive(_27); + StorageLive(_26); + _26 = (_25.0: *const T); + _27 = Offset(move _26, const -1_isize); + StorageDead(_26); + _28 = NonNull::<T> { pointer: move _27 }; + StorageDead(_27); + goto -> bb12; + } + + bb11: { + _28 = _25; + goto -> bb12; + } + + bb12: { + (*_24) = move _28; + StorageDead(_28); + _29 = (*_24); + goto -> bb14; + } + + bb13: { + StorageLive(_30); + _30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T); + _31 = _30 as *mut usize (PtrToPtr); + StorageDead(_30); + StorageLive(_33); + StorageLive(_32); + _32 = (*_31); + _33 = SubUnchecked(move _32, const 1_usize); + StorageDead(_32); + (*_31) = move _33; + StorageDead(_33); + _29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + goto -> bb14; } - bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate(cleanup)]; + bb14: { + StorageDead(_24); + StorageDead(_31); + StorageLive(_34); + _34 = _29; + _35 = (_34.0: *const T); + StorageDead(_34); + _36 = &(*_35); + StorageDead(_29); + StorageDead(_35); + _37 = Option::<&T>::Some(_36); + StorageDead(_20); + StorageDead(_36); + StorageDead(_16); + StorageDead(_21); + StorageDead(_22); + _38 = ((_37 as Some).0: &T); + StorageLive(_39); + _39 = &_2; + StorageLive(_40); + _40 = (_38,); + _41 = <impl Fn(&T) as Fn<(&T,)>>::call(move _39, move _40) -> [return: bb15, unwind: bb16]; } - bb12 (cleanup): { + bb15: { + StorageDead(_40); + StorageDead(_39); + StorageDead(_37); + goto -> bb4; + } + + bb16 (cleanup): { + drop(_2) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { resume; } + + bb18: { + StorageDead(_20); + StorageDead(_36); + StorageDead(_16); + StorageDead(_21); + StorageDead(_22); + StorageDead(_37); + StorageDead(_13); + drop(_2) -> [return: bb19, unwind continue]; + } + + bb19: { + return; + } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs index 86f37ca4d13..3f89ab0e6f3 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.rs +++ b/tests/mir-opt/pre-codegen/slice_iter.rs @@ -1,8 +1,10 @@ // skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 +//@ only-64bit (constants for `None::<&T>` show in the output) // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] +#![feature(exact_size_is_empty)] // When this test was added, the MIR for `next` was 174 lines just for the basic // blocks -- far more if you counted the scopes. The goal of having this here @@ -13,6 +15,11 @@ // As such, feel free to `--bless` whatever changes you get here, so long as // doing so doesn't add substantially more MIR. +// EMIT_MIR slice_iter.slice_iter_generic_is_empty.PreCodegen.after.mir +pub fn slice_iter_generic_is_empty<T>(it: &std::slice::Iter<'_, T>) -> bool { + it.is_empty() +} + // EMIT_MIR slice_iter.slice_iter_next.PreCodegen.after.mir pub fn slice_iter_next<'a, T>(it: &mut std::slice::Iter<'a, T>) -> Option<&'a T> { it.next() diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir new file mode 100644 index 00000000000..96e71c298e0 --- /dev/null +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir @@ -0,0 +1,76 @@ +// MIR for `slice_iter_generic_is_empty` after PreCodegen + +fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { + debug it => _1; + let mut _0: bool; + scope 1 (inlined <std::slice::Iter<'_, T> as ExactSizeIterator>::is_empty) { + let mut _2: *const *const T; + let mut _3: *const std::ptr::NonNull<T>; + let mut _8: *const T; + scope 2 { + let _4: std::ptr::NonNull<T>; + let _9: usize; + scope 3 { + } + scope 4 { + scope 8 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _5: std::ptr::NonNull<T>; + scope 9 (inlined NonNull::<T>::as_ptr) { + let mut _6: *const T; + } + scope 10 (inlined NonNull::<T>::as_ptr) { + let mut _7: *const T; + } + } + } + scope 5 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 6 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + scope 7 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) { + } + } + } + + bb0: { + StorageLive(_9); + StorageLive(_8); + StorageLive(_4); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = &raw const ((*_1).1: *const T); + _3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_2); + _4 = (*_3); + StorageDead(_3); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); + _5 = ((*_1).0: std::ptr::NonNull<T>); + _6 = (_5.0: *const T); + StorageDead(_5); + _7 = (_4.0: *const T); + _0 = Eq(_6, _7); + StorageDead(_7); + StorageDead(_6); + goto -> bb3; + } + + bb2: { + _8 = ((*_1).1: *const T); + _9 = _8 as usize (Transmute); + _0 = Eq(_9, const 0_usize); + goto -> bb3; + } + + bb3: { + StorageDead(_4); + StorageDead(_8); + StorageDead(_9); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir new file mode 100644 index 00000000000..96e71c298e0 --- /dev/null +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,76 @@ +// MIR for `slice_iter_generic_is_empty` after PreCodegen + +fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { + debug it => _1; + let mut _0: bool; + scope 1 (inlined <std::slice::Iter<'_, T> as ExactSizeIterator>::is_empty) { + let mut _2: *const *const T; + let mut _3: *const std::ptr::NonNull<T>; + let mut _8: *const T; + scope 2 { + let _4: std::ptr::NonNull<T>; + let _9: usize; + scope 3 { + } + scope 4 { + scope 8 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _5: std::ptr::NonNull<T>; + scope 9 (inlined NonNull::<T>::as_ptr) { + let mut _6: *const T; + } + scope 10 (inlined NonNull::<T>::as_ptr) { + let mut _7: *const T; + } + } + } + scope 5 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 6 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + scope 7 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) { + } + } + } + + bb0: { + StorageLive(_9); + StorageLive(_8); + StorageLive(_4); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = &raw const ((*_1).1: *const T); + _3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_2); + _4 = (*_3); + StorageDead(_3); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); + _5 = ((*_1).0: std::ptr::NonNull<T>); + _6 = (_5.0: *const T); + StorageDead(_5); + _7 = (_4.0: *const T); + _0 = Eq(_6, _7); + StorageDead(_7); + StorageDead(_6); + goto -> bb3; + } + + bb2: { + _8 = ((*_1).1: *const T); + _9 = _8 as usize (Transmute); + _0 = Eq(_9, const 0_usize); + goto -> bb3; + } + + bb3: { + StorageDead(_4); + StorageDead(_8); + StorageDead(_9); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir index 78f96bf4195..2df346c081c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir @@ -3,12 +3,205 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; + scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) { + let mut _2: *const *mut T; + let mut _3: *const std::ptr::NonNull<T>; + let mut _8: bool; + let mut _9: *mut T; + let mut _25: &mut T; + scope 2 { + let _4: std::ptr::NonNull<T>; + let _10: usize; + scope 3 { + } + scope 4 { + scope 8 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _5: std::ptr::NonNull<T>; + scope 9 (inlined NonNull::<T>::as_ptr) { + let mut _6: *const T; + } + scope 10 (inlined NonNull::<T>::as_ptr) { + let mut _7: *const T; + } + } + } + scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) { + scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) { + } + } + scope 7 (inlined std::ptr::const_ptr::<impl *const *mut T>::cast::<NonNull<T>>) { + } + } + scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { + let mut _17: std::ptr::NonNull<T>; + scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { + let mut _11: *mut *mut T; + let mut _12: *mut std::ptr::NonNull<T>; + let mut _13: std::ptr::NonNull<T>; + let mut _16: std::ptr::NonNull<T>; + let mut _18: *mut *mut T; + let mut _19: *mut usize; + let mut _20: usize; + let mut _21: usize; + scope 13 { + scope 14 { + } + scope 15 { + scope 18 (inlined NonNull::<T>::sub) { + scope 19 (inlined core::num::<impl isize>::unchecked_neg) { + scope 20 (inlined core::ub_checks::check_language_ub) { + scope 21 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 22 (inlined NonNull::<T>::offset) { + let mut _14: *const T; + let mut _15: *const T; + } + } + } + scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) { + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) { + } + } + } + scope 23 (inlined NonNull::<T>::as_mut::<'_>) { + let mut _22: std::ptr::NonNull<T>; + let mut _24: *mut T; + scope 24 (inlined NonNull::<T>::as_ptr) { + let mut _23: *const T; + } + } + } + } bb0: { - _0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind unreachable]; + StorageLive(_10); + StorageLive(_9); + StorageLive(_4); + StorageLive(_25); + StorageLive(_8); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = &raw const ((*_1).1: *mut T); + _3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_2); + _4 = (*_3); + StorageDead(_3); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); + _5 = ((*_1).0: std::ptr::NonNull<T>); + _6 = (_5.0: *const T); + StorageDead(_5); + _7 = (_4.0: *const T); + _8 = Eq(_6, _7); + StorageDead(_7); + StorageDead(_6); + goto -> bb3; + } + + bb2: { + _9 = ((*_1).1: *mut T); + _10 = _9 as usize (Transmute); + _8 = Eq(_10, const 0_usize); + goto -> bb3; + } + + bb3: { + switchInt(move _8) -> [0: bb4, otherwise: bb11]; + } + + bb4: { + StorageLive(_24); + StorageLive(_17); + StorageLive(_19); + StorageLive(_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb9]; + } + + bb5: { + StorageLive(_11); + _11 = &raw mut ((*_1).1: *mut T); + _12 = _11 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_11); + StorageLive(_16); + _13 = (*_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageLive(_15); + StorageLive(_14); + _14 = (_13.0: *const T); + _15 = Offset(move _14, const -1_isize); + StorageDead(_14); + _16 = NonNull::<T> { pointer: move _15 }; + StorageDead(_15); + goto -> bb8; + } + + bb7: { + _16 = _13; + goto -> bb8; + } + + bb8: { + (*_12) = move _16; + StorageDead(_16); + _17 = (*_12); + goto -> bb10; + } + + bb9: { + StorageLive(_18); + _18 = &raw mut ((*_1).1: *mut T); + _19 = _18 as *mut usize (PtrToPtr); + StorageDead(_18); + StorageLive(_21); + StorageLive(_20); + _20 = (*_19); + _21 = SubUnchecked(move _20, const 1_usize); + StorageDead(_20); + (*_19) = move _21; + StorageDead(_21); + _17 = ((*_1).0: std::ptr::NonNull<T>); + goto -> bb10; + } + + bb10: { + StorageDead(_12); + StorageDead(_19); + StorageLive(_22); + _22 = _17; + StorageLive(_23); + _23 = (_22.0: *const T); + _24 = move _23 as *mut T (PtrToPtr); + StorageDead(_23); + StorageDead(_22); + _25 = &mut (*_24); + StorageDead(_17); + StorageDead(_24); + _0 = Option::<&mut T>::Some(_25); + goto -> bb12; + } + + bb11: { + _0 = const {transmute(0x0000000000000000): Option<&mut T>}; + goto -> bb12; + } + + bb12: { + StorageDead(_8); + StorageDead(_25); + StorageDead(_4); + StorageDead(_9); + StorageDead(_10); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir index dfe5e206fad..2df346c081c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir @@ -3,12 +3,205 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; + scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) { + let mut _2: *const *mut T; + let mut _3: *const std::ptr::NonNull<T>; + let mut _8: bool; + let mut _9: *mut T; + let mut _25: &mut T; + scope 2 { + let _4: std::ptr::NonNull<T>; + let _10: usize; + scope 3 { + } + scope 4 { + scope 8 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _5: std::ptr::NonNull<T>; + scope 9 (inlined NonNull::<T>::as_ptr) { + let mut _6: *const T; + } + scope 10 (inlined NonNull::<T>::as_ptr) { + let mut _7: *const T; + } + } + } + scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) { + scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) { + } + } + scope 7 (inlined std::ptr::const_ptr::<impl *const *mut T>::cast::<NonNull<T>>) { + } + } + scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { + let mut _17: std::ptr::NonNull<T>; + scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { + let mut _11: *mut *mut T; + let mut _12: *mut std::ptr::NonNull<T>; + let mut _13: std::ptr::NonNull<T>; + let mut _16: std::ptr::NonNull<T>; + let mut _18: *mut *mut T; + let mut _19: *mut usize; + let mut _20: usize; + let mut _21: usize; + scope 13 { + scope 14 { + } + scope 15 { + scope 18 (inlined NonNull::<T>::sub) { + scope 19 (inlined core::num::<impl isize>::unchecked_neg) { + scope 20 (inlined core::ub_checks::check_language_ub) { + scope 21 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 22 (inlined NonNull::<T>::offset) { + let mut _14: *const T; + let mut _15: *const T; + } + } + } + scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) { + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) { + } + } + } + scope 23 (inlined NonNull::<T>::as_mut::<'_>) { + let mut _22: std::ptr::NonNull<T>; + let mut _24: *mut T; + scope 24 (inlined NonNull::<T>::as_ptr) { + let mut _23: *const T; + } + } + } + } bb0: { - _0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind continue]; + StorageLive(_10); + StorageLive(_9); + StorageLive(_4); + StorageLive(_25); + StorageLive(_8); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = &raw const ((*_1).1: *mut T); + _3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_2); + _4 = (*_3); + StorageDead(_3); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); + _5 = ((*_1).0: std::ptr::NonNull<T>); + _6 = (_5.0: *const T); + StorageDead(_5); + _7 = (_4.0: *const T); + _8 = Eq(_6, _7); + StorageDead(_7); + StorageDead(_6); + goto -> bb3; + } + + bb2: { + _9 = ((*_1).1: *mut T); + _10 = _9 as usize (Transmute); + _8 = Eq(_10, const 0_usize); + goto -> bb3; + } + + bb3: { + switchInt(move _8) -> [0: bb4, otherwise: bb11]; + } + + bb4: { + StorageLive(_24); + StorageLive(_17); + StorageLive(_19); + StorageLive(_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb9]; + } + + bb5: { + StorageLive(_11); + _11 = &raw mut ((*_1).1: *mut T); + _12 = _11 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_11); + StorageLive(_16); + _13 = (*_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageLive(_15); + StorageLive(_14); + _14 = (_13.0: *const T); + _15 = Offset(move _14, const -1_isize); + StorageDead(_14); + _16 = NonNull::<T> { pointer: move _15 }; + StorageDead(_15); + goto -> bb8; + } + + bb7: { + _16 = _13; + goto -> bb8; + } + + bb8: { + (*_12) = move _16; + StorageDead(_16); + _17 = (*_12); + goto -> bb10; + } + + bb9: { + StorageLive(_18); + _18 = &raw mut ((*_1).1: *mut T); + _19 = _18 as *mut usize (PtrToPtr); + StorageDead(_18); + StorageLive(_21); + StorageLive(_20); + _20 = (*_19); + _21 = SubUnchecked(move _20, const 1_usize); + StorageDead(_20); + (*_19) = move _21; + StorageDead(_21); + _17 = ((*_1).0: std::ptr::NonNull<T>); + goto -> bb10; + } + + bb10: { + StorageDead(_12); + StorageDead(_19); + StorageLive(_22); + _22 = _17; + StorageLive(_23); + _23 = (_22.0: *const T); + _24 = move _23 as *mut T (PtrToPtr); + StorageDead(_23); + StorageDead(_22); + _25 = &mut (*_24); + StorageDead(_17); + StorageDead(_24); + _0 = Option::<&mut T>::Some(_25); + goto -> bb12; + } + + bb11: { + _0 = const {transmute(0x0000000000000000): Option<&mut T>}; + goto -> bb12; + } + + bb12: { + StorageDead(_8); + StorageDead(_25); + StorageDead(_4); + StorageDead(_9); + StorageDead(_10); return; } } diff --git a/tests/run-make/crate-name-priority/Makefile b/tests/run-make/crate-name-priority/Makefile deleted file mode 100644 index 4adaa75a71c..00000000000 --- a/tests/run-make/crate-name-priority/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo.rs - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --crate-name bar - rm $(TMPDIR)/$(call BIN,bar) - $(RUSTC) foo1.rs - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo1.rs -o $(TMPDIR)/$(call BIN,bar1) - rm $(TMPDIR)/$(call BIN,bar1) diff --git a/tests/run-make/crate-name-priority/rmake.rs b/tests/run-make/crate-name-priority/rmake.rs new file mode 100644 index 00000000000..b7cb2c99711 --- /dev/null +++ b/tests/run-make/crate-name-priority/rmake.rs @@ -0,0 +1,18 @@ +// The `crate_name` rustc flag should have higher priority +// over `#![crate_name = "foo"]` defined inside the source code. +// This test has a conflict between crate_names defined in the .rs files +// and the compiler flags, and checks that the flag is favoured each time. +// See https://github.com/rust-lang/rust/pull/15518 + +use run_make_support::{bin_name, fs_wrapper, rustc}; + +fn main() { + rustc().input("foo.rs").run(); + fs_wrapper::remove_file(bin_name("foo")); + rustc().input("foo.rs").crate_name("bar").run(); + fs_wrapper::remove_file(bin_name("bar")); + rustc().input("foo1.rs").run(); + fs_wrapper::remove_file(bin_name("foo")); + rustc().input("foo1.rs").output(bin_name("bar1")).run(); + fs_wrapper::remove_file(bin_name("bar1")); +} diff --git a/tests/run-make/error-writing-dependencies/Makefile b/tests/run-make/error-writing-dependencies/Makefile deleted file mode 100644 index a5d30a647f8..00000000000 --- a/tests/run-make/error-writing-dependencies/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -all: - # Let's get a nice error message - $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | \ - $(CGREP) "error writing dependencies" - # Make sure the filename shows up - $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | $(CGREP) "baz" diff --git a/tests/run-make/error-writing-dependencies/rmake.rs b/tests/run-make/error-writing-dependencies/rmake.rs new file mode 100644 index 00000000000..2227f0a1a7f --- /dev/null +++ b/tests/run-make/error-writing-dependencies/rmake.rs @@ -0,0 +1,17 @@ +// Invalid paths passed to rustc used to cause internal compilation errors +// alongside an obscure error message. This was turned into a standard error, +// and this test checks that the cleaner error message is printed instead. +// See https://github.com/rust-lang/rust/issues/13517 + +use run_make_support::rustc; + +// NOTE: This cannot be a UI test due to the --out-dir flag, which is +// already present by default in UI testing. + +fn main() { + let out = rustc().input("foo.rs").emit("dep-info").out_dir("foo/bar/baz").run_fail(); + // The error message should be informative. + out.assert_stderr_contains("error writing dependencies"); + // The filename should appear. + out.assert_stderr_contains("baz"); +} diff --git a/tests/run-make/inline-always-many-cgu/Makefile b/tests/run-make/inline-always-many-cgu/Makefile deleted file mode 100644 index 9945821db28..00000000000 --- a/tests/run-make/inline-always-many-cgu/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 - if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \ - echo "found call instruction when one wasn't expected"; \ - exit 1; \ - fi diff --git a/tests/run-make/inline-always-many-cgu/rmake.rs b/tests/run-make/inline-always-many-cgu/rmake.rs new file mode 100644 index 00000000000..c55ea69f3b9 --- /dev/null +++ b/tests/run-make/inline-always-many-cgu/rmake.rs @@ -0,0 +1,18 @@ +use run_make_support::fs_wrapper::read_to_string; +use run_make_support::regex::Regex; +use run_make_support::{read_dir, rustc}; + +use std::ffi::OsStr; + +fn main() { + rustc().input("foo.rs").emit("llvm-ir").codegen_units(2).run(); + let re = Regex::new(r"\bcall\b").unwrap(); + let mut nb_ll = 0; + read_dir(".", |path| { + if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("ll")) { + assert!(!re.is_match(&read_to_string(path))); + nb_ll += 1; + } + }); + assert!(nb_ll > 0); +} diff --git a/tests/run-make/relocation-model/Makefile b/tests/run-make/relocation-model/Makefile deleted file mode 100644 index 8cc5205ed51..00000000000 --- a/tests/run-make/relocation-model/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: others - $(RUSTC) -C relocation-model=dynamic-no-pic foo.rs - $(call RUN,foo) - - $(RUSTC) -C relocation-model=default foo.rs - $(call RUN,foo) - - $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs --emit=link,obj - -ifdef IS_MSVC -# FIXME(#28026) -others: -else -others: - $(RUSTC) -C relocation-model=static foo.rs - $(call RUN,foo) -endif diff --git a/tests/run-make/relocation-model/rmake.rs b/tests/run-make/relocation-model/rmake.rs new file mode 100644 index 00000000000..9cf85d6d730 --- /dev/null +++ b/tests/run-make/relocation-model/rmake.rs @@ -0,0 +1,24 @@ +// Generation of position-independent code (PIC) can be altered +// through use of the -C relocation-model rustc flag. This test +// uses varied values with this flag and checks that compilation +// succeeds. +// See https://github.com/rust-lang/rust/pull/13340 + +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + rustc().arg("-Crelocation-model=static").input("foo.rs").run(); + run("foo"); + rustc().arg("-Crelocation-model=dynamic-no-pic").input("foo.rs").run(); + run("foo"); + rustc().arg("-Crelocation-model=default").input("foo.rs").run(); + run("foo"); + rustc() + .arg("-Crelocation-model=dynamic-no-pic") + .crate_type("dylib") + .emit("link,obj") + .input("foo.rs") + .run(); +} diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs index b6379c05a85..f3f1fcfda65 100644 --- a/tests/rustdoc/const-effect-param.rs +++ b/tests/rustdoc/const-effect-param.rs @@ -2,6 +2,7 @@ #![crate_name = "foo"] #![feature(effects, const_trait_impl)] +#![allow(incomplete_features)] #[const_trait] pub trait Tr { diff --git a/tests/rustdoc/const-fn-effects.rs b/tests/rustdoc/const-fn-effects.rs index 7c19b4b2c0c..c495a4faa87 100644 --- a/tests/rustdoc/const-fn-effects.rs +++ b/tests/rustdoc/const-fn-effects.rs @@ -1,5 +1,6 @@ #![crate_name = "foo"] #![feature(effects)] +#![allow(incomplete_features)] // @has foo/fn.bar.html // @has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> ' diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs index 6f264969e54..d165a406f56 100644 --- a/tests/rustdoc/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs @@ -7,6 +7,7 @@ // not remove this test. // // FIXME(effects) add `const_trait` to `Fn` so we use `~const` +// FIXME(effects) restore `const_trait` to `Destruct` #![feature(const_trait_impl)] #![crate_name = "foo"] @@ -24,9 +25,9 @@ pub trait Tr<T> { // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="method.a"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' - fn a<A: /* ~const */ Fn() + ~const Destruct>() + fn a<A: /* ~const */ Fn() /* + ~const Destruct */>() where - Option<A>: /* ~const */ Fn() + ~const Destruct, + Option<A>: /* ~const */ Fn() /* + ~const Destruct */, { } } @@ -36,13 +37,13 @@ pub trait Tr<T> { // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/div[@class="where"]' ': Fn' -impl<T: /* ~const */ Fn() + ~const Destruct> const Tr<T> for T +impl<T: /* ~const */ Fn() /* + ~const Destruct */> const Tr<T> for T where - Option<T>: /* ~const */ Fn() + ~const Destruct, + Option<T>: /* ~const */ Fn() /* + ~const Destruct */, { - fn a<A: /* ~const */ Fn() + ~const Destruct>() + fn a<A: /* ~const */ Fn() /* + ~const Destruct */>() where - Option<A>: /* ~const */ Fn() + ~const Destruct, + Option<A>: /* ~const */ Fn() /* + ~const Destruct */, { } } @@ -51,9 +52,9 @@ where // @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' // @!has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' '~const' // @has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' ': Fn' -pub const fn foo<F: /* ~const */ Fn() + ~const Destruct>() +pub const fn foo<F: /* ~const */ Fn() /* + ~const Destruct */>() where - Option<F>: /* ~const */ Fn() + ~const Destruct, + Option<F>: /* ~const */ Fn() /* + ~const Destruct */, { F::a() } @@ -63,9 +64,9 @@ impl<T> S<T> { // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' - pub const fn foo<B, C: /* ~const */ Fn() + ~const Destruct>() + pub const fn foo<B, C: /* ~const */ Fn() /* + ~const Destruct */>() where - B: /* ~const */ Fn() + ~const Destruct, + B: /* ~const */ Fn() /* + ~const Destruct */, { B::a() } diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs new file mode 100644 index 00000000000..22d3beea6c3 --- /dev/null +++ b/tests/rustdoc/unsafe-extern-blocks.rs @@ -0,0 +1,30 @@ +// Test to ensure the feature is working as expected. + +#![feature(unsafe_extern_blocks)] +#![crate_name = "foo"] + +// @has 'foo/index.html' + +// First we check that both the static and the function have a "sup" element +// to tell they're unsafe. + +// @count - '//ul[@class="item-table"]//sup[@title="unsafe static"]' 1 +// @has - '//ul[@class="item-table"]//sup[@title="unsafe static"]' '⚠' +// @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1 +// @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠' + +unsafe extern { + // @has 'foo/static.FOO.html' + // @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32' + pub safe static FOO: i32; + // @has 'foo/static.BAR.html' + // @has - '//pre[@class="rust item-decl"]' 'pub unsafe static BAR: i32' + pub static BAR: i32; + + // @has 'foo/fn.foo.html' + // @has - '//pre[@class="rust item-decl"]' 'pub extern "C" fn foo()' + pub safe fn foo(); + // @has 'foo/fn.bar.html' + // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn bar()' + pub fn bar(); +} diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 359dd4146ba..7518ea902ec 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -54,6 +54,21 @@ fn test_stable_mir() -> ControlFlow<()> { let variadic_fn = *get_item(&items, (ItemKind::Fn, "variadic_fn")).unwrap(); check_variadic(variadic_fn); + // Extract function pointers. + let fn_ptr_holder = *get_item(&items, (ItemKind::Fn, "fn_ptr_holder")).unwrap(); + let fn_ptr_holder_instance = Instance::try_from(fn_ptr_holder).unwrap(); + let body = fn_ptr_holder_instance.body().unwrap(); + let args = body.arg_locals(); + + // Test fn_abi of function pointer version. + let ptr_fn_abi = args[0].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap(); + assert_eq!(ptr_fn_abi, fn_abi); + + // Test variadic_fn of function pointer version. + let ptr_variadic_fn_abi = args[1].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap(); + assert!(ptr_variadic_fn_abi.c_variadic); + assert_eq!(ptr_variadic_fn_abi.args.len(), 1); + ControlFlow::Continue(()) } @@ -164,6 +179,14 @@ fn generate_input(path: &str) -> std::io::Result<()> { pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{ 0 }} + + pub type ComplexFn = fn([u8; 0], char, NonZero<u8>) -> Result<usize, &'static str>; + pub type VariadicFn = unsafe extern "C" fn(usize, ...) -> usize; + + pub fn fn_ptr_holder(complex_fn: ComplexFn, variadic_fn: VariadicFn) {{ + // We only care about the signature. + todo!() + }} "# )?; Ok(()) diff --git a/tests/ui/abi/abi-typo-unstable.stderr b/tests/ui/abi/abi-typo-unstable.stderr index d31cc2a896f..9ba67ad7dbe 100644 --- a/tests/ui/abi/abi-typo-unstable.stderr +++ b/tests/ui/abi/abi-typo-unstable.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `rust-intrinsec` LL | extern "rust-intrinsec" fn rust_intrinsic() {} | ^^^^^^^^^^^^^^^^ invalid ABI | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: aborting due to 1 previous error diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr index 02082c13f91..e80411fda34 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr @@ -7,7 +7,7 @@ LL | extern "riscv-interrupt" fn isr() {} | invalid ABI | help: did you mean: `"riscv-interrupt-m"` | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively error[E0703]: invalid ABI: found `riscv-interrupt-u` @@ -19,7 +19,7 @@ LL | extern "riscv-interrupt-u" fn isr_U() {} | invalid ABI | help: did you mean: `"riscv-interrupt-m"` | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314 error: aborting due to 2 previous errors diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr index 02082c13f91..e80411fda34 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr @@ -7,7 +7,7 @@ LL | extern "riscv-interrupt" fn isr() {} | invalid ABI | help: did you mean: `"riscv-interrupt-m"` | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively error[E0703]: invalid ABI: found `riscv-interrupt-u` @@ -19,7 +19,7 @@ LL | extern "riscv-interrupt-u" fn isr_U() {} | invalid ABI | help: did you mean: `"riscv-interrupt-m"` | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314 error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/dump-preds.rs b/tests/ui/attributes/dump-preds.rs new file mode 100644 index 00000000000..1e15ff2f9bd --- /dev/null +++ b/tests/ui/attributes/dump-preds.rs @@ -0,0 +1,20 @@ +//@ normalize-stderr-test "DefId\(.+?\)" -> "DefId(..)" + +#![feature(rustc_attrs)] + +#[rustc_dump_predicates] +trait Trait<T>: Iterator<Item: Copy> +//~^ ERROR rustc_dump_predicates +where + String: From<T> +{ + #[rustc_dump_predicates] + #[rustc_dump_item_bounds] + type Assoc<P: Eq>: std::ops::Deref<Target = ()> + //~^ ERROR rustc_dump_predicates + //~| ERROR rustc_dump_item_bounds + where + Self::Assoc<()>: Copy; +} + +fn main() {} diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr new file mode 100644 index 00000000000..26834376e76 --- /dev/null +++ b/tests/ui/attributes/dump-preds.stderr @@ -0,0 +1,39 @@ +error: rustc_dump_predicates + --> $DIR/dump-preds.rs:6:1 + | +LL | trait Trait<T>: Iterator<Item: Copy> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(<Self as std::iter::Iterator>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<<Self as std::iter::Iterator>::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<T as std::marker::Sized>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<std::string::String as std::convert::From<T>>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<Self as Trait<T>>, polarity:Positive), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/dump-preds.rs:13:5 + | +LL | type Assoc<P: Eq>: std::ops::Deref<Target = ()> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(<Self as std::iter::Iterator>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<<Self as std::iter::Iterator>::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<T as std::marker::Sized>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<std::string::String as std::convert::From<T>>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<Self as Trait<T>>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<P as std::marker::Sized>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<P as std::cmp::Eq>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<()> as std::marker::Copy>, polarity:Positive), bound_vars: [] } + +error: rustc_dump_item_bounds + --> $DIR/dump-preds.rs:13:5 + | +LL | type Assoc<P: Eq>: std::ops::Deref<Target = ()> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..) })], def_id: DefId(..) }, Term::Ty(())), bound_vars: [] } + = note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::ops::Deref>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::marker::Sized>, polarity:Positive), bound_vars: [] } + +error: aborting due to 3 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 856ec4a5b9e..fdcada468e0 100644 --- a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -17,7 +17,7 @@ help: add a dummy let to cause `fptr` to be fully captured | LL ~ thread::spawn(move || { let _ = &fptr; unsafe { LL | - ... +... LL | LL ~ } }).join().unwrap(); | @@ -39,7 +39,7 @@ help: add a dummy let to cause `fptr` to be fully captured | LL ~ thread::spawn(move || { let _ = &fptr; unsafe { LL | - ... +... LL | LL ~ } }).join().unwrap(); | diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index 344bc662ee7..138778ff5d7 100644 --- a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -109,7 +109,7 @@ help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured | LL ~ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { LL | - ... +... LL | LL ~ } }).join().unwrap(); | diff --git a/tests/ui/codemap_tests/unicode.normal.stderr b/tests/ui/codemap_tests/unicode.normal.stderr index a6e22e1c38f..0f254e0246f 100644 --- a/tests/ui/codemap_tests/unicode.normal.stderr +++ b/tests/ui/codemap_tests/unicode.normal.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́` LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs index 89bcd54c461..cd008aa2c9f 100644 --- a/tests/ui/const-generics/const_trait_fn-issue-88433.rs +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -1,6 +1,6 @@ //@ build-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Func<T> { diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.stderr b/tests/ui/const-generics/const_trait_fn-issue-88433.stderr new file mode 100644 index 00000000000..4e0d6370fbd --- /dev/null +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const_trait_fn-issue-88433.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index 8adf3ba433d..eb58233d1b1 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,5 +1,5 @@ #![crate_type = "lib"] -#![feature(const_closures, const_trait_impl, effects)] +#![feature(const_closures, const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete pub const fn test() { let cl = const || {}; diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index 81790a62f61..42a42ae3938 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-block-const-bound.rs:8:22 + | +LL | const fn f<T: ~const Destruct>(x: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-block-const-bound.rs:8:32 | @@ -6,6 +12,6 @@ LL | const fn f<T: ~const Destruct>(x: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs index 44772fb7313..ae094003c89 100644 --- a/tests/ui/consts/const-float-classify.rs +++ b/tests/ui/consts/const-float-classify.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zmir-opt-level=0 -//@ run-pass +//@ known-bug: #110395 +// FIXME(effects) run-pass #![feature(const_float_bits_conv)] #![feature(const_float_classify)] diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr new file mode 100644 index 00000000000..1de27a072cf --- /dev/null +++ b/tests/ui/consts/const-float-classify.stderr @@ -0,0 +1,223 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-float-classify.rs:7:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ^^^^^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/const-float-classify.rs:12:6 + | +LL | impl const PartialEq<NonDet> for bool { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0284]: type annotations needed + --> $DIR/const-float-classify.rs:21:35 + | +LL | const _: () = assert!($a == $b); + | ^^ cannot infer the value of the constant `_` +... +LL | / suite! { +LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] +LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] +... | +LL | | -1.0 / 0.0 => [ false, true, false, false, false, true] +LL | | } + | |_- in this macro invocation + | +note: required for `bool` to implement `PartialEq<NonDet>` + --> $DIR/const-float-classify.rs:12:12 + | +LL | impl const PartialEq<NonDet> for bool { + | ----- ^^^^^^^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0284. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 98f5b3a5e90..e0e673d5fbd 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const_cmp_type_id.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0131]: `main` function is not allowed to have generic parameters --> $DIR/const_cmp_type_id.rs:7:14 | @@ -10,25 +19,7 @@ error[E0080]: evaluation of constant value failed LL | const _A: bool = TypeId::of::<u8>() < TypeId::of::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<TypeId as PartialOrd>::lt` -error[E0308]: mismatched types - --> $DIR/const_cmp_type_id.rs:8:13 - | -LL | assert!(TypeId::of::<u8>() == TypeId::of::<u8>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` - | - = note: expected constant `host` - found constant `true` - -error[E0308]: mismatched types - --> $DIR/const_cmp_type_id.rs:9:13 - | -LL | assert!(TypeId::of::<()>() != TypeId::of::<u8>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` - | - = note: expected constant `host` - found constant `true` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors; 1 warning emitted -Some errors have detailed explanations: E0080, E0131, E0308. +Some errors have detailed explanations: E0080, E0131. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 4fb82c0683d..42a6026cfba 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,6 +4,12 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls` LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0635]: unknown feature `const_cmp` + --> $DIR/fn_trait_refs.rs:8:12 + | +LL | #![feature(const_cmp)] + | ^^^^^^^^^ + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:15:15 | @@ -11,6 +17,12 @@ LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:15:31 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:15:15 | LL | T: ~const Fn<()> + ~const Destruct, @@ -25,6 +37,12 @@ LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:22:34 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:22:15 | LL | T: ~const FnMut<()> + ~const Destruct, @@ -53,6 +71,12 @@ LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:36:31 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:36:15 | LL | T: ~const Fn<()> + ~const Destruct, @@ -67,6 +91,12 @@ LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:50:34 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:50:15 | LL | T: ~const FnMut<()> + ~const Destruct, @@ -182,7 +212,7 @@ LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output) LL | } | - value is dropped here -error: aborting due to 20 previous errors +error: aborting due to 25 previous errors Some errors have detailed explanations: E0015, E0493, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/rustc-impl-const-stability.stderr b/tests/ui/consts/rustc-impl-const-stability.stderr index ba8e6c1555c..250d1c3fc05 100644 --- a/tests/ui/consts/rustc-impl-const-stability.stderr +++ b/tests/ui/consts/rustc-impl-const-stability.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/rustc-impl-const-stability.rs:5:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/rustc-impl-const-stability.rs:15:12 | @@ -16,6 +25,6 @@ LL | impl const Default for Data { = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/error-codes/E0116.stderr b/tests/ui/error-codes/E0116.stderr index bf215435ba6..1ea5a57f46d 100644 --- a/tests/ui/error-codes/E0116.stderr +++ b/tests/ui/error-codes/E0116.stderr @@ -2,7 +2,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/E0116.rs:1:1 | LL | impl Vec<u8> {} - | ^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/error-codes/E0519.stderr b/tests/ui/error-codes/E0519.stderr index 4fbd268134f..a814277cafa 100644 --- a/tests/ui/error-codes/E0519.stderr +++ b/tests/ui/error-codes/E0519.stderr @@ -1,4 +1,4 @@ -error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `crateresolve1` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. +error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `crateresolve1` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two --> $DIR/E0519.rs:8:1 | LL | extern crate crateresolve1; diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 30039267979..88732f75cb4 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -186,7 +186,7 @@ warning: unknown lint: `x5100` LL | #[deny(x5100)] impl S { } | ^^^^^ -warning: use of deprecated attribute `crate_id`: no longer used. +warning: use of deprecated attribute `crate_id`: no longer used --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 | LL | #![crate_id = "10"] @@ -194,7 +194,7 @@ LL | #![crate_id = "10"] | = note: `#[warn(deprecated)]` on by default -warning: use of deprecated attribute `no_start`: no longer used. +warning: use of deprecated attribute `no_start`: no longer used --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 | LL | #![no_start] diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 5e3c0ea054b..73f4d4c3885 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -4,6 +4,12 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/normalize-tait-in-const.rs:27:69 + | +LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^^^^^^ + error[E0015]: cannot call non-const closure in constant functions --> $DIR/normalize-tait-in-const.rs:28:5 | @@ -29,7 +35,7 @@ LL | fun(filter_positive()); LL | } | - value is dropped here -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0015, E0493. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/imports/issue-59764.stderr b/tests/ui/imports/issue-59764.stderr index 293c2a60d80..74525c9c88f 100644 --- a/tests/ui/imports/issue-59764.stderr +++ b/tests/ui/imports/issue-59764.stderr @@ -209,7 +209,7 @@ help: a macro with this name exists at the root of the crate | LL ~ issue_59764::{makro as foobar, LL | - ... +... LL | LL ~ foo::{baz} | diff --git a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr index 6dc1680cf89..f8491697910 100644 --- a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr +++ b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr @@ -2,7 +2,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/no-attr-empty-impl.rs:4:1 | LL | impl extern_crate::StructWithAttr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead @@ -10,7 +10,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/no-attr-empty-impl.rs:7:1 | LL | impl extern_crate::StructNoAttr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead @@ -18,7 +18,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/no-attr-empty-impl.rs:10:1 | LL | impl extern_crate::EnumWithAttr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead @@ -26,7 +26,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/no-attr-empty-impl.rs:13:1 | LL | impl extern_crate::EnumNoAttr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr index 5df6aaf9804..15fa3f6ee11 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr @@ -1,4 +1,4 @@ -warning: Number of conditions in decision (7) exceeds limit (6). MC/DC analysis will not count this expression. +warning: number of conditions in decision (7) exceeds limit (6), so MC/DC analysis will not count this expression --> $DIR/mcdc-condition-limit.rs:29:8 | LL | if a && b && c && d && e && f && g { diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs index de3770b5709..eb19ddec78f 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.rs +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -26,7 +26,7 @@ fn main() { fn main() { // 7 conditions is too many, so issue a diagnostic. let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); - if a && b && c && d && e && f && g { //[bad]~ WARNING Number of conditions in decision + if a && b && c && d && e && f && g { //[bad]~ WARNING number of conditions in decision core::hint::black_box("hello"); } } diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs index d6655b51905..a53071e304d 100644 --- a/tests/ui/intrinsics/not-overridden.rs +++ b/tests/ui/intrinsics/not-overridden.rs @@ -1,6 +1,6 @@ //! Check that intrinsics that do not get overridden, but are marked as such, //! cause an error instead of silently invoking the body. -#![feature(rustc_attrs, effects)] +#![feature(rustc_attrs/* , effects*/)] // FIXME(effects) //@ build-fail //@ failure-status:101 //@ normalize-stderr-test ".*note: .*\n\n" -> "" diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs index 23cd5f10835..c116ba7a62e 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -1,6 +1,6 @@ #![feature(intrinsics)] #![feature(rustc_attrs)] -#![feature(effects)] +// FIXME(effects) do this with revisions #![feature(effects)] extern "rust-intrinsic" { fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch @@ -19,7 +19,7 @@ const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} mod foo { #[rustc_intrinsic] unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - //~^ ERROR wrong number of const parameters + // FIXME(effects) ~^ ERROR wrong number of const parameters } fn main() {} diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index d73d5bab8d7..7f37e0f8211 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -42,13 +42,6 @@ LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} = note: expected signature `unsafe fn(_, _, _)` found signature `fn(_, _, _)` -error[E0094]: intrinsic has wrong number of const parameters: found 0, expected 1 - --> $DIR/safe-intrinsic-mismatch.rs:21:31 - | -LL | unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - | ^ expected 1 const parameter - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0094, E0308. -For more information about an error, try `rustc --explain E0094`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-22644.stderr b/tests/ui/issues/issue-22644.stderr index 7d8a0ff170a..c6d41cc856d 100644 --- a/tests/ui/issues/issue-22644.stderr +++ b/tests/ui/issues/issue-22644.stderr @@ -64,7 +64,7 @@ help: try comparing the cast value | LL ~ println!("{}", (a LL | - ... +... LL | LL ~ usize) | diff --git a/tests/ui/issues/issue-57271.stderr b/tests/ui/issues/issue-57271.stderr index 10cbb34ef5d..a61419c61d7 100644 --- a/tests/ui/issues/issue-57271.stderr +++ b/tests/ui/issues/issue-57271.stderr @@ -17,7 +17,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ Array(Box<TypeSignature>), LL | TypeVariable(()), - ... +... LL | Base(BaseType), LL ~ Object(Box<ObjectType>), | diff --git a/tests/ui/let-else/let-else-if.stderr b/tests/ui/let-else/let-else-if.stderr index c8058ec6692..7e2215c8c05 100644 --- a/tests/ui/let-else/let-else-if.stderr +++ b/tests/ui/let-else/let-else-if.stderr @@ -8,7 +8,7 @@ help: try placing this code inside a block | LL ~ let Some(_) = Some(()) else { if true { LL | - ... +... LL | return; LL ~ } }; | diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr index c3784770d79..9ceaef2f9b1 100644 --- a/tests/ui/lifetimes/no_lending_iterators.stderr +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -4,7 +4,7 @@ error: associated type `Iterator::Item` is declared without lifetime parameters, LL | type Item = &str; | ^ | -note: you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type. +note: you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type --> $DIR/no_lending_iterators.rs:3:19 | LL | impl Iterator for Data { diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr index 7fe078068fe..ddc31905afb 100644 --- a/tests/ui/lint/lint-attr-everywhere-late.stderr +++ b/tests/ui/lint/lint-attr-everywhere-late.stderr @@ -154,7 +154,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | fn assoc_fn() { discriminant::<i32>(&123); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:96:41 | LL | fn assoc_fn() { discriminant::<i32>(&123); } @@ -208,7 +208,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | let _ = discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:139:33 | LL | let _ = discriminant::<i32>(&123); @@ -237,7 +237,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:155:33 | LL | discriminant::<i32>(&123); @@ -254,7 +254,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:161:33 | LL | discriminant::<i32>(&123); @@ -283,7 +283,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:173:29 | LL | discriminant::<i32>(&123); @@ -300,7 +300,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:177:29 | LL | discriminant::<i32>(&123); @@ -317,7 +317,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant::<i32>(&123); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:182:25 | LL | discriminant::<i32>(&123); @@ -334,7 +334,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:184:61 | LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; @@ -351,7 +351,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:185:61 | LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); @@ -368,7 +368,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:187:65 | LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); @@ -385,7 +385,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum --> $DIR/lint-attr-everywhere-late.rs:189:72 | LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); diff --git a/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr index 63ed2503cf3..f9eeaebe21f 100644 --- a/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr +++ b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr @@ -4,7 +4,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant(&()); | ^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum --> $DIR/lint-enum-intrinsics-non-enums.rs:26:18 | LL | discriminant(&()); @@ -17,7 +17,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant(&&SomeEnum::B); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum --> $DIR/lint-enum-intrinsics-non-enums.rs:29:18 | LL | discriminant(&&SomeEnum::B); @@ -29,7 +29,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum --> $DIR/lint-enum-intrinsics-non-enums.rs:32:18 | LL | discriminant(&SomeStruct); @@ -41,7 +41,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant(&123u32); | ^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum --> $DIR/lint-enum-intrinsics-non-enums.rs:35:18 | LL | discriminant(&123u32); @@ -53,7 +53,7 @@ error: the return value of `mem::discriminant` is unspecified when called with a LL | discriminant(&&123i8); | ^^^^^^^^^^^^^^^^^^^^^ | -note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum. +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum --> $DIR/lint-enum-intrinsics-non-enums.rs:38:18 | LL | discriminant(&&123i8); @@ -65,7 +65,7 @@ error: the return value of `mem::variant_count` is unspecified when called with LL | variant_count::<&str>(); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum. + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum error: the return value of `mem::variant_count` is unspecified when called with a non-enum type --> $DIR/lint-enum-intrinsics-non-enums.rs:49:5 @@ -73,7 +73,7 @@ error: the return value of `mem::variant_count` is unspecified when called with LL | variant_count::<*const u8>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum. + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum error: the return value of `mem::variant_count` is unspecified when called with a non-enum type --> $DIR/lint-enum-intrinsics-non-enums.rs:52:5 @@ -81,7 +81,7 @@ error: the return value of `mem::variant_count` is unspecified when called with LL | variant_count::<()>(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum. + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum error: the return value of `mem::variant_count` is unspecified when called with a non-enum type --> $DIR/lint-enum-intrinsics-non-enums.rs:55:5 @@ -89,7 +89,7 @@ error: the return value of `mem::variant_count` is unspecified when called with LL | variant_count::<&SomeEnum>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum. + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum error: aborting due to 9 previous errors diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index 13d4c5faf73..ca18f0fdd7f 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -27,7 +27,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched | LL ~ if let Some(1) = loop { LL | - ... +... LL | return; LL ~ } { todo!() }; | diff --git a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr index 3247513d42c..cf863ff8af1 100644 --- a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr +++ b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr @@ -26,7 +26,7 @@ help: consider moving the expression out of the loop so it is only moved once LL ~ for foo in foos { let mut value = baz.push(foo); LL ~ for bar in &bars { if foo == *bar { LL | - ... +... LL | LL ~ value; | @@ -69,7 +69,7 @@ help: consider moving the expression out of the loop so it is only moved once LL ~ let mut value = baz.push(foo); LL ~ for bar in &bars { LL | - ... +... LL | if foo == *bar { LL ~ value; | diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr index f2bc8bd8400..7cd6175a5ad 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -4,7 +4,7 @@ warning: unnecessary associated type bound for not object safe associated type LL | fn foo(_: &dyn Foo<Bar = ()>) {} | ^^^^^^^^ help: remove this bound | - = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` = note: `#[warn(unused_associated_type_bounds)]` on by default warning: 1 warning emitted diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index abaa6527b0a..29404f1793b 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -105,15 +105,6 @@ LL | extern "C" { LL | extern "C" fn fe4(); | ^^^^^^^^^^ help: remove this qualifier -error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:9 - | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -... -LL | const async unsafe extern "C" fn fe5(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:50:15 | @@ -141,6 +132,15 @@ LL | extern "C" { LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^ help: remove this qualifier +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/fn-header-semantic-fail.rs:50:9 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +... +LL | const async unsafe extern "C" fn fe5(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:50:9 | diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs index 43530e41a66..0e95fc757f3 100644 --- a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -1,7 +1,7 @@ // Regression test for part of issue #119924. //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Trait { diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr b/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr new file mode 100644 index 00000000000..6670b3772db --- /dev/null +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/impls-nested-within-fns-semantic-1.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/parser/issues/issue-8537.stderr b/tests/ui/parser/issues/issue-8537.stderr index 0d636bd28a5..b685464d8d4 100644 --- a/tests/ui/parser/issues/issue-8537.stderr +++ b/tests/ui/parser/issues/issue-8537.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize` LL | "invalid-ab_isize" | ^^^^^^^^^^^^^^^^^^ invalid ABI | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: aborting due to 1 previous error diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index 892024ce893..f575acc839d 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -6,23 +6,23 @@ LL | extern "C" { LL | const fn foo(); | ^^^^^ help: remove this qualifier -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: functions in `extern` blocks cannot have qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | LL | extern "C" { - | ---------- help: add unsafe to this `extern` block + | ---------- in this `extern` block ... LL | const unsafe fn bar(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ help: remove this qualifier -error: functions in `extern` blocks cannot have qualifiers +error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | LL | extern "C" { - | ---------- in this `extern` block + | ---------- help: add unsafe to this `extern` block ... LL | const unsafe fn bar(); - | ^^^^^ help: remove this qualifier + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr b/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr index d66ce695090..c8107997c2e 100644 --- a/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr +++ b/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr @@ -54,7 +54,7 @@ help: consider enclosing expression in a block | LL ~ let _i = 'label: { match x { LL | 0 => 42, - ... +... LL | _ => 1, LL ~ } }; | diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr index 62c8a442ab9..3aec4383eab 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-type-const-bound-usage-0.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-0.rs:21:6 | @@ -9,6 +18,6 @@ help: consider further restricting this bound LL | const fn qualified<T: ~const Trait + Trait>() -> i32 { | +++++++ -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs index 6b55e82629b..eecd6e6109c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs @@ -3,7 +3,7 @@ //@[unqualified] check-pass //@[qualified] known-bug: unknown -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //[unqualified]~ WARN the feature `effects` is incomplete #[const_trait] trait Trait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr new file mode 100644 index 00000000000..3d592834600 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.unqualified.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-type-const-bound-usage-0.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs index 886fa6577d7..645fff4e014 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,5 +1,5 @@ // FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Add<Rhs = Self> { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index a9cae2a70be..cc3abea25eb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-type.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied --> $DIR/assoc-type.rs:35:16 | @@ -11,6 +20,6 @@ note: required by a bound in `Foo::Bar` LL | type Bar: ~const Add; | ^^^^^^^^^^ required by this bound in `Foo::Bar` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs index f40dc27cb4c..62609384cff 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] pub trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs index 687cb128b05..fd4e1ff803d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index 771c35cf6ab..bb9e9045f8f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] pub trait Plus { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 93d520f29ef..0e4dcf0f302 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-const-trait-method-fail.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `u32: ~const Plus` is not satisfied --> $DIR/call-const-trait-method-fail.rs:25:5 | @@ -6,6 +15,6 @@ LL | a.plus(b) | = help: the trait `Plus` is implemented for `u32` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs index b63458b39e9..6b3a4ae1b95 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -1,4 +1,5 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr new file mode 100644 index 00000000000..12027c4d713 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr @@ -0,0 +1,8 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-in-impl.rs:10:16 + | +LL | impl<T: ~const PartialEq> const MyPartialEq for T { + | ^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs index 37b2de0fd2d..9df694a02f5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -1,6 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass #![feature(const_trait_impl, effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr new file mode 100644 index 00000000000..36c7a654430 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr @@ -0,0 +1,71 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-chain.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-chain.rs:10:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/call-generic-method-chain.rs:10:6 + | +LL | impl const PartialEq for S { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-chain.rs:19:32 + | +LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-chain.rs:23:40 + | +LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-chain.rs:27:22 + | +LL | pub const EQ: bool = equals_self_wrapper(&S); + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-chain.rs:10:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-chain.rs:15:10 + | +LL | !self.eq(other) + | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-chain.rs:10:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0284. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index ea8fd005561..f46a34911f1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -1,4 +1,5 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass #![feature(const_trait_impl, effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr new file mode 100644 index 00000000000..320e420b80a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr @@ -0,0 +1,85 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-dup-bound.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-dup-bound.rs:8:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/call-generic-method-dup-bound.rs:8:6 + | +LL | impl const PartialEq for S { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-dup-bound.rs:19:44 + | +LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-dup-bound.rs:26:37 + | +LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-dup-bound.rs:30:22 + | +LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S); + | ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-dup-bound.rs:8:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-dup-bound.rs:30:41 + | +LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S); + | ^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-dup-bound.rs:8:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-dup-bound.rs:13:10 + | +LL | !self.eq(other) + | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-dup-bound.rs:8:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 7 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0284. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs index 043939750a8..a9ed5a639d7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -1,8 +1,10 @@ -#![feature(const_trait_impl, effects)] +//@ check-pass + +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete pub const fn equals_self<T: PartialEq>(t: &T) -> bool { *t == *t - //~^ ERROR mismatched types + // FIXME(effects) ~^ ERROR mismatched types // FIXME(effects): diagnostic } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr index 5074c4a2261..74b74052da0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -1,12 +1,11 @@ -error[E0308]: mismatched types - --> $DIR/call-generic-method-fail.rs:4:5 +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-fail.rs:3:30 | -LL | *t == *t - | ^^^^^^^^ expected `host`, found `true` +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ | - = note: expected constant `host` - found constant `true` + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 1 previous error +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index 8d6176a5bac..222bff2db88 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete struct S; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index 3581b1fcd7d..fa59e5ee03d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-nonconst.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `S: const Foo` is not satisfied --> $DIR/call-generic-method-nonconst.rs:23:34 | @@ -13,6 +22,6 @@ note: required by a bound in `equals_self` LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool { | ^^^^^^^^^^ required by this bound in `equals_self` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs index 55d8afa8d47..413685d8b34 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -1,6 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass #![feature(const_trait_impl, effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr new file mode 100644 index 00000000000..6b9d290839e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr @@ -0,0 +1,65 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-pass.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-pass.rs:10:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/call-generic-method-pass.rs:10:6 + | +LL | impl const PartialEq for S { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-pass.rs:19:32 + | +LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-pass.rs:23:22 + | +LL | pub const EQ: bool = equals_self(&S); + | ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-pass.rs:10:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0284]: type annotations needed + --> $DIR/call-generic-method-pass.rs:15:10 + | +LL | !self.eq(other) + | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + | +note: required for `S` to implement `PartialEq` + --> $DIR/call-generic-method-pass.rs:10:12 + | +LL | impl const PartialEq for S { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0284. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 54bc4347722..8916450df2d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Add` for type `Int` + --> $DIR/const-and-non-const-impl.rs:23:1 + | +LL | impl std::ops::Add for Int { + | -------------------------- first implementation here +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` + error[E0117]: only traits defined in the current crate can be implemented for primitive types --> $DIR/const-and-non-const-impl.rs:7:1 | @@ -10,15 +19,6 @@ LL | impl const std::ops::Add for i32 { | = note: define and implement a trait or new type instead -error[E0119]: conflicting implementations of trait `Add` for type `Int` - --> $DIR/const-and-non-const-impl.rs:23:1 - | -LL | impl std::ops::Add for Int { - | -------------------------- first implementation here -... -LL | impl const std::ops::Add for Int { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` - error: aborting due to 2 previous errors Some errors have detailed explanations: E0117, E0119. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs index 3582e5e050c..db446f8bc2e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs @@ -1,5 +1,5 @@ // Regression test for issue #117244. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete trait NonConst {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr index 08954987d31..d04e5490b76 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-bounds-non-const-trait.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-bounds-non-const-trait.rs:6:28 | @@ -10,5 +19,5 @@ error: `const` can only be applied to `#[const_trait]` traits LL | fn operate<T: const NonConst>() {} | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs index 4854f41bf04..a1710e65252 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete struct S; #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr index ae035b26ec5..d93327cea1b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-check-fns-in-const-impl.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0015]: cannot call non-const fn `non_const` in constant functions --> $DIR/const-check-fns-in-const-impl.rs:12:16 | @@ -6,6 +15,6 @@ LL | fn foo() { non_const() } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs index be668b4f13a..2fd58b05178 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait ConstDefaultFn: Sized { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index f39e6dcadba..8e04d0bd20d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-method-bodies.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied --> $DIR/const-default-method-bodies.rs:24:18 | @@ -6,6 +15,6 @@ LL | NonConstImpl.a(); | = help: the trait `ConstDefaultFn` is implemented for `NonConstImpl` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr index 16ed615907b..be197006f02 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr @@ -1,9 +1,27 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:9:68 + | +LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct { + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:20:15 + | +LL | T: ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:21:15 + | +LL | E: ~const Destruct, + | ^^^^^^^^ + error[E0493]: destructor of `E` cannot be evaluated at compile-time --> $DIR/const-drop-bound.rs:12:13 | LL | Err(_e) => None, | ^^ the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr index 6f75924f0aa..085d9e71012 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail-2.rs:21:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop-fail-2.rs:21:36 | @@ -6,6 +12,6 @@ LL | const fn check<T: ~const Destruct>(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index 9afa2072dde..e95215d4715 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail.rs:24:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop-fail.rs:24:36 | @@ -54,7 +60,7 @@ LL | | } | |_- in this macro invocation = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0080, E0493. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index 09ebf55c57c..f9bd9953fcf 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail.rs:24:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop-fail.rs:24:36 | @@ -6,6 +12,6 @@ LL | const fn check<T: ~const Destruct>(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 5ff3be713a7..6aace105896 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop.rs:19:22 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time --> $DIR/const-drop.rs:24:13 | @@ -86,7 +92,7 @@ LL | | } | |_- in this macro invocation = note: this error originates in the macro `implements_const_drop` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0080, E0493. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 40e39cbefbc..18dd4543c3d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop.rs:19:22 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time --> $DIR/const-drop.rs:24:13 | @@ -14,6 +20,6 @@ LL | const fn a<T: ~const Destruct>(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs index f6bba19a19e..faa913c7598 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs @@ -7,7 +7,7 @@ #![feature( auto_traits, const_trait_impl, - effects, + effects, //~ WARN the feature `effects` is incomplete lang_items, no_core, staged_api, diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr new file mode 100644 index 00000000000..42b19fce28e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-fns-are-early-bound.rs:10:5 + | +LL | effects, + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr index d20404e63b3..fb282d9ee2b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-impl-requires-const-trait.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: const `impl` for trait `A` which is not marked with `#[const_trait]` --> $DIR/const-impl-requires-const-trait.rs:8:12 | @@ -19,6 +28,6 @@ LL | impl const A for () {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr index 03038eb5c84..af50a115c69 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr @@ -1,28 +1,244 @@ -error[E0277]: can't compare `()` with `()` - --> $DIR/const-impl-trait.rs:36:17 +error[E0635]: unknown feature `const_cmp` + --> $DIR/const-impl-trait.rs:8:5 | -LL | assert!(cmp(&())); - | --- ^^^ no implementation for `() == ()` +LL | const_cmp, + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:13:30 + | +LL | const fn cmp(a: &impl ~const PartialEq) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:30 + | +LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct) + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:49 + | +LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct) + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:20 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:39 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:20 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:39 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:50:41 + | +LL | const fn apit(_: impl ~const T + ~const Destruct) {} + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:54:73 + | +LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {} + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:26 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:26 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:13 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^ - value is dropped here | | - | required by a bound introduced by this call + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:13 | - = help: the trait `const PartialEq` is not implemented for `()` - = help: the trait `PartialEq` is implemented for `()` -note: required by a bound in `cmp` - --> $DIR/const-impl-trait.rs:13:23 +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants | -LL | const fn cmp(a: &impl ~const PartialEq) -> bool { - | ^^^^^^^^^^^^^^^^ required by this bound in `cmp` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:26 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:26 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:13 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:13 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl ~const T + ~const Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:50:15 + | +LL | const fn apit(_: impl ~const T + ~const Destruct) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions -error[E0369]: binary operation `==` cannot be applied to type `&impl ~const PartialEq` - --> $DIR/const-impl-trait.rs:14:7 +error[E0493]: destructor of `impl IntoIterator<Item : ~const T> + ~const Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:54:27 | -LL | a == a - | - ^^ - &impl ~const PartialEq - | | - | &impl ~const PartialEq +LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error: aborting due to 32 previous errors -Some errors have detailed explanations: E0277, E0369. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0493, E0635. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs index 79719dae44f..8e71fa4d519 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete //@ edition: 2021 #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr index 04c2dc2e2e0..7d774bef0e9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr @@ -26,5 +26,14 @@ LL | const fn take(_: &dyn ~const NonConst) {} | = note: trait objects cannot have `~const` trait bounds -error: aborting due to 4 previous errors +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-trait-bounds-trait-objects.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr index 4b009446dbc..1e091283510 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-non-const-type.rs:2:26 + | +LL | #![feature(derive_const, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-non-const-type.rs:10:16 | @@ -13,6 +22,6 @@ error[E0207]: the const parameter `host` is not constrained by the impl trait, s = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr index 86dfc521fea..925b2c58ed7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr @@ -1,3 +1,18 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-use.rs:3:76 + | +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0635]: unknown feature `const_cmp` + --> $DIR/derive-const-use.rs:3:30 + | +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + | ^^^^^^^^^ + error[E0635]: unknown feature `const_default_impls` --> $DIR/derive-const-use.rs:3:41 | @@ -22,6 +37,24 @@ LL | impl const Default for A { = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:11:12 + | +LL | impl const PartialEq for A { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/derive-const-use.rs:11:6 + | +LL | impl const PartialEq for A { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:15:16 | @@ -37,6 +70,22 @@ error[E0207]: the const parameter `host` is not constrained by the impl trait, s = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:15:25 + | +LL | #[derive_const(Default, PartialEq)] + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0284]: type annotations needed --> $DIR/derive-const-use.rs:18:35 | @@ -50,16 +99,17 @@ LL | #[derive_const(Default, PartialEq)] | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0308]: mismatched types - --> $DIR/derive-const-use.rs:16:14 +error[E0284]: type annotations needed + --> $DIR/derive-const-use.rs:18:23 | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^^ expected `host`, found `true` +LL | const _: () = assert!(S((), A) == S::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` | - = note: expected constant `host` - found constant `true` +note: required for `S` to implement `PartialEq` + --> $DIR/derive-const-use.rs:15:25 + | +LL | #[derive_const(Default, PartialEq)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0284]: type annotations needed @@ -79,7 +129,24 @@ LL | impl const Default for A { | unsatisfied trait bound introduced here = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0284]: type annotations needed + --> $DIR/derive-const-use.rs:16:18 + | +LL | #[derive_const(Default, PartialEq)] + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^ cannot infer the value of the constant `_` + | +note: required for `A` to implement `PartialEq` + --> $DIR/derive-const-use.rs:11:12 + | +LL | impl const PartialEq for A { + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 14 previous errors; 1 warning emitted -Some errors have detailed explanations: E0207, E0284, E0308, E0635. +Some errors have detailed explanations: E0207, E0284, E0635. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs index 0eb422728c6..c032c76d38f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs @@ -1,4 +1,5 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass #![feature(derive_const)] #![feature(const_trait_impl, effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr new file mode 100644 index 00000000000..5d3aa250d18 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr @@ -0,0 +1,49 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-with-params.rs:5:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-with-params.rs:7:16 + | +LL | #[derive_const(PartialEq)] + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/derive-const-with-params.rs:7:16 + | +LL | #[derive_const(PartialEq)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0284]: type annotations needed + --> $DIR/derive-const-with-params.rs:11:5 + | +LL | a == b + | ^^^^^^ cannot infer the value of the constant `_` + | +note: required for `Reverse<i32>` to implement `PartialEq` + --> $DIR/derive-const-with-params.rs:7:16 + | +LL | #[derive_const(PartialEq)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0284. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs index 54e5c95c259..d8be8b13d08 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete //@ aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr new file mode 100644 index 00000000000..2f1e1e6b8d2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate-default-method-body-is-const.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr new file mode 100644 index 00000000000..2ce29a74eae --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gated.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate.rs:3:60 + | +LL | #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr index f0ac953fd5d..ddb5b3c7c50 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -1,11 +1,20 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate.rs:3:60 + | +LL | #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:17:14 + --> $DIR/cross-crate.rs:18:14 | LL | NonConst.func(); | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` | = help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs index 587dd70c18b..04c101d0fc5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs @@ -1,6 +1,7 @@ //@ revisions: stock gated stocknc gatednc //@ [gated] check-pass #![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] +//[gated,gatednc]~^ WARN the feature `effects` is incomplete //@ aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr index a0c50ac7e61..3df875057f2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions - --> $DIR/cross-crate.rs:20:11 + --> $DIR/cross-crate.rs:21:11 | LL | Const.func(); | ^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr index 312818ae631..e56a5e4165c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions - --> $DIR/cross-crate.rs:17:14 + --> $DIR/cross-crate.rs:18:14 | LL | NonConst.func(); | ^^^^^^ @@ -11,7 +11,7 @@ LL + #![feature(const_trait_impl)] | error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions - --> $DIR/cross-crate.rs:20:11 + --> $DIR/cross-crate.rs:21:11 | LL | Const.func(); | ^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs index da27724007d..64f23824b39 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] pub trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index 29db6109a98..67a936d0882 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-method-body-is-const-same-trait-ck.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `(): ~const Tr` is not satisfied --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | @@ -6,6 +15,6 @@ LL | ().a() | = help: the trait `Tr` is implemented for `()` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs index 8b51f65fd04..be5e66478df 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, rustc_attrs, effects)] +#![feature(const_trait_impl, rustc_attrs, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr new file mode 100644 index 00000000000..4be1160b58c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/do-not-const-check-override.rs:2:43 + | +LL | #![feature(const_trait_impl, rustc_attrs, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs index a74c50cc8fa..5c32eee8737 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete pub const fn foo() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs index d35e9bb7f1e..b354591e007 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] pub trait Foo<Rhs: ?Sized = Self> { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr new file mode 100644 index 00000000000..7ceb3669e59 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/effect-param-infer.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs index aa75aa9c989..d949e4b829f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(effects)] +#![feature(effects)] //~ WARN the feature `effects` is incomplete pub const fn owo() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr new file mode 100644 index 00000000000..f7d5de829b2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/fallback.rs:3:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs index 502062a559c..eed8cdc447c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs @@ -3,7 +3,12 @@ // gate-test-effects // ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test -#![feature(const_trait_impl, effects, core_intrinsics, const_eval_select)] +#![feature( + const_trait_impl, + effects, //~ WARN the feature `effects` is incomplete + core_intrinsics, + const_eval_select +)] // ensure we are passing in the correct host effect in always const contexts. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr new file mode 100644 index 00000000000..8719c5cbcef --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/helloworld.rs:8:5 + | +LL | effects, + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs index 21197fcaa27..9a9016de3a0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs @@ -1,16 +1,15 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete const fn test() -> impl ~const Fn() { //~^ ERROR `~const` can only be applied to `#[const_trait]` traits //~| ERROR `~const` can only be applied to `#[const_trait]` traits - //~| ERROR cycle detected const move || { //~ ERROR const closures are experimental let sl: &[u8] = b"foo"; match sl { [first, remainder @ ..] => { assert_eq!(first, &b'f'); - //~^ ERROR can't compare `&u8` with `&u8` + //~^ ERROR cannot call non-const fn } [] => panic!(), } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr index 2f805110917..3f0ed13d665 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.stderr @@ -1,5 +1,5 @@ error[E0658]: const closures are experimental - --> $DIR/ice-112822-expected-type-for-param.rs:7:5 + --> $DIR/ice-112822-expected-type-for-param.rs:6:5 | LL | const move || { | ^^^^^ @@ -8,6 +8,15 @@ LL | const move || { = help: add `#![feature(const_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-112822-expected-type-for-param.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/ice-112822-expected-type-for-param.rs:3:32 | @@ -22,47 +31,16 @@ LL | const fn test() -> impl ~const Fn() { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0277]: can't compare `&u8` with `&u8` - --> $DIR/ice-112822-expected-type-for-param.rs:12:17 +error[E0015]: cannot call non-const fn `core::panicking::assert_failed::<&u8, &u8>` in constant functions + --> $DIR/ice-112822-expected-type-for-param.rs:11:17 | LL | assert_eq!(first, &b'f'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&u8 == &u8` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the trait `~const PartialEq<&u8>` is not implemented for `&u8` + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0391]: cycle detected when computing type of opaque `test::{opaque#0}` - --> $DIR/ice-112822-expected-type-for-param.rs:3:20 - | -LL | const fn test() -> impl ~const Fn() { - | ^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `test`... - --> $DIR/ice-112822-expected-type-for-param.rs:3:1 - | -LL | const fn test() -> impl ~const Fn() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires promoting constants in MIR for `test`... - --> $DIR/ice-112822-expected-type-for-param.rs:3:1 - | -LL | const fn test() -> impl ~const Fn() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `test`... - --> $DIR/ice-112822-expected-type-for-param.rs:3:1 - | -LL | const fn test() -> impl ~const Fn() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing whether `test::{opaque#0}` is freeze... - = note: ...which requires evaluating trait selection obligation `test::{opaque#0}: core::marker::Freeze`... - = note: ...which again requires computing type of opaque `test::{opaque#0}`, completing the cycle -note: cycle used when computing type of `test::{opaque#0}` - --> $DIR/ice-112822-expected-type-for-param.rs:3:20 - | -LL | const fn test() -> impl ~const Fn() { - | ^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0391, E0658. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs index 85aabe46640..ff3a27c3ee4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete const fn a() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr new file mode 100644 index 00000000000..49c7d395846 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/infer-fallback.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 281cfdaef28..af88a73b4d6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -1,4 +1,6 @@ -//@ check-pass +//@ known-bug: #110395 +// FIXME(effects) check-pass +// FIXME(effects) fix intrinsics const parameter counting #![crate_type = "lib"] #![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr new file mode 100644 index 00000000000..e4a5f368608 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr @@ -0,0 +1,18 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/minicore.rs:8:30 + | +LL | #![feature(const_trait_impl, effects, const_mut_refs)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/minicore.rs:517:27 + | +LL | const fn const_eval_select<ARG: Tuple, F, G, RET>( + | ^^^^^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0094`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs index 929da1ca8fa..84f5f2803e1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete const fn foo() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr index 0745d0304b9..39aa5825611 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/no-explicit-const-params.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params.rs:22:5 | @@ -63,7 +72,7 @@ note: trait defined here, with 0 generic parameters LL | trait Bar { | ^^^ -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted Some errors have detailed explanations: E0107, E0308. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr index eac3ee9e4e2..ab5f7b55a4e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/project.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:1 | @@ -60,6 +69,6 @@ help: consider further restricting `Self` LL | pub trait Uwu: Owo + Uwu { | +++++ -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs index 7bead45b35a..987a162cd6c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs @@ -1,5 +1,5 @@ #![feature(const_trait_impl)] -#![feature(effects)] +#![feature(effects)] //~ WARN the feature `effects` is incomplete struct S; trait T {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr index 3ff1efb5988..f24d7c7a160 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr @@ -8,6 +8,15 @@ LL | impl const dyn T { | = note: only trait implementations may be annotated with `const` +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/span-bug-issue-121418.rs:2:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates --> $DIR/span-bug-issue-121418.rs:7:6 | @@ -39,7 +48,7 @@ note: required because it appears within the type `Mutex<(dyn T + 'static)>` --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL = note: the return type of a function must have a statically known size -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0207, E0277, E0308. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs index 6b5ba5bb624..00465b0f53d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs @@ -1,7 +1,7 @@ //@ check-fail // Fixes #119830 -#![feature(effects)] +#![feature(effects)] //~ WARN the feature `effects` is incomplete #![feature(min_specialization)] #![feature(const_trait_impl)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr index 70dd0350dc4..8d69151bf74 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/spec-effectvar-ice.rs:4:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` --> $DIR/spec-effectvar-ice.rs:12:15 | @@ -55,7 +64,7 @@ LL | impl<T> const Foo for T where T: const Specialize {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 6 previous errors +error: aborting due to 6 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0207. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs index 891e87d3b97..d63dbfbf57d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs @@ -1,5 +1,5 @@ // Regression test for issue #113378. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Trait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr index 4d0b03046d2..33914cb306d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr @@ -54,6 +54,15 @@ LL + #[const_trait] LL | trait NonConst { | -error: aborting due to 4 previous errors +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-fn-const.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 4 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs index 426534deb67..f5fb0fd516a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs @@ -1,6 +1,6 @@ // Regression test for #69615. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] pub trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr index 5b14ef46d25..416ba248a5f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/hir-const-check.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0658]: `?` is not allowed in a `const fn` --> $DIR/hir-const-check.rs:12:9 | @@ -8,6 +17,6 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs new file mode 100644 index 00000000000..ab46d49073c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs @@ -0,0 +1,18 @@ +//@ edition: 2021 +#![feature(effects)] //~ WARN the feature `effects` is incomplete + +trait MyTrait {} + +impl MyTrait for i32 { + async const fn bar(&self) { + //~^ ERROR expected one of `extern` + //~| ERROR functions in trait impls cannot be declared const + //~| ERROR functions cannot be both `const` and `async` + //~| ERROR method `bar` is not a member + //~| ERROR cycle detected when computing type + main8().await; + //~^ ERROR cannot find function + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr new file mode 100644 index 00000000000..011232f30b8 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr @@ -0,0 +1,101 @@ +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` + --> $DIR/ice-120503-async-const-method.rs:7:11 + | +LL | async const fn bar(&self) { + | ------^^^^^ + | | | + | | expected one of `extern`, `fn`, `safe`, or `unsafe` + | help: `const` must come before `async`: `const async` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/ice-120503-async-const-method.rs:7:11 + | +LL | async const fn bar(&self) { + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` + +error: functions cannot be both `const` and `async` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | -^^^^ ^^^^^ `const` because of this + | | + | _____`async` because of this + | | +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____- + +error[E0407]: method `bar` is not a member of trait `MyTrait` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | / async const fn bar(&self) { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____^ not a member of trait `MyTrait` + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-120503-async-const-method.rs:2:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0425]: cannot find function `main8` in this scope + --> $DIR/ice-120503-async-const-method.rs:13:9 + | +LL | main8().await; + | ^^^^^ help: a function with a similar name exists: `main` +... +LL | fn main() {} + | --------- similarly named function `main` defined here + +error[E0391]: cycle detected when computing type of opaque `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires borrow-checking `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`... + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`... + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`... + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}` is freeze... + = note: ...which requires evaluating trait selection obligation `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}: core::marker::Freeze`... + = note: ...which again requires computing type of opaque `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}`, completing the cycle +note: cycle used when computing type of `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0379, E0391, E0407, E0425. +For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.rs new file mode 100644 index 00000000000..a01329278d7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +pub struct Vec3; + +#[const_trait] +pub trait Add { + fn add(self) -> Vec3; +} + +impl Add for Vec3 { + const fn add(self) -> Vec3 { + //~^ ERROR functions in trait impls cannot be declared const + self + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr new file mode 100644 index 00000000000..4fe88f263c8 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-121536-const-method.stderr @@ -0,0 +1,28 @@ +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/ice-121536-const-method.rs:11:5 + | +LL | const fn add(self) -> Vec3 { + | ^^^^^ functions in trait impls cannot be const + | +help: remove the `const` ... + | +LL - const fn add(self) -> Vec3 { +LL + fn add(self) -> Vec3 { + | +help: ... and declare the impl to be const instead + | +LL | impl const Add for Vec3 { + | +++++ + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-121536-const-method.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs index 269fd87ba0d..36c82dfe684 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs @@ -1,5 +1,5 @@ #![feature(const_fmt_arguments_new)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Tr { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr index 85996c21211..9da31486faa 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-79450.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0015]: cannot call non-const fn `_print` in constant functions --> $DIR/issue-79450.rs:9:9 | @@ -7,6 +16,6 @@ LL | println!("lul"); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr index 2edaca60623..ecc994a3fe6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr @@ -1,3 +1,9 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/issue-92111.rs:20:22 + | +LL | const fn a<T: ~const Destruct>(t: T) {} + | ^^^^^^^^ + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/issue-92111.rs:20:32 | @@ -6,6 +12,6 @@ LL | const fn a<T: ~const Destruct>(t: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs index 6153e2770a4..c653e62032e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -3,7 +3,7 @@ //@ run-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr new file mode 100644 index 00000000000..f533fb61aad --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-const-specialized.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs index 9a93d01ed06..40fc3b17ae4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs @@ -1,6 +1,6 @@ // Tests that specializing trait impls must be at least as const as the default impl. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr index e356621ba47..363fbee1f8b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -1,8 +1,17 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-impl-non-const-specialized-impl.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: cannot specialize on const impl with non-const impl --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 | LL | impl Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr index 68eac990aaa..bcccc855aab 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-const-default-const-specialized.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` --> $DIR/non-const-default-const-specialized.rs:27:1 | @@ -7,6 +16,6 @@ LL | impl<T> Value for T { LL | impl const Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index e5b9493b3ce..7404b6a8b11 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specializing-constness-2.rs:1:30 + | +LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0119]: conflicting implementations of trait `A` --> $DIR/specializing-constness-2.rs:20:1 | @@ -16,7 +25,7 @@ LL | <T as A>::a(); = note: expected constant `host` found constant `true` -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0308. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs index 7206a89e5c5..3aabaf137d5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] +#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] //~ WARN the feature `effects` is incomplete #[rustc_specialization_trait] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr index 21e21c2cb71..226295bf949 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -1,8 +1,17 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specializing-constness.rs:1:30 + | +LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: cannot specialize on const impl with non-const impl --> $DIR/specializing-constness.rs:23:1 | LL | impl<T: Spec + Sup> A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs index 31ca9419589..460c2ef6174 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs @@ -1,7 +1,7 @@ //@ revisions: stable unstable #![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index 95129539770..0604b22ecbb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/staged-api.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: trait implementations cannot be const stable yet --> $DIR/staged-api.rs:19:1 | @@ -45,5 +54,5 @@ LL | Unstable::func(); | = help: const-stable functions can only call other const-stable functions -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index c9ca15d5b56..b53e7b6f6ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/staged-api.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn --> $DIR/staged-api.rs:34:5 | @@ -38,5 +47,5 @@ LL | const_context_not_const_stable() | = help: const-stable functions can only call other const-stable functions -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index ac25812c42d..3a36a5b7509 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -10,6 +10,15 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-2.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:10:19 | @@ -32,5 +41,5 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index 5273f7e48eb..beb931570cb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-2.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:10:19 | @@ -20,5 +29,5 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs index 6d57a4f5798..2f26eebbe32 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete //@ revisions: yy yn ny nn #[cfg_attr(any(yy, yn), const_trait)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index 53445d25590..f96e6fb4ae4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -10,6 +10,15 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-2.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0308]: mismatched types --> $DIR/super-traits-fail-2.rs:17:5 | @@ -19,6 +28,6 @@ LL | x.a(); = note: expected constant `host` found constant `true` -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index 681647945d0..ffc259e590e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-2.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0308]: mismatched types --> $DIR/super-traits-fail-2.rs:17:5 | @@ -7,6 +16,6 @@ LL | x.a(); = note: expected constant `host` found constant `true` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index 77aee6a8bb8..cde4b1ff77f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -10,6 +10,15 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-3.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:12:19 | @@ -38,5 +47,5 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^ -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index f737cb243df..6f184018148 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-3.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:12:19 | @@ -20,5 +29,5 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 1e02a135100..f7e85902a41 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete //@ revisions: yy yn ny nn //@[yy] check-pass diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index de7a11cf155..b0a3b39631d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -10,6 +10,15 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-3.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:18:24 | @@ -25,6 +34,6 @@ LL | x.a(); = note: expected constant `host` found constant `true` -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr new file mode 100644 index 00000000000..e354c66919e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits-fail-3.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs index 0515380564d..cfbb8e9f6be 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr new file mode 100644 index 00000000000..2ff1a880d84 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-traits.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs index ad0f10f7ee8..86a2bbe35ed 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs @@ -1,7 +1,7 @@ // Regression test for issue #119700. //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Main { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr new file mode 100644 index 00000000000..70019ce57f2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/tilde-const-assoc-fn-in-trait-impl.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs index 5c8f5f4db3b..0f5729e3daf 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr new file mode 100644 index 00000000000..4ec8dac1f0d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/tilde-const-inherent-assoc-const-fn.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs index b4006783082..c2d3b2036c6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Trait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr new file mode 100644 index 00000000000..1ead23d5c2c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/tilde-const-trait-assoc-tys.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr index b58af6bb9d0..adb1b01f087 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-default-body-stability.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: const `impl` for trait `Try` which is not marked with `#[const_trait]` --> $DIR/trait-default-body-stability.rs:18:12 | @@ -121,7 +130,7 @@ LL | impl const Try for T { | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 10 previous errors +error: aborting due to 10 previous errors; 1 warning emitted Some errors have detailed explanations: E0207, E0284. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index 0141dcfb06f..95c32b12241 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-where-clause-const.rs:7:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | @@ -30,6 +39,6 @@ help: consider further restricting this bound LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() { | ++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs index 65e605a4a2f..afc5b1c8369 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Bar { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr new file mode 100644 index 00000000000..aef4f569d5e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-where-clause-run.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs index 18d0267fed3..59ddc2f748e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr new file mode 100644 index 00000000000..6e9e948e45c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-where-clause-self-referential.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2024/safe-outside-extern.gated.stderr b/tests/ui/rust-2024/safe-outside-extern.gated.stderr new file mode 100644 index 00000000000..ea7aa181445 --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.gated.stderr @@ -0,0 +1,32 @@ +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:8:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:13:5 + | +LL | safe fn foo(); + | ^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:19:5 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: function pointers cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:24:14 + | +LL | type FnPtr = safe fn(i32, i32) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs new file mode 100644 index 00000000000..9ec0c5c70e1 --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.rs @@ -0,0 +1,28 @@ +//@ revisions: gated ungated +#![cfg_attr(gated, feature(unsafe_extern_blocks))] + +safe fn foo() {} +//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier +//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] + +safe static FOO: i32 = 1; +//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier +//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] + +trait Foo { + safe fn foo(); + //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] +} + +impl Foo for () { + safe fn foo() {} + //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] +} + +type FnPtr = safe fn(i32, i32) -> i32; +//~^ ERROR: function pointers cannot be declared with `safe` safety qualifier +//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] + +fn main() {} diff --git a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr new file mode 100644 index 00000000000..908f5b504eb --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr @@ -0,0 +1,83 @@ +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:8:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:13:5 + | +LL | safe fn foo(); + | ^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:19:5 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: function pointers cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:24:14 + | +LL | type FnPtr = safe fn(i32, i32) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe fn foo() {} + | ^^^^ + | + = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/safe-outside-extern.rs:8:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^ + | + = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/safe-outside-extern.rs:13:5 + | +LL | safe fn foo(); + | ^^^^ + | + = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/safe-outside-extern.rs:19:5 + | +LL | safe fn foo() {} + | ^^^^ + | + = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/safe-outside-extern.rs:24:14 + | +LL | type FnPtr = safe fn(i32, i32) -> i32; + | ^^^^ + | + = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/span/recursive-type-field.stderr b/tests/ui/span/recursive-type-field.stderr index 30ba8cde463..323bbd89457 100644 --- a/tests/ui/span/recursive-type-field.stderr +++ b/tests/ui/span/recursive-type-field.stderr @@ -17,7 +17,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ bar: Box<Bar<'a>>, LL | b: Rc<Bar<'a>>, - ... +... LL | struct Bar<'a> { LL ~ y: (Box<Foo<'a>>, Box<Foo<'a>>), | diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs index 621e8576249..62bb0239168 100644 --- a/tests/ui/stability-attribute/missing-const-stability.rs +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -1,5 +1,5 @@ #![feature(staged_api)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete #![stable(feature = "stable", since = "1.0.0")] #[stable(feature = "stable", since = "1.0.0")] diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr index 4cfbe152891..4e488124fe3 100644 --- a/tests/ui/stability-attribute/missing-const-stability.stderr +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -1,3 +1,12 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/missing-const-stability.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + error: function has missing const stability attribute --> $DIR/missing-const-stability.rs:6:1 | @@ -19,5 +28,5 @@ error: associated function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/suggestions/abi-typo.stderr b/tests/ui/suggestions/abi-typo.stderr index ea474e32125..5195c43220b 100644 --- a/tests/ui/suggestions/abi-typo.stderr +++ b/tests/ui/suggestions/abi-typo.stderr @@ -7,7 +7,7 @@ LL | extern "cdedl" fn cdedl() {} | invalid ABI | help: did you mean: `"cdecl"` | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-68049-2.stderr b/tests/ui/suggestions/issue-68049-2.stderr index 449ecabeb7f..91def27bfcd 100644 --- a/tests/ui/suggestions/issue-68049-2.stderr +++ b/tests/ui/suggestions/issue-68049-2.stderr @@ -19,7 +19,7 @@ help: consider changing this to be a mutable reference in the `impl` method and | LL ~ fn example(&mut self, input: &i32); LL | } - ... +... LL | impl Hello for Test2 { LL ~ fn example(&mut self, input: &i32) { | diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr index 26bd6a82e34..3cd438004c8 100644 --- a/tests/ui/tool-attributes/duplicate-diagnostic.stderr +++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr @@ -1,14 +1,14 @@ -error: duplicate diagnostic item in crate `p2`: `Foo`. +error: duplicate diagnostic item in crate `p2`: `Foo` | - = note: the diagnostic item is first defined in crate `p1`. + = note: the diagnostic item is first defined in crate `p1` -error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`. +error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo` --> $DIR/duplicate-diagnostic.rs:12:1 | LL | pub struct Foo {} | ^^^^^^^^^^^^^^ | - = note: the diagnostic item is first defined in crate `p2`. + = note: the diagnostic item is first defined in crate `p2` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/canonical/effect-var.rs b/tests/ui/traits/next-solver/canonical/effect-var.rs index 6d0f09bb9be..d1e3e18cdc8 100644 --- a/tests/ui/traits/next-solver/canonical/effect-var.rs +++ b/tests/ui/traits/next-solver/canonical/effect-var.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(effects)] +#![feature(effects)] //~ WARN the feature `effects` is incomplete #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/next-solver/canonical/effect-var.stderr b/tests/ui/traits/next-solver/canonical/effect-var.stderr new file mode 100644 index 00000000000..994228c51e5 --- /dev/null +++ b/tests/ui/traits/next-solver/canonical/effect-var.stderr @@ -0,0 +1,11 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/effect-var.rs:4:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr index 17ee9398878..5f5aa3ac569 100644 --- a/tests/ui/traits/trait-or-new-type-instead.stderr +++ b/tests/ui/traits/trait-or-new-type-instead.stderr @@ -2,7 +2,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher --> $DIR/trait-or-new-type-instead.rs:1:1 | LL | impl<T> Option<T> { - | ^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | ^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr index ba6eacde68f..d22117165c1 100644 --- a/tests/ui/try-trait/try-operator-on-main.stderr +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -12,7 +12,7 @@ help: consider adding return type | LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> { LL | // error for a `Try` type on a non-`Try` fn - ... +... LL | try_trait_generic::<()>(); LL + LL + Ok(()) diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 5b8a49d22c7..a0430240dc4 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -11,19 +11,6 @@ LL | <i32 as Add<u32>>::add(1, 2); `i32` implements `Add<&i32>` `i32` implements `Add` -error[E0277]: cannot add `u32` to `i32` - --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 - | -LL | <i32 as Add<u32>>::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` - | - = help: the trait `Add<u32>` is not implemented for `i32` - = help: the following other types implement trait `Add<Rhs>`: - `&'a i32` implements `Add<i32>` - `&i32` implements `Add<&i32>` - `i32` implements `Add<&i32>` - `i32` implements `Add` - error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | @@ -68,6 +55,19 @@ help: change the type of the numeric literal from `u32` to `i32` LL | <i32 as Add<i32>>::add(1, 2i32); | ~~~ +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | <i32 as Add<u32>>::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add<u32>` is not implemented for `i32` + = help: the following other types implement trait `Add<Rhs>`: + `&'a i32` implements `Add<i32>` + `&i32` implements `Add<&i32>` + `i32` implements `Add<&i32>` + `i32` implements `Add` + error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index c0fce5c2aaa..926e1c72f2f 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -14,7 +14,7 @@ help: consider introducing a named lifetime parameter | LL ~ fn main<'a>() { LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, - ... +... LL | LL ~ let _: dyn Foo(&'a isize, &'a usize) -> &'a usize; | |
