From 809dc73d90d191c75b24840113797bd4f7e138b3 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 11 Oct 2024 11:54:16 +0100 Subject: [PATCH 01/40] Make asm label blocks safe context `asm!()` is forced to be wrapped inside unsafe. If there's no special treatment, the label blocks would also always be unsafe with no way of opting out. --- .../rustc_mir_build/src/check_unsafety.rs | 39 ++++++++++++++++++- .../src/language-features/asm-goto.md | 4 +- tests/ui/asm/x86_64/goto-block-safe.rs | 23 +++++++++++ tests/ui/asm/x86_64/goto-block-safe.stderr | 14 +++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/ui/asm/x86_64/goto-block-safe.rs create mode 100644 tests/ui/asm/x86_64/goto-block-safe.stderr diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 8512763a595d..2e3169bbf89b 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -541,8 +541,45 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(expr.span, DerefOfRawPointer); } } - ExprKind::InlineAsm { .. } => { + ExprKind::InlineAsm(box InlineAsmExpr { + asm_macro: _, + ref operands, + template: _, + options: _, + line_spans: _, + }) => { self.requires_unsafe(expr.span, UseOfInlineAssembly); + + // For inline asm, do not use `walk_expr`, since we want to handle the label block + // specially. + for op in &**operands { + use rustc_middle::thir::InlineAsmOperand::*; + match op { + In { expr, reg: _ } + | Out { expr: Some(expr), reg: _, late: _ } + | InOut { expr, reg: _, late: _ } => self.visit_expr(&self.thir()[*expr]), + SplitInOut { in_expr, out_expr, reg: _, late: _ } => { + self.visit_expr(&self.thir()[*in_expr]); + if let Some(out_expr) = out_expr { + self.visit_expr(&self.thir()[*out_expr]); + } + } + Out { expr: None, reg: _, late: _ } + | Const { value: _, span: _ } + | SymFn { value: _, span: _ } + | SymStatic { def_id: _ } => {} + Label { block } => { + // Label blocks are safe context. + // `asm!()` is forced to be wrapped inside unsafe. If there's no special + // treatment, the label blocks would also always be unsafe with no way + // of opting out. + self.in_safety_context(SafetyContext::Safe, |this| { + visit::walk_block(this, &this.thir()[*block]) + }); + } + } + } + return; } ExprKind::Adt(box AdtExpr { adt_def, diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md index d72eb7c0c6ef..823118bcae1e 100644 --- a/src/doc/unstable-book/src/language-features/asm-goto.md +++ b/src/doc/unstable-book/src/language-features/asm-goto.md @@ -21,7 +21,9 @@ unsafe { } ``` -The block must have unit type or diverge. +The block must have unit type or diverge. The block starts a new safety context, +so despite outer `unsafe`, you need extra unsafe to perform unsafe operations +within `label `. When `label ` is used together with `noreturn` option, it means that the assembly will not fallthrough. It's allowed to jump to a label within the diff --git a/tests/ui/asm/x86_64/goto-block-safe.rs b/tests/ui/asm/x86_64/goto-block-safe.rs new file mode 100644 index 000000000000..ee833a48a4b1 --- /dev/null +++ b/tests/ui/asm/x86_64/goto-block-safe.rs @@ -0,0 +1,23 @@ +//@ only-x86_64 +//@ needs-asm-support + +#![deny(unreachable_code)] +#![feature(asm_goto)] + +use std::arch::asm; + +fn goto_fallthough() { + unsafe { + asm!( + "/* {} */", + label { + core::hint::unreachable_unchecked(); + //~^ ERROR [E0133] + } + ) + } +} + +fn main() { + goto_fallthough(); +} diff --git a/tests/ui/asm/x86_64/goto-block-safe.stderr b/tests/ui/asm/x86_64/goto-block-safe.stderr new file mode 100644 index 000000000000..49818db7484e --- /dev/null +++ b/tests/ui/asm/x86_64/goto-block-safe.stderr @@ -0,0 +1,14 @@ +error[E0133]: call to unsafe function `unreachable_unchecked` is unsafe and requires unsafe function or block + --> $DIR/goto-block-safe.rs:14:17 + | +LL | unsafe { + | ------ items do not inherit unsafety from separate enclosing items +... +LL | core::hint::unreachable_unchecked(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. From 78bbc648c5b2e6e092167d2ed593cd89f06dd37f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 2 Nov 2024 03:42:10 +0000 Subject: [PATCH 02/40] Fix closure arg extraction in extract_callable_info --- .../src/error_reporting/traits/suggestions.rs | 4 ++-- .../correct-args-on-call-suggestion.rs | 7 +++++++ .../correct-args-on-call-suggestion.stderr | 20 +++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/ui/closures/correct-args-on-call-suggestion.rs create mode 100644 tests/ui/closures/correct-args-on-call-suggestion.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 553bb61ed043..2ce46ed5a798 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1091,7 +1091,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(( DefIdOrName::DefId(def_id), fn_sig.output(), - fn_sig.inputs().map_bound(|inputs| &inputs[1..]), + fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()), )) } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { @@ -1101,7 +1101,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .iter() .find_map(|pred| { if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() - && self.tcx.is_lang_item(proj.projection_term.def_id,LangItem::FnOnceOutput) + && self.tcx.is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) // args tuple will always be args[1] && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() { diff --git a/tests/ui/closures/correct-args-on-call-suggestion.rs b/tests/ui/closures/correct-args-on-call-suggestion.rs new file mode 100644 index 000000000000..fa7915a7c032 --- /dev/null +++ b/tests/ui/closures/correct-args-on-call-suggestion.rs @@ -0,0 +1,7 @@ +// Ensure we give the right args when we suggest calling a closure. + +fn main() { + let x = |a: i32, b: i32| a + b; + let y: i32 = x; + //~^ ERROR mismatched types +} diff --git a/tests/ui/closures/correct-args-on-call-suggestion.stderr b/tests/ui/closures/correct-args-on-call-suggestion.stderr new file mode 100644 index 000000000000..2613c7776b25 --- /dev/null +++ b/tests/ui/closures/correct-args-on-call-suggestion.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/correct-args-on-call-suggestion.rs:5:18 + | +LL | let x = |a: i32, b: i32| a + b; + | ---------------- the found closure +LL | let y: i32 = x; + | --- ^ expected `i32`, found closure + | | + | expected due to this + | + = note: expected type `i32` + found closure `{closure@$DIR/correct-args-on-call-suggestion.rs:4:13: 4:29}` +help: use parentheses to call this closure + | +LL | let y: i32 = x(/* i32 */, /* i32 */); + | ++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From cbacb6d93108a7e5156c8b37d1a78f0dca351606 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 2 Nov 2024 03:53:59 +0000 Subject: [PATCH 03/40] Use extract_callable_info, generalize it to async closure --- .../rustc_hir_typeck/src/method/suggest.rs | 55 +----- .../src/error_reporting/traits/suggestions.rs | 177 ++++++++++-------- .../issue-18343.stderr | 2 +- .../issue-2392.stderr | 14 +- .../issue-32128.stderr | 2 +- .../issue-33784.stderr | 6 +- ...rg-where-it-should-have-been-called.stderr | 4 + 7 files changed, 121 insertions(+), 139 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index eaf40a193a63..4269e8b9f1e5 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -31,6 +31,7 @@ use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span, Symbol, edit_distance, }; +use rustc_trait_selection::error_reporting::traits::DefIdOrName; use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -45,50 +46,6 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem}; use crate::{Expectation, FnCtxt}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { - let tcx = self.tcx; - match ty.kind() { - // Not all of these (e.g., unsafe fns) implement `FnOnce`, - // so we look for these beforehand. - // FIXME(async_closures): These don't impl `FnOnce` by default. - ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(..) => true, - // If it's not a simple function, look for things which implement `FnOnce`. - _ => { - let Some(fn_once) = tcx.lang_items().fn_once_trait() else { - return false; - }; - - // This conditional prevents us from asking to call errors and unresolved types. - // It might seem that we can use `predicate_must_hold_modulo_regions`, - // but since a Dummy binder is used to fill in the FnOnce trait's arguments, - // type resolution always gives a "maybe" here. - if self.autoderef(span, ty).silence_errors().any(|(ty, _)| { - info!("check deref {:?} error", ty); - matches!(ty.kind(), ty::Error(_) | ty::Infer(_)) - }) { - return false; - } - - self.autoderef(span, ty).silence_errors().any(|(ty, _)| { - info!("check deref {:?} impl FnOnce", ty); - self.probe(|_| { - let trait_ref = - ty::TraitRef::new(tcx, fn_once, [ty, self.next_ty_var(span)]); - let poly_trait_ref = ty::Binder::dummy(trait_ref); - let obligation = Obligation::misc( - tcx, - span, - self.body_id, - self.param_env, - poly_trait_ref, - ); - self.predicate_may_hold(&obligation) - }) - }) - } - } - } - fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { self.autoderef(span, ty) .silence_errors() @@ -2365,12 +2322,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_accessible = field.vis.is_accessible_from(scope, tcx); if is_accessible { - if self.is_fn_ty(field_ty, span) { + if let Some((what, _, _)) = self.extract_callable_info(field_ty) { + let what = match what { + DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id), + DefIdOrName::Name(what) => what, + }; let expr_span = expr.span.to(item_name.span); err.multipart_suggestion( format!( - "to call the function stored in `{item_name}`, \ - surround the field access with parentheses", + "to call the {what} stored in `{item_name}`, \ + surround the field access with parentheses", ), vec![ (expr_span.shrink_to_lo(), '('.to_string()), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 2ce46ed5a798..d1d6ad04c423 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1075,93 +1075,110 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)> { // Autoderef is useful here because sometimes we box callables, etc. let Some((def_id_or_name, output, inputs)) = - (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| { - match *found.kind() { - ty::FnPtr(sig_tys, _) => Some(( - DefIdOrName::Name("function pointer"), - sig_tys.output(), - sig_tys.inputs(), - )), - ty::FnDef(def_id, _) => { - let fn_sig = found.fn_sig(self.tcx); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) - } - ty::Closure(def_id, args) => { - let fn_sig = args.as_closure().sig(); - Some(( - DefIdOrName::DefId(def_id), - fn_sig.output(), - fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()), - )) - } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - self.tcx - .item_super_predicates(def_id) - .instantiate(self.tcx, args) - .iter() - .find_map(|pred| { - if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() - && self.tcx.is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) - // args tuple will always be args[1] - && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() - { - Some(( - DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.expect_type()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - ty::Dynamic(data, _, ty::Dyn) => { - data.iter().find_map(|pred| { - if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() + (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| match *found.kind() { + ty::FnPtr(sig_tys, _) => Some(( + DefIdOrName::Name("function pointer"), + sig_tys.output(), + sig_tys.inputs(), + )), + ty::FnDef(def_id, _) => { + let fn_sig = found.fn_sig(self.tcx); + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) + } + ty::Closure(def_id, args) => { + let fn_sig = args.as_closure().sig(); + Some(( + DefIdOrName::DefId(def_id), + fn_sig.output(), + fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()), + )) + } + ty::CoroutineClosure(def_id, args) => { + let sig_parts = args.as_coroutine_closure().coroutine_closure_sig(); + Some(( + DefIdOrName::DefId(def_id), + sig_parts.map_bound(|sig| { + sig.to_coroutine( + self.tcx, + args.as_coroutine_closure().parent_args(), + // Just use infer vars here, since we don't really care + // what these types are, just that we're returning a coroutine. + self.next_ty_var(DUMMY_SP), + self.tcx.coroutine_for_closure(def_id), + self.next_ty_var(DUMMY_SP), + ) + }), + sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()), + )) + } + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self + .tcx + .item_super_predicates(def_id) + .instantiate(self.tcx, args) + .iter() + .find_map(|pred| { + if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() + && self + .tcx + .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) + // args tuple will always be args[1] + && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() + { + Some(( + DefIdOrName::DefId(def_id), + pred.kind().rebind(proj.term.expect_type()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }), + ty::Dynamic(data, _, ty::Dyn) => data.iter().find_map(|pred| { + if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput) // for existential projection, args are shifted over by 1 && let ty::Tuple(args) = proj.args.type_at(0).kind() - { - Some(( - DefIdOrName::Name("trait object"), - pred.rebind(proj.term.expect_type()), - pred.rebind(args.as_slice()), - )) - } else { - None - } - }) + { + Some(( + DefIdOrName::Name("trait object"), + pred.rebind(proj.term.expect_type()), + pred.rebind(args.as_slice()), + )) + } else { + None } - ty::Param(param) => { - let generics = self.tcx.generics_of(body_id); - let name = if generics.count() > param.index as usize - && let def = generics.param_at(param.index as usize, self.tcx) - && matches!(def.kind, ty::GenericParamDefKind::Type { .. }) - && def.name == param.name + }), + ty::Param(param) => { + let generics = self.tcx.generics_of(body_id); + let name = if generics.count() > param.index as usize + && let def = generics.param_at(param.index as usize, self.tcx) + && matches!(def.kind, ty::GenericParamDefKind::Type { .. }) + && def.name == param.name + { + DefIdOrName::DefId(def.def_id) + } else { + DefIdOrName::Name("type parameter") + }; + param_env.caller_bounds().iter().find_map(|pred| { + if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() + && self + .tcx + .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) + && proj.projection_term.self_ty() == found + // args tuple will always be args[1] + && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() { - DefIdOrName::DefId(def.def_id) + Some(( + name, + pred.kind().rebind(proj.term.expect_type()), + pred.kind().rebind(args.as_slice()), + )) } else { - DefIdOrName::Name("type parameter") - }; - param_env.caller_bounds().iter().find_map(|pred| { - if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() - && self.tcx.is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) - && proj.projection_term.self_ty() == found - // args tuple will always be args[1] - && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() - { - Some(( - name, - pred.kind().rebind(proj.term.expect_type()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - _ => None, + None + } + }) } + _ => None, }) else { return None; diff --git a/tests/ui/confuse-field-and-method/issue-18343.stderr b/tests/ui/confuse-field-and-method/issue-18343.stderr index a51fd4f02aab..e50c971d837b 100644 --- a/tests/ui/confuse-field-and-method/issue-18343.stderr +++ b/tests/ui/confuse-field-and-method/issue-18343.stderr @@ -7,7 +7,7 @@ LL | struct Obj where F: FnMut() -> u32 { LL | o.closure(); | ^^^^^^^ field, not a method | -help: to call the function stored in `closure`, surround the field access with parentheses +help: to call the closure stored in `closure`, surround the field access with parentheses | LL | (o.closure)(); | + + diff --git a/tests/ui/confuse-field-and-method/issue-2392.stderr b/tests/ui/confuse-field-and-method/issue-2392.stderr index 440fbb27c004..77930de44a77 100644 --- a/tests/ui/confuse-field-and-method/issue-2392.stderr +++ b/tests/ui/confuse-field-and-method/issue-2392.stderr @@ -7,7 +7,7 @@ LL | struct Obj where F: FnOnce() -> u32 { LL | o_closure.closure(); | ^^^^^^^ field, not a method | -help: to call the function stored in `closure`, surround the field access with parentheses +help: to call the closure stored in `closure`, surround the field access with parentheses | LL | (o_closure.closure)(); | + + @@ -46,7 +46,7 @@ LL | struct BoxedObj { LL | boxed_fn.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method | -help: to call the function stored in `boxed_closure`, surround the field access with parentheses +help: to call the trait object stored in `boxed_closure`, surround the field access with parentheses | LL | (boxed_fn.boxed_closure)(); | + + @@ -60,7 +60,7 @@ LL | struct BoxedObj { LL | boxed_closure.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method | -help: to call the function stored in `boxed_closure`, surround the field access with parentheses +help: to call the trait object stored in `boxed_closure`, surround the field access with parentheses | LL | (boxed_closure.boxed_closure)(); | + + @@ -99,7 +99,7 @@ LL | struct Obj where F: FnOnce() -> u32 { LL | check_expression().closure(); | ^^^^^^^ field, not a method | -help: to call the function stored in `closure`, surround the field access with parentheses +help: to call the trait object stored in `closure`, surround the field access with parentheses | LL | (check_expression().closure)(); | + + @@ -113,7 +113,7 @@ LL | struct FuncContainer { LL | (*self.container).f1(1); | ^^ field, not a method | -help: to call the function stored in `f1`, surround the field access with parentheses +help: to call the function pointer stored in `f1`, surround the field access with parentheses | LL | ((*self.container).f1)(1); | + + @@ -127,7 +127,7 @@ LL | struct FuncContainer { LL | (*self.container).f2(1); | ^^ field, not a method | -help: to call the function stored in `f2`, surround the field access with parentheses +help: to call the function pointer stored in `f2`, surround the field access with parentheses | LL | ((*self.container).f2)(1); | + + @@ -141,7 +141,7 @@ LL | struct FuncContainer { LL | (*self.container).f3(1); | ^^ field, not a method | -help: to call the function stored in `f3`, surround the field access with parentheses +help: to call the function pointer stored in `f3`, surround the field access with parentheses | LL | ((*self.container).f3)(1); | + + diff --git a/tests/ui/confuse-field-and-method/issue-32128.stderr b/tests/ui/confuse-field-and-method/issue-32128.stderr index 3d860d8c85a1..aaec15a41dce 100644 --- a/tests/ui/confuse-field-and-method/issue-32128.stderr +++ b/tests/ui/confuse-field-and-method/issue-32128.stderr @@ -7,7 +7,7 @@ LL | struct Example { LL | demo.example(1); | ^^^^^^^ field, not a method | -help: to call the function stored in `example`, surround the field access with parentheses +help: to call the trait object stored in `example`, surround the field access with parentheses | LL | (demo.example)(1); | + + diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr index 8acd1f8ff1ee..59a6f4fccd8d 100644 --- a/tests/ui/confuse-field-and-method/issue-33784.stderr +++ b/tests/ui/confuse-field-and-method/issue-33784.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `closure` found for reference `&Obj<{closure@$DIR/ LL | p.closure(); | ^^^^^^^ field, not a method | -help: to call the function stored in `closure`, surround the field access with parentheses +help: to call the closure stored in `closure`, surround the field access with parentheses | LL | (p.closure)(); | + + @@ -19,7 +19,7 @@ error[E0599]: no method named `fn_ptr` found for reference `&&Obj<{closure@$DIR/ LL | q.fn_ptr(); | ^^^^^^ field, not a method | -help: to call the function stored in `fn_ptr`, surround the field access with parentheses +help: to call the function pointer stored in `fn_ptr`, surround the field access with parentheses | LL | (q.fn_ptr)(); | + + @@ -30,7 +30,7 @@ error[E0599]: no method named `c_fn_ptr` found for reference `&D` in the current LL | s.c_fn_ptr(); | ^^^^^^^^ field, not a method | -help: to call the function stored in `c_fn_ptr`, surround the field access with parentheses +help: to call the function pointer stored in `c_fn_ptr`, surround the field access with parentheses | LL | (s.c_fn_ptr)(); | + + diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 05e087fd9f9a..a040e71cf3b2 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -31,6 +31,10 @@ note: required by a bound in `bar` | LL | fn bar(f: impl Future) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` +help: use parentheses to call this closure + | +LL | bar(async_closure()); + | ++ error: aborting due to 2 previous errors From b071f6405cd7622b12bd45c4d6d77c7663a97816 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 15 Oct 2024 14:40:59 +0200 Subject: [PATCH 04/40] Emscripten: link with -sWASM_BIGINT When linking an executable without dynamic linking, this is a pure improvement. It significantly reduces code size and avoids a lot of buggy behaviors. It is supported in all browsers for many years and in all maintained versions of Node. It does change the ABI, so people who are dynamically linking with a library or executable that uses the old ABI may need to turn it off. It can be disabled if needed by passing `-Clink-arg -sWASM_BIGINT=0` to `rustc`. But few people will want to turn it off. --- .../src/spec/targets/wasm32_unknown_emscripten.rs | 3 ++- library/Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index a213adadbea7..a70cebbd9c88 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -5,7 +5,8 @@ use crate::spec::{ pub(crate) fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. let pre_link_args = LinkArgs::new(); - let post_link_args = TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0"]); + let post_link_args = + TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0", "-sWASM_BIGINT"]); let opts = TargetOptions { os: "emscripten".into(), diff --git a/library/Cargo.lock b/library/Cargo.lock index 772f9b196956..84c20ec6f876 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index b732fdf16968..c1ab70b714a4 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -34,7 +34,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.161", default-features = false, features = [ +libc = { version = "0.2.162", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } From 7652e349b091531ceb91eae8de23fb86ac7c0b09 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 14 Nov 2024 22:14:11 +0900 Subject: [PATCH 05/40] Support s390x z13 vector ABI --- compiler/rustc_abi/src/layout/ty.rs | 18 + compiler/rustc_target/src/callconv/s390x.rs | 26 +- .../spec/targets/s390x_unknown_linux_gnu.rs | 3 - .../spec/targets/s390x_unknown_linux_musl.rs | 3 - tests/assembly/s390x-vector-abi.rs | 322 ++++++++++++++++++ tests/ui/simd-abi-checks-s390x.rs | 174 ++++++++++ tests/ui/simd-abi-checks-s390x.z10.stderr | 111 ++++++ ...simd-abi-checks-s390x.z13_no_vector.stderr | 111 ++++++ ...imd-abi-checks-s390x.z13_soft_float.stderr | 111 ++++++ 9 files changed, 865 insertions(+), 14 deletions(-) create mode 100644 tests/assembly/s390x-vector-abi.rs create mode 100644 tests/ui/simd-abi-checks-s390x.rs create mode 100644 tests/ui/simd-abi-checks-s390x.z10.stderr create mode 100644 tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr create mode 100644 tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 062447ea03f0..d188750bfe10 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -209,6 +209,24 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { } } + pub fn is_single_vector_element(self, cx: &C, expected_size: Size) -> bool + where + Ty: TyAbiInterface<'a, C>, + C: HasDataLayout, + { + match self.backend_repr { + BackendRepr::Vector { .. } => self.size == expected_size, + BackendRepr::Memory { .. } => { + if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { + self.field(cx, 0).is_single_vector_element(cx, expected_size) + } else { + false + } + } + _ => false, + } + } + pub fn is_adt(self) -> bool where Ty: TyAbiInterface<'a, C>, diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index 502e73312677..c99eb9226eff 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -1,12 +1,16 @@ -// FIXME: The assumes we're using the non-vector ABI, i.e., compiling -// for a pre-z13 machine or using -mno-vx. +// Reference: ELF Application Binary Interface s390x Supplement +// https://github.com/IBM/s390x-abi -use crate::abi::call::{ArgAbi, FnAbi, Reg}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind}; +use crate::abi::{BackendRepr, HasDataLayout, TyAbiInterface}; use crate::spec::HasTargetSpec; fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { - if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 { + let size = ret.layout.size; + if size.bits() <= 128 && matches!(ret.layout.backend_repr, BackendRepr::Vector { .. }) { + return; + } + if !ret.layout.is_aggregate() && size.bits() <= 64 { ret.extend_integer_width_to(64); } else { ret.make_indirect(); @@ -32,19 +36,25 @@ where } return; } - if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { + + let size = arg.layout.size; + if size.bits() <= 128 && arg.layout.is_single_vector_element(cx, size) { + arg.cast_to(Reg { kind: RegKind::Vector, size }); + return; + } + if !arg.layout.is_aggregate() && size.bits() <= 64 { arg.extend_integer_width_to(64); return; } if arg.layout.is_single_fp_element(cx) { - match arg.layout.size.bytes() { + match size.bytes() { 4 => arg.cast_to(Reg::f32()), 8 => arg.cast_to(Reg::f64()), _ => arg.make_indirect(), } } else { - match arg.layout.size.bytes() { + match size.bytes() { 1 => arg.cast_to(Reg::i8()), 2 => arg.cast_to(Reg::i16()), 4 => arg.cast_to(Reg::i32()), diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index 3efbb4648361..a84a18a433ff 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. - base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 65b5c1167bdd..4bde0fb729c7 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. - base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); base.static_position_independent_executables = true; diff --git a/tests/assembly/s390x-vector-abi.rs b/tests/assembly/s390x-vector-abi.rs new file mode 100644 index 000000000000..c1935582561f --- /dev/null +++ b/tests/assembly/s390x-vector-abi.rs @@ -0,0 +1,322 @@ +//@ revisions: z10 z10_vector z13 z13_no_vector +// ignore-tidy-linelength +//@ assembly-output: emit-asm +//@ compile-flags: -O -Z merge-functions=disabled +//@[z10] compile-flags: --target s390x-unknown-linux-gnu --cfg no_vector +//@[z10] needs-llvm-components: systemz +//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[z10_vector] needs-llvm-components: systemz +//@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 +//@[z13] needs-llvm-components: systemz +//@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector --cfg no_vector +//@[z13_no_vector] needs-llvm-components: systemz + +#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![no_core] +#![crate_type = "lib"] +#![allow(non_camel_case_types)] + +// Cases where vector feature is disabled are rejected. +// See tests/ui/simd-abi-checks-s390x.rs for test for them. + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub trait Freeze {} + +impl Copy for [T; N] {} + +#[lang = "phantom_data"] +pub struct PhantomData; +impl Copy for PhantomData {} + +#[repr(simd)] +pub struct i8x8([i8; 8]); +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i8x32([i8; 32]); +#[repr(C)] +pub struct Wrapper(T); +#[repr(C, align(16))] +pub struct WrapperAlign16(T); +#[repr(C)] +pub struct WrapperWithZst(T, PhantomData<()>); +#[repr(transparent)] +pub struct TransparentWrapper(T); + +impl Copy for i8 {} +impl Copy for i64 {} +impl Copy for i8x8 {} +impl Copy for i8x16 {} +impl Copy for i8x32 {} +impl Copy for Wrapper {} +impl Copy for WrapperAlign16 {} +impl Copy for WrapperWithZst {} +impl Copy for TransparentWrapper {} + +// CHECK-LABEL: vector_ret_small: +// CHECK: vlrepg %v24, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + *x +} +// CHECK-LABEL: vector_ret: +// CHECK: vl %v24, 0(%r2), 3 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + *x +} +// CHECK-LABEL: vector_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 0(%r3), 4 +// z13-NEXT: vl %v1, 16(%r3), 4 +// z13-NEXT: vst %v1, 16(%r2), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 { + *x +} + +// CHECK-LABEL: vector_wrapper_ret_small: +// CHECK: mvc 0(8,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret_small(x: &Wrapper) -> Wrapper { + *x +} +// CHECK-LABEL: vector_wrapper_ret: +// CHECK: mvc 0(16,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret(x: &Wrapper) -> Wrapper { + *x +} +// CHECK-LABEL: vector_wrapper_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 16(%r3), 4 +// z13-NEXT: vst %v0, 16(%r2), 4 +// z13-NEXT: vl %v0, 0(%r3), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret_large(x: &Wrapper) -> Wrapper { + *x +} + +// CHECK-LABEL: vector_wrapper_padding_ret: +// CHECK: mvc 0(16,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_padding_ret(x: &WrapperAlign16) -> WrapperAlign16 { + *x +} + +// CHECK-LABEL: vector_wrapper_with_zst_ret_small: +// CHECK: mvc 0(8,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_ret_small( + x: &WrapperWithZst, +) -> WrapperWithZst { + *x +} +// CHECK-LABEL: vector_wrapper_with_zst_ret: +// CHECK: mvc 0(16,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_ret( + x: &WrapperWithZst, +) -> WrapperWithZst { + *x +} +// CHECK-LABEL: vector_wrapper_with_zst_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 16(%r3), 4 +// z13-NEXT: vst %v0, 16(%r2), 4 +// z13-NEXT: vl %v0, 0(%r3), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_ret_large( + x: &WrapperWithZst, +) -> WrapperWithZst { + *x +} + +// CHECK-LABEL: vector_transparent_wrapper_ret_small: +// CHECK: vlrepg %v24, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret_small( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} +// CHECK-LABEL: vector_transparent_wrapper_ret: +// CHECK: vl %v24, 0(%r2), 3 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} +// CHECK-LABEL: vector_transparent_wrapper_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 0(%r3), 4 +// z13-NEXT: vl %v1, 16(%r3), 4 +// z13-NEXT: vst %v1, 16(%r2), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret_large( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} + +// CHECK-LABEL: vector_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg_small(x: i8x8) -> i64 { + unsafe { *(&x as *const i8x8 as *const i64) } +} +// CHECK-LABEL: vector_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg(x: i8x16) -> i64 { + unsafe { *(&x as *const i8x16 as *const i64) } +} +// CHECK-LABEL: vector_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg_large(x: i8x32) -> i64 { + unsafe { *(&x as *const i8x32 as *const i64) } +} + +// CHECK-LABEL: vector_wrapper_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} +// CHECK-LABEL: vector_wrapper_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} +// CHECK-LABEL: vector_wrapper_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg_large(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} + +// https://github.com/rust-lang/rust/pull/131586#discussion_r1837071121 +// CHECK-LABEL: vector_wrapper_padding_arg: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_padding_arg(x: WrapperAlign16) -> i64 { + unsafe { *(&x as *const WrapperAlign16 as *const i64) } +} + +// CHECK-LABEL: vector_wrapper_with_zst_arg_small: +// CHECK: .cfi_startproc +// CHECK-NOT: vlgvg +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst) -> i64 { + unsafe { *(&x as *const WrapperWithZst as *const i64) } +} +// CHECK-LABEL: vector_wrapper_with_zst_arg: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_arg(x: WrapperWithZst) -> i64 { + unsafe { *(&x as *const WrapperWithZst as *const i64) } +} +// CHECK-LABEL: vector_wrapper_with_zst_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_with_zst_arg_large(x: WrapperWithZst) -> i64 { + unsafe { *(&x as *const WrapperWithZst as *const i64) } +} + +// CHECK-LABEL: vector_transparent_wrapper_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +// CHECK-LABEL: vector_transparent_wrapper_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +// CHECK-LABEL: vector_transparent_wrapper_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} diff --git a/tests/ui/simd-abi-checks-s390x.rs b/tests/ui/simd-abi-checks-s390x.rs new file mode 100644 index 000000000000..15df66a2ceda --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.rs @@ -0,0 +1,174 @@ +//@ revisions: z10 z13_no_vector z13_soft_float +//@ build-fail +//@[z10] compile-flags: --target s390x-unknown-linux-gnu +//@[z10] needs-llvm-components: systemz +//@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector +//@[z13_no_vector] needs-llvm-components: systemz +// FIXME: +soft-float itself doesn't set -vector +//@[z13_soft_float] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector,+soft-float +//@[z13_soft_float] needs-llvm-components: systemz + +#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![no_core] +#![crate_type = "lib"] +#![allow(non_camel_case_types, improper_ctypes_definitions)] +#![deny(abi_unsupported_vector_types)] + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub trait Freeze {} + +impl Copy for [T; N] {} + +#[repr(simd)] +pub struct i8x8([i8; 8]); +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i8x32([i8; 32]); +#[repr(C)] +pub struct Wrapper(T); +#[repr(transparent)] +pub struct TransparentWrapper(T); + +impl Copy for i8 {} +impl Copy for i64 {} +impl Copy for i8x8 {} +impl Copy for i8x16 {} +impl Copy for i8x32 {} +impl Copy for Wrapper {} +impl Copy for TransparentWrapper {} + +#[no_mangle] +extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + *x +} +#[no_mangle] +extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + *x +} +#[no_mangle] +extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 { + // Ok + *x +} + +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_ret_target_feature_small(x: &i8x8) -> i8x8 { + // Ok + *x +} +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_target_feature_ret(x: &i8x16) -> i8x16 { + // Ok + *x +} +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_ret_target_feature_large(x: &i8x32) -> i8x32 { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_wrapper_ret_small(x: &Wrapper) -> Wrapper { + // Ok + *x +} +#[no_mangle] +extern "C" fn vector_wrapper_ret(x: &Wrapper) -> Wrapper { + // Ok + *x +} +#[no_mangle] +extern "C" fn vector_wrapper_ret_large(x: &Wrapper) -> Wrapper { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret_small( + x: &TransparentWrapper, +) -> TransparentWrapper { + //~^^^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^^^ WARN this was previously accepted + *x +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret( + x: &TransparentWrapper, +) -> TransparentWrapper { + //~^^^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^^^ WARN this was previously accepted + *x +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret_large( + x: &TransparentWrapper, +) -> TransparentWrapper { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_arg_small(x: i8x8) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const i8x8 as *const i64) } +} +#[no_mangle] +extern "C" fn vector_arg(x: i8x16) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const i8x16 as *const i64) } +} +#[no_mangle] +extern "C" fn vector_arg_large(x: i8x32) -> i64 { + // Ok + unsafe { *(&x as *const i8x32 as *const i64) } +} + +#[no_mangle] +extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const Wrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const Wrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_wrapper_arg_large(x: Wrapper) -> i64 { + // Ok + unsafe { *(&x as *const Wrapper as *const i64) } +} + +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + //~^ ERROR this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + //~^^ WARN this was previously accepted + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper) -> i64 { + // Ok + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} diff --git a/tests/ui/simd-abi-checks-s390x.z10.stderr b/tests/ui/simd-abi-checks-s390x.z10.stderr new file mode 100644 index 000000000000..a91322ec0583 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z10.stderr @@ -0,0 +1,111 @@ +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:46:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) +note: the lint level is defined here + --> $DIR/simd-abi-checks-s390x.rs:15:9 + | +LL | #![deny(abi_unsupported_vector_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:52:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:99:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:107:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:129:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:141:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:147:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:159:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:165:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: aborting due to 10 previous errors + diff --git a/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr new file mode 100644 index 000000000000..a91322ec0583 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr @@ -0,0 +1,111 @@ +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:46:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) +note: the lint level is defined here + --> $DIR/simd-abi-checks-s390x.rs:15:9 + | +LL | #![deny(abi_unsupported_vector_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:52:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:99:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:107:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:129:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:141:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:147:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:159:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:165:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: aborting due to 10 previous errors + diff --git a/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr new file mode 100644 index 000000000000..a91322ec0583 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr @@ -0,0 +1,111 @@ +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:46:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) +note: the lint level is defined here + --> $DIR/simd-abi-checks-s390x.rs:15:9 + | +LL | #![deny(abi_unsupported_vector_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:52:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:99:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:107:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:129:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:141:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:147:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:159:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:165:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) + +error: aborting due to 10 previous errors + From 98ab898d30f0914aa9bc0c3864dc059d45c2c7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 15 Nov 2024 18:49:43 +0100 Subject: [PATCH 06/40] tests: ui/inline-consts: add issue number to a test, rename other tests from a_b_c to a-b-c --- ...liveness.rs => const-block-pat-liveness.rs} | 0 ...w.rs => cross-const-control-flow-125846.rs} | 0 ... => cross-const-control-flow-125846.stderr} | 18 +++++++++--------- ...ables.rs => referencing-local-variables.rs} | 0 ...derr => referencing-local-variables.stderr} | 2 +- .../{uninit_local.rs => uninit-local.rs} | 0 ...uninit_local.stderr => uninit-local.stderr} | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename tests/ui/inline-const/{const_block_pat_liveness.rs => const-block-pat-liveness.rs} (100%) rename tests/ui/inline-const/{cross_const_control_flow.rs => cross-const-control-flow-125846.rs} (100%) rename tests/ui/inline-const/{cross_const_control_flow.stderr => cross-const-control-flow-125846.stderr} (82%) rename tests/ui/inline-const/{referencing_local_variables.rs => referencing-local-variables.rs} (100%) rename tests/ui/inline-const/{referencing_local_variables.stderr => referencing-local-variables.stderr} (87%) rename tests/ui/inline-const/{uninit_local.rs => uninit-local.rs} (100%) rename tests/ui/inline-const/{uninit_local.stderr => uninit-local.stderr} (93%) diff --git a/tests/ui/inline-const/const_block_pat_liveness.rs b/tests/ui/inline-const/const-block-pat-liveness.rs similarity index 100% rename from tests/ui/inline-const/const_block_pat_liveness.rs rename to tests/ui/inline-const/const-block-pat-liveness.rs diff --git a/tests/ui/inline-const/cross_const_control_flow.rs b/tests/ui/inline-const/cross-const-control-flow-125846.rs similarity index 100% rename from tests/ui/inline-const/cross_const_control_flow.rs rename to tests/ui/inline-const/cross-const-control-flow-125846.rs diff --git a/tests/ui/inline-const/cross_const_control_flow.stderr b/tests/ui/inline-const/cross-const-control-flow-125846.stderr similarity index 82% rename from tests/ui/inline-const/cross_const_control_flow.stderr rename to tests/ui/inline-const/cross-const-control-flow-125846.stderr index ecfa921edd2c..4aa1c273504c 100644 --- a/tests/ui/inline-const/cross_const_control_flow.stderr +++ b/tests/ui/inline-const/cross-const-control-flow-125846.stderr @@ -1,5 +1,5 @@ error[E0767]: use of unreachable label `'a` - --> $DIR/cross_const_control_flow.rs:9:25 + --> $DIR/cross-const-control-flow-125846.rs:9:25 | LL | 'a: { const { break 'a } } | -- ^^ unreachable label `'a` @@ -9,7 +9,7 @@ LL | 'a: { const { break 'a } } = note: labels are unreachable through functions, closures, async blocks and modules error[E0767]: use of unreachable label `'a` - --> $DIR/cross_const_control_flow.rs:22:28 + --> $DIR/cross-const-control-flow-125846.rs:22:28 | LL | 'a: { const { continue 'a } } | -- ^^ unreachable label `'a` @@ -19,7 +19,7 @@ LL | 'a: { const { continue 'a } } = note: labels are unreachable through functions, closures, async blocks and modules error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/cross_const_control_flow.rs:41:14 + --> $DIR/cross-const-control-flow-125846.rs:41:14 | LL | const { &x }; | ^ non-constant value @@ -30,7 +30,7 @@ LL | const x: /* Type */ = 1; | ~~~~~ ++++++++++++ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/cross_const_control_flow.rs:35:22 + --> $DIR/cross-const-control-flow-125846.rs:35:22 | LL | const { async {}.await } | -----------^^^^^-- @@ -39,31 +39,31 @@ LL | const { async {}.await } | this is not `async` error[E0268]: `break` outside of a loop or labeled block - --> $DIR/cross_const_control_flow.rs:9:19 + --> $DIR/cross-const-control-flow-125846.rs:9:19 | LL | 'a: { const { break 'a } } | ^^^^^^^^ cannot `break` outside of a loop or labeled block error[E0268]: `break` outside of a loop or labeled block - --> $DIR/cross_const_control_flow.rs:16:17 + --> $DIR/cross-const-control-flow-125846.rs:16:17 | LL | const { break } | ^^^^^ cannot `break` outside of a loop or labeled block error[E0268]: `continue` outside of a loop - --> $DIR/cross_const_control_flow.rs:22:19 + --> $DIR/cross-const-control-flow-125846.rs:22:19 | LL | 'a: { const { continue 'a } } | ^^^^^^^^^^^ cannot `continue` outside of a loop error[E0268]: `continue` outside of a loop - --> $DIR/cross_const_control_flow.rs:29:17 + --> $DIR/cross-const-control-flow-125846.rs:29:17 | LL | const { continue } | ^^^^^^^^ cannot `continue` outside of a loop error[E0572]: return statement outside of function body - --> $DIR/cross_const_control_flow.rs:4:13 + --> $DIR/cross-const-control-flow-125846.rs:4:13 | LL | / fn foo() { LL | | const { return } diff --git a/tests/ui/inline-const/referencing_local_variables.rs b/tests/ui/inline-const/referencing-local-variables.rs similarity index 100% rename from tests/ui/inline-const/referencing_local_variables.rs rename to tests/ui/inline-const/referencing-local-variables.rs diff --git a/tests/ui/inline-const/referencing_local_variables.stderr b/tests/ui/inline-const/referencing-local-variables.stderr similarity index 87% rename from tests/ui/inline-const/referencing_local_variables.stderr rename to tests/ui/inline-const/referencing-local-variables.stderr index 4a0a54066024..7e1cecdddcba 100644 --- a/tests/ui/inline-const/referencing_local_variables.stderr +++ b/tests/ui/inline-const/referencing-local-variables.stderr @@ -1,5 +1,5 @@ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/referencing_local_variables.rs:2:13 + --> $DIR/referencing-local-variables.rs:2:13 | LL | const fn test_me(a: usize) -> usize { | - this would need to be a `const` diff --git a/tests/ui/inline-const/uninit_local.rs b/tests/ui/inline-const/uninit-local.rs similarity index 100% rename from tests/ui/inline-const/uninit_local.rs rename to tests/ui/inline-const/uninit-local.rs diff --git a/tests/ui/inline-const/uninit_local.stderr b/tests/ui/inline-const/uninit-local.stderr similarity index 93% rename from tests/ui/inline-const/uninit_local.stderr rename to tests/ui/inline-const/uninit-local.stderr index 37b78e337e7b..fab65ffb5fa0 100644 --- a/tests/ui/inline-const/uninit_local.stderr +++ b/tests/ui/inline-const/uninit-local.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/uninit_local.rs:4:15 + --> $DIR/uninit-local.rs:4:15 | LL | let x: bool; | - binding declared here but left uninitialized From f2f7d329485d966fd5b2d207fca5e94c315a362f Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:32:16 -0300 Subject: [PATCH 07/40] FieldDef --- compiler/rustc_ast/src/mut_visit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a09aa9ee6651..578b9bbe199f 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -116,6 +116,10 @@ pub trait MutVisitor: Sized { walk_fn_header(self, header); } + fn visit_field_def(&mut self, fd: &mut FieldDef) { + walk_field_def(self, fd); + } + fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> { walk_flat_map_field_def(self, fd) } @@ -1050,17 +1054,21 @@ fn walk_poly_trait_ref(vis: &mut T, p: &mut PolyTraitRef) { vis.visit_span(span); } -pub fn walk_flat_map_field_def( - visitor: &mut T, - mut fd: FieldDef, -) -> SmallVec<[FieldDef; 1]> { - let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd; +pub fn walk_field_def(visitor: &mut T, fd: &mut FieldDef) { + let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = fd; visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_ty(ty); visitor.visit_span(span); +} + +pub fn walk_flat_map_field_def( + vis: &mut T, + mut fd: FieldDef, +) -> SmallVec<[FieldDef; 1]> { + vis.visit_field_def(&mut fd); smallvec![fd] } From b96758bb71cfb71b3e335b07d86389f53414f1c0 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:37:48 -0300 Subject: [PATCH 08/40] Arm --- compiler/rustc_ast/src/mut_visit.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 578b9bbe199f..5ff65e9d44d7 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -157,6 +157,10 @@ pub trait MutVisitor: Sized { walk_flat_map_stmt(self, s) } + fn visit_arm(&mut self, arm: &mut Arm) { + walk_arm(self, arm); + } + fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { walk_flat_map_arm(self, arm) } @@ -459,14 +463,18 @@ fn walk_use_tree(vis: &mut T, use_tree: &mut UseTree) { vis.visit_span(span); } -pub fn walk_flat_map_arm(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> { - let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; +pub fn walk_arm(vis: &mut T, arm: &mut Arm) { + let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); visit_opt(body, |body| vis.visit_expr(body)); vis.visit_span(span); +} + +pub fn walk_flat_map_arm(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> { + vis.visit_arm(&mut arm); smallvec![arm] } From e52cef19a4b2a83e803ce8d2d5b1189e2b848d0d Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:41:16 -0300 Subject: [PATCH 09/40] Variant --- compiler/rustc_ast/src/mut_visit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 5ff65e9d44d7..735002e25a50 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -207,6 +207,10 @@ pub trait MutVisitor: Sized { walk_foreign_mod(self, nm); } + fn visit_variant(&mut self, v: &mut Variant) { + walk_variant(self, v); + } + fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { walk_flat_map_variant(self, v) } @@ -551,11 +555,8 @@ fn walk_foreign_mod(vis: &mut T, foreign_mod: &mut ForeignMod) { items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } -pub fn walk_flat_map_variant( - visitor: &mut T, - mut variant: Variant, -) -> SmallVec<[Variant; 1]> { - let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; +pub fn walk_variant(visitor: &mut T, variant: &mut Variant) { + let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = variant; visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); @@ -563,6 +564,13 @@ pub fn walk_flat_map_variant( visitor.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); visitor.visit_span(span); +} + +pub fn walk_flat_map_variant( + vis: &mut T, + mut variant: Variant, +) -> SmallVec<[Variant; 1]> { + vis.visit_variant(&mut variant); smallvec![variant] } From f4fbe88a4d8e34e34112bb7d16d274cca396ec77 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:43:40 -0300 Subject: [PATCH 10/40] Param --- compiler/rustc_ast/src/mut_visit.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 735002e25a50..c5c26b0bbc17 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -263,6 +263,10 @@ pub trait MutVisitor: Sized { walk_attribute(self, at); } + fn visit_param(&mut self, param: &mut Param) { + walk_param(self, param); + } + fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { walk_flat_map_param(self, param) } @@ -701,13 +705,17 @@ fn walk_meta_item(vis: &mut T, mi: &mut MetaItem) { vis.visit_span(span); } -pub fn walk_flat_map_param(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> { - let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param; +pub fn walk_param(vis: &mut T, param: &mut Param) { + let Param { attrs, id, pat, span, ty, is_placeholder: _ } = param; vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_pat(pat); vis.visit_ty(ty); vis.visit_span(span); +} + +pub fn walk_flat_map_param(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> { + vis.visit_param(&mut param); smallvec![param] } From 8b0284afd3735a94878a73ecb6d84be8d3842247 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:45:19 -0300 Subject: [PATCH 11/40] GenericParam --- compiler/rustc_ast/src/mut_visit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c5c26b0bbc17..731e5b601ea5 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -287,6 +287,10 @@ pub trait MutVisitor: Sized { walk_variant_data(self, vdata); } + fn visit_generic_param(&mut self, param: &mut GenericParam) { + walk_generic_param(self, param) + } + fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { walk_flat_map_generic_param(self, param) } @@ -974,11 +978,8 @@ fn walk_precise_capturing_arg(vis: &mut T, arg: &mut PreciseCaptu } } -pub fn walk_flat_map_generic_param( - vis: &mut T, - mut param: GenericParam, -) -> SmallVec<[GenericParam; 1]> { - let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param; +pub fn walk_generic_param(vis: &mut T, param: &mut GenericParam) { + let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = param; vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_ident(ident); @@ -996,6 +997,13 @@ pub fn walk_flat_map_generic_param( if let Some(colon_span) = colon_span { vis.visit_span(colon_span); } +} + +pub fn walk_flat_map_generic_param( + vis: &mut T, + mut param: GenericParam, +) -> SmallVec<[GenericParam; 1]> { + vis.visit_generic_param(&mut param); smallvec![param] } From eb2f1c85b32e591293c8242230ad9bdca9d3c69b Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:48:03 -0300 Subject: [PATCH 12/40] ExprField --- compiler/rustc_ast/src/mut_visit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 731e5b601ea5..4987e218933a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -307,6 +307,10 @@ pub trait MutVisitor: Sized { walk_mt(self, mt); } + fn visit_expr_field(&mut self, f: &mut ExprField) { + walk_expr_field(self, f); + } + fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> { walk_flat_map_expr_field(self, f) } @@ -1104,16 +1108,20 @@ pub fn walk_flat_map_field_def( smallvec![fd] } -pub fn walk_flat_map_expr_field( - vis: &mut T, - mut f: ExprField, -) -> SmallVec<[ExprField; 1]> { - let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f; +pub fn walk_expr_field(vis: &mut T, f: &mut ExprField) { + let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = f; vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_ident(ident); vis.visit_expr(expr); vis.visit_span(span); +} + +pub fn walk_flat_map_expr_field( + vis: &mut T, + mut f: ExprField, +) -> SmallVec<[ExprField; 1]> { + vis.visit_expr_field(&mut f); smallvec![f] } From 5c2de73700d351b5ec4182f9ea13ce4e702686b3 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 19:49:29 -0300 Subject: [PATCH 13/40] PatField --- compiler/rustc_ast/src/mut_visit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4987e218933a..2158ed33e6e3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -335,6 +335,10 @@ pub trait MutVisitor: Sized { // Do nothing. } + fn visit_pat_field(&mut self, fp: &mut PatField) { + walk_pat_field(self, fp) + } + fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> { walk_flat_map_pat_field(self, fp) } @@ -449,16 +453,20 @@ pub fn visit_delim_span(vis: &mut T, DelimSpan { open, close }: & vis.visit_span(close); } -pub fn walk_flat_map_pat_field( - vis: &mut T, - mut fp: PatField, -) -> SmallVec<[PatField; 1]> { - let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp; +pub fn walk_pat_field(vis: &mut T, fp: &mut PatField) { + let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = fp; vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_ident(ident); vis.visit_pat(pat); vis.visit_span(span); +} + +pub fn walk_flat_map_pat_field( + vis: &mut T, + mut fp: PatField, +) -> SmallVec<[PatField; 1]> { + vis.visit_pat_field(&mut fp); smallvec![fp] } From 588c4c45d55556ec7dcaad746ff1af3ca991b64a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Nov 2024 20:30:58 +0000 Subject: [PATCH 14/40] Rename implied_const_bounds to explicit_implied_const_bounds --- .../rustc_hir_analysis/src/check/compare_impl_item.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 ++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 ++-- .../rustc_next_trait_solver/src/solve/assembly/mod.rs | 2 +- .../rustc_next_trait_solver/src/solve/effect_goals.rs | 5 +---- compiler/rustc_type_ir/src/elaborate.rs | 2 +- compiler/rustc_type_ir/src/interner.rs | 2 +- 12 files changed, 17 insertions(+), 20 deletions(-) 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 77c324183c35..c004a37137b8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2083,7 +2083,7 @@ pub(super) fn check_type_bounds<'tcx>( // Only in a const implementation do we need to check that the `~const` item bounds hold. if tcx.is_conditionally_const(impl_ty_def_id) { obligations.extend( - tcx.implied_const_bounds(trait_ty.def_id) + tcx.explicit_implied_const_bounds(trait_ty.def_id) .iter_instantiated_copied(tcx, rebased_args) .map(|(c, span)| { traits::Obligation::new( diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 63a0e7d31c3b..001118eb8d32 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -78,7 +78,7 @@ pub fn provide(providers: &mut Providers) { predicates_of::explicit_supertraits_containing_assoc_item, trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds, const_conditions: predicates_of::const_conditions, - implied_const_bounds: predicates_of::implied_const_bounds, + explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds, type_param_predicates: predicates_of::type_param_predicates, trait_def, adt_def, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 7ce12d48160a..a675a7fc7683 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1017,7 +1017,7 @@ pub(super) fn const_conditions<'tcx>( } } -pub(super) fn implied_const_bounds<'tcx>( +pub(super) fn explicit_implied_const_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { @@ -1036,7 +1036,7 @@ pub(super) fn implied_const_bounds<'tcx>( Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) => { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst) } - _ => bug!("implied_const_bounds called on wrong item: {def_id:?}"), + _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"), }; bounds.map_bound(|bounds| { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 045fd0565ba0..a89096beb8c3 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -275,7 +275,7 @@ provide! { tcx, def_id, other, cdata, defaultness => { table_direct } constness => { table_direct } const_conditions => { table } - implied_const_bounds => { table_defaulted_array } + explicit_implied_const_bounds => { table_defaulted_array } coerce_unsized_info => { Ok(cdata .root diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b5391247cea5..1ac5f1401d6e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1463,8 +1463,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_array!(self.tables.module_children_non_reexports[def_id] <- module_children.iter().map(|child| child.res.def_id().index)); if self.tcx.is_const_trait(def_id) { - record_defaulted_array!(self.tables.implied_const_bounds[def_id] - <- self.tcx.implied_const_bounds(def_id).skip_binder()); + record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] + <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder()); } } if let DefKind::TraitAlias = def_kind { @@ -1654,8 +1654,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_super_predicates(def_id); if tcx.is_conditionally_const(def_id) { - record_defaulted_array!(self.tables.implied_const_bounds[def_id] - <- self.tcx.implied_const_bounds(def_id).skip_binder()); + record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] + <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder()); } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 58f58efb116f..4a8f8521b4ff 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -391,7 +391,7 @@ define_tables! { inferred_outlives_of: Table, Span)>>, explicit_super_predicates_of: Table, Span)>>, explicit_implied_predicates_of: Table, Span)>>, - implied_const_bounds: Table, Span)>>, + explicit_implied_const_bounds: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, opt_rpitit_info: Table>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 684d5b6c2a77..bb6175cc2cee 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -697,7 +697,7 @@ rustc_queries! { separate_provide_extern } - query implied_const_bounds( + query explicit_implied_const_bounds( key: DefId ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { desc { |tcx| "computing the implied `~const` bounds for `{}`", diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2ba1bf2822fb..9ccfd8e1117c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -387,12 +387,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) } - fn implied_const_bounds( + fn explicit_implied_const_bounds( self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { ty::EarlyBinder::bind( - self.implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), + self.explicit_implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), ) } 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 ebf7372926f8..9f01acb2f6d1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -102,7 +102,7 @@ where /// Assemble additional assumptions for an alias that are not included /// in the item bounds of the alias. For now, this is limited to the - /// `implied_const_bounds` for an associated type. + /// `explicit_implied_const_bounds` for an associated type. fn consider_additional_alias_assumptions( ecx: &mut EvalCtxt<'_, D>, goal: Goal, diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 0912e5effa63..bb082a0eb5a3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -84,12 +84,9 @@ where let cx = ecx.cx(); let mut candidates = vec![]; - // FIXME(const_trait_impl): We elaborate here because the implied const bounds - // aren't necessarily elaborated. We probably should prefix this query - // with `explicit_`... for clause in elaborate::elaborate( cx, - cx.implied_const_bounds(alias_ty.def_id) + cx.explicit_implied_const_bounds(alias_ty.def_id) .iter_instantiated(cx, alias_ty.args) .map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.constness)), ) { diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 3fbce7886edc..2c1ad9de9aa8 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -157,7 +157,7 @@ impl> Elaborator { } // `T: ~const Trait` implies `T: ~const Supertrait`. ty::ClauseKind::HostEffect(data) => self.extend_deduped( - cx.implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| { + cx.explicit_implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| { elaboratable.child( trait_ref .to_host_effect_clause(cx, data.constness) diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index f988f003c0f9..d5f5ccce9c50 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -228,7 +228,7 @@ pub trait Interner: self, def_id: Self::DefId, ) -> ty::EarlyBinder>>>; - fn implied_const_bounds( + fn explicit_implied_const_bounds( self, def_id: Self::DefId, ) -> ty::EarlyBinder>>>; From 5eeaf2ec3310b6b10d0567890a52eb0293585e7a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Nov 2024 20:29:01 +0000 Subject: [PATCH 15/40] Implement ~const opaques --- .../rustc_hir_analysis/src/check/check.rs | 2 + compiler/rustc_hir_analysis/src/collect.rs | 8 ++++ .../src/collect/predicates_of.rs | 9 ++++- .../rustc_infer/src/infer/opaque_types/mod.rs | 27 +++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++ compiler/rustc_middle/src/ty/mod.rs | 8 +++- .../const-closure-parse-not-item.stderr | 10 ++++- .../const-traits/const-opaque.no.stderr | 15 ++++++++ tests/ui/traits/const-traits/const-opaque.rs | 38 +++++++++++++++++++ .../ice-112822-expected-type-for-param.rs | 1 + .../ice-112822-expected-type-for-param.stderr | 16 ++++++-- 11 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 tests/ui/traits/const-traits/const-opaque.no.stderr create mode 100644 tests/ui/traits/const-traits/const-opaque.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index cf8c81c0b089..275100411d39 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -339,6 +339,8 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = ObligationCause::misc(span, def_id); // FIXME: We should just register the item bounds here, rather than equating. + // FIXME(const_trait_impl): When we do that, please make sure to also register + // the `~const` bounds. match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} Err(ty_err) => { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 001118eb8d32..63e908019046 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -339,6 +339,10 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().explicit_item_super_predicates(def_id); self.tcx.ensure().item_bounds(def_id); self.tcx.ensure().item_super_predicates(def_id); + if self.tcx.is_conditionally_const(def_id) { + self.tcx.ensure().explicit_implied_const_bounds(def_id); + self.tcx.ensure().const_conditions(def_id); + } intravisit::walk_opaque_ty(self, opaque); } @@ -681,6 +685,10 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().generics_of(item.owner_id); tcx.ensure().type_of(item.owner_id); tcx.ensure().predicates_of(item.owner_id); + if tcx.is_conditionally_const(def_id) { + tcx.ensure().explicit_implied_const_bounds(def_id); + tcx.ensure().const_conditions(def_id); + } match item.kind { hir::ForeignItemKind::Fn(..) => { tcx.ensure().codegen_fn_attrs(item.owner_id); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a675a7fc7683..65a419adaa1e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -958,6 +958,12 @@ pub(super) fn const_conditions<'tcx>( hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false), _ => bug!("const_conditions called on wrong item: {def_id:?}"), }, + Node::OpaqueTy(opaque) => match opaque.origin { + hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent), + hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => { + unreachable!() + } + }, // N.B. Tuple ctors are unconditionally constant. Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(), _ => bug!("const_conditions called on wrong item: {def_id:?}"), @@ -1033,7 +1039,8 @@ pub(super) fn explicit_implied_const_bounds<'tcx>( PredicateFilter::SelfConstIfConst, ) } - Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) => { + Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) + | Node::OpaqueTy(_) => { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst) } _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"), diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index d65ed72a8e84..0aff46203144 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -574,9 +574,8 @@ impl<'tcx> InferCtxt<'tcx> { // unexpected region errors. goals.push(Goal::new(tcx, param_env, ty::ClauseKind::WellFormed(hidden_ty.into()))); - let item_bounds = tcx.explicit_item_bounds(def_id); - for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { - let predicate = predicate.fold_with(&mut BottomUpFolder { + let replace_opaques_in = |clause: ty::Clause<'tcx>, goals: &mut Vec<_>| { + clause.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| match *ty.kind() { // We can't normalize associated types from `rustc_infer`, @@ -612,11 +611,31 @@ impl<'tcx> InferCtxt<'tcx> { }, lt_op: |lt| lt, ct_op: |ct| ct, - }); + }) + }; + + let item_bounds = tcx.explicit_item_bounds(def_id); + for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { + let predicate = replace_opaques_in(predicate, goals); // Require that the predicate holds for the concrete type. debug!(?predicate); goals.push(Goal::new(self.tcx, param_env, predicate)); } + + // If this opaque is being defined and it's conditionally const, + if self.tcx.is_conditionally_const(def_id) { + let item_bounds = tcx.explicit_implied_const_bounds(def_id); + for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { + let predicate = replace_opaques_in( + predicate.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe), + goals, + ); + + // Require that the predicate holds for the concrete type. + debug!(?predicate); + goals.push(Goal::new(self.tcx, param_env, predicate)); + } + } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1ac5f1401d6e..8378e7c6e9b9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1532,6 +1532,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_explicit_item_super_predicates(def_id); record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id)); self.encode_precise_capturing_args(def_id); + if tcx.is_conditionally_const(def_id) { + record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] + <- tcx.explicit_implied_const_bounds(def_id).skip_binder()); + } } if tcx.impl_method_has_trait_impl_trait_tys(def_id) && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cddd6110c23c..13ea3b680268 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2117,7 +2117,13 @@ impl<'tcx> TyCtxt<'tcx> { _ => bug!("unexpected parent item of associated item: {parent_def_id:?}"), } } - DefKind::Closure | DefKind::OpaqueTy => { + DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) { + hir::OpaqueTyOrigin::FnReturn { parent, .. } => self.is_conditionally_const(parent), + hir::OpaqueTyOrigin::AsyncFn { .. } => false, + // FIXME(const_trait_impl): ATPITs could be conditionally const? + hir::OpaqueTyOrigin::TyAlias { .. } => false, + }, + DefKind::Closure => { // Closures and RPITs will eventually have const conditions // for `~const` bounds. false diff --git a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr index 25c81ff900f2..0970cd5225fb 100644 --- a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr +++ b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr @@ -12,5 +12,13 @@ LL | const fn test() -> impl ~const Fn() { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-parse-not-item.rs:7:25 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr new file mode 100644 index 000000000000..e43a6b603fda --- /dev/null +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): const Foo` is not satisfied + --> $DIR/const-opaque.rs:31:18 + | +LL | let opaque = bar(()); + | ^^^^^^^ + +error[E0277]: the trait bound `(): const Foo` is not satisfied + --> $DIR/const-opaque.rs:33:5 + | +LL | opaque.method(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-opaque.rs b/tests/ui/traits/const-traits/const-opaque.rs new file mode 100644 index 000000000000..96cdd7d9f261 --- /dev/null +++ b/tests/ui/traits/const-traits/const-opaque.rs @@ -0,0 +1,38 @@ +//@ revisions: yes no +//@ compile-flags: -Znext-solver +//@[yes] check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn method(&self); +} + +impl const Foo for (T,) { + fn method(&self) {} +} + +#[cfg(yes)] +impl const Foo for () { + fn method(&self) {} +} + +#[cfg(no)] +impl Foo for () { + fn method(&self) {} +} + +const fn bar(t: T) -> impl ~const Foo { + (t,) +} + +const _: () = { + let opaque = bar(()); + //[no]~^ ERROR the trait bound `(): const Foo` is not satisfied + opaque.method(); + //[no]~^ ERROR the trait bound `(): const Foo` is not satisfied + std::mem::forget(opaque); +}; + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs index c467088ab3d3..8ff15dd09cc0 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs @@ -3,6 +3,7 @@ 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 `~const` can only be applied to `#[const_trait]` traits const move || { //~ ERROR const closures are experimental let sl: &[u8] = b"foo"; diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr index 6d7edaf19f26..879d966b1f97 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/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:6:5 + --> $DIR/ice-112822-expected-type-for-param.rs:7:5 | LL | const move || { | ^^^^^ @@ -22,8 +22,16 @@ LL | const fn test() -> impl ~const Fn() { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/ice-112822-expected-type-for-param.rs:3:25 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0015]: cannot call non-const operator in constant functions - --> $DIR/ice-112822-expected-type-for-param.rs:11:17 + --> $DIR/ice-112822-expected-type-for-param.rs:12:17 | LL | assert_eq!(first, &b'f'); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +40,7 @@ LL | assert_eq!(first, &b'f'); = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) 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 + --> $DIR/ice-112822-expected-type-for-param.rs:12:17 | LL | assert_eq!(first, &b'f'); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +48,7 @@ LL | assert_eq!(first, &b'f'); = 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: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. From 91be81592f43dab084e24d3e317671274860e180 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:55:35 +0100 Subject: [PATCH 16/40] ci: Disable full `debuginfo-level=2` in windows alt job --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index 5690d8edea6a..b874f71832d7 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -116,7 +116,7 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" - if [ "$DEPLOY_ALT" != "" ]; then + if [ "$DEPLOY_ALT" != "" ] && isLinux; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level=2" else RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1" From a4bd5708c6bda556adf5b494bef6576aa1fabe6c Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:59:48 +0100 Subject: [PATCH 17/40] Update LLVM to 19.1.4 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index b35599be7586..104d0d16c3c7 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit b35599be758613448201a49f4b8c7ebfba5558ac +Subproject commit 104d0d16c3c7c3fef2435fef6efb2d57b70fff73 From 19b528b8a0770d55ba3c7b3cc5b91d6466e6ff2d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 27 Oct 2024 00:16:44 +0000 Subject: [PATCH 18/40] Store resolution for self and crate root module segments --- compiler/rustc_resolve/src/ident.rs | 14 +++++--- .../generics/generics-on-self-mod-segment.rs | 18 +++++++++++ .../generics-on-self-mod-segment.stderr | 32 +++++++++++++++++++ .../trait-bounds/maybe-bound-has-path-args.rs | 2 +- .../maybe-bound-has-path-args.stderr | 4 +-- 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 tests/ui/generics/generics-on-self-mod-segment.rs create mode 100644 tests/ui/generics/generics-on-self-mod-segment.stderr diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index ad825d7813d6..466e190028ac 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1478,9 +1478,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if segment_idx == 0 { if name == kw::SelfLower { let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); - module = Some(ModuleOrUniformRoot::Module( - self.resolve_self(&mut ctxt, parent_scope.module), - )); + let self_mod = self.resolve_self(&mut ctxt, parent_scope.module); + if let Some(res) = self_mod.res() { + record_segment_res(self, res); + } + module = Some(ModuleOrUniformRoot::Module(self_mod)); continue; } if name == kw::PathRoot && ident.span.at_least_rust_2018() { @@ -1497,7 +1499,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if name == kw::PathRoot || name == kw::Crate || name == kw::DollarCrate { // `::a::b`, `crate::a::b` or `$crate::a::b` - module = Some(ModuleOrUniformRoot::Module(self.resolve_crate_root(ident))); + let crate_root = self.resolve_crate_root(ident); + if let Some(res) = crate_root.res() { + record_segment_res(self, res); + } + module = Some(ModuleOrUniformRoot::Module(crate_root)); continue; } } diff --git a/tests/ui/generics/generics-on-self-mod-segment.rs b/tests/ui/generics/generics-on-self-mod-segment.rs new file mode 100644 index 000000000000..ef229eeba530 --- /dev/null +++ b/tests/ui/generics/generics-on-self-mod-segment.rs @@ -0,0 +1,18 @@ +struct Ty; + +fn self_(_: self::::Ty) {} +//~^ ERROR type arguments are not allowed on module `generics_on_self_mod_segment` + +fn crate_(_: crate::::Ty) {} +//~^ ERROR type arguments are not allowed on module `generics_on_self_mod_segment` + +macro_rules! dollar_crate { + () => { + fn dollar_crate_(_: $crate::::Ty) {} + //~^ ERROR type arguments are not allowed on module `generics_on_self_mod_segment` + } +} + +dollar_crate!(); + +fn main() {} diff --git a/tests/ui/generics/generics-on-self-mod-segment.stderr b/tests/ui/generics/generics-on-self-mod-segment.stderr new file mode 100644 index 000000000000..4a2d5939a3ec --- /dev/null +++ b/tests/ui/generics/generics-on-self-mod-segment.stderr @@ -0,0 +1,32 @@ +error[E0109]: type arguments are not allowed on module `generics_on_self_mod_segment` + --> $DIR/generics-on-self-mod-segment.rs:3:20 + | +LL | fn self_(_: self::::Ty) {} + | ---- ^^^ type argument not allowed + | | + | not allowed on module `generics_on_self_mod_segment` + +error[E0109]: type arguments are not allowed on module `generics_on_self_mod_segment` + --> $DIR/generics-on-self-mod-segment.rs:6:22 + | +LL | fn crate_(_: crate::::Ty) {} + | ----- ^^^ type argument not allowed + | | + | not allowed on module `generics_on_self_mod_segment` + +error[E0109]: type arguments are not allowed on module `generics_on_self_mod_segment` + --> $DIR/generics-on-self-mod-segment.rs:11:38 + | +LL | fn dollar_crate_(_: $crate::::Ty) {} + | ------ ^^^ type argument not allowed + | | + | not allowed on module `generics_on_self_mod_segment` +... +LL | dollar_crate!(); + | --------------- in this macro invocation + | + = note: this error originates in the macro `dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs index 2cb63f25d063..fd0e96917004 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs @@ -1,7 +1,7 @@ trait Trait {} fn test::Trait>() {} -//~^ ERROR type arguments are not allowed on this type +//~^ ERROR type arguments are not allowed on module `maybe_bound_has_path_args` //~| WARN relaxing a default bound only does something for `?Sized` fn main() {} diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr index 701e493f5a52..0c167fff9401 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr @@ -4,13 +4,13 @@ warning: relaxing a default bound only does something for `?Sized`; all other tr LL | fn test::Trait>() {} | ^^^^^^^^^^^^^^^^^^^ -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on module `maybe_bound_has_path_args` --> $DIR/maybe-bound-has-path-args.rs:3:20 | LL | fn test::Trait>() {} | ---- ^^^ type argument not allowed | | - | not allowed on this type + | not allowed on module `maybe_bound_has_path_args` error: aborting due to 1 previous error; 1 warning emitted From b33a0d329236833ecafcd84978f51d6ccb0dd5ad Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 26 Oct 2024 23:57:36 +0000 Subject: [PATCH 19/40] we should not be reporting generic error if there is not a segment to deny --- compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index dd0f250a8e28..4e5a8271e9ec 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1106,7 +1106,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect::() ), [(only, _)] => only.to_string(), - [] => "this type".to_string(), + [] => bug!("expected one segment to deny"), }; let arg_spans: Vec = segments @@ -1136,7 +1136,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "s", ), [only] => (only.to_string(), ""), - [] => unreachable!("expected at least one generic to prohibit"), + [] => bug!("expected at least one generic to prohibit"), }; let last_span = *arg_spans.last().unwrap(); let span: MultiSpan = arg_spans.into(); From dc97db105ac3ebefe0ab51b88a26f87ef4fec207 Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Fri, 6 Sep 2024 13:05:01 -0700 Subject: [PATCH 20/40] unstable feature usage metrics --- Cargo.lock | 2 + compiler/rustc_driver_impl/messages.ftl | 2 + compiler/rustc_driver_impl/src/lib.rs | 24 ++++- .../src/session_diagnostics.rs | 8 ++ compiler/rustc_feature/Cargo.toml | 2 + compiler/rustc_feature/src/unstable.rs | 50 +++++++++++ compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_session/src/options.rs | 2 +- .../unstable-feature-usage-metrics/lib.rs | 9 ++ .../unstable-feature-usage-metrics/rmake.rs | 87 +++++++++++++++++++ 10 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 tests/run-make/unstable-feature-usage-metrics/lib.rs create mode 100644 tests/run-make/unstable-feature-usage-metrics/rmake.rs diff --git a/Cargo.lock b/Cargo.lock index b98c4fd0642d..ed624af2476e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3684,6 +3684,8 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_span", + "serde", + "serde_json", ] [[package]] diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl index 31837e017643..05e11c4527f8 100644 --- a/compiler/rustc_driver_impl/messages.ftl +++ b/compiler/rustc_driver_impl/messages.ftl @@ -23,3 +23,5 @@ driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc ver driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}` driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file + +driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b6f7abed6f3c..6c3c81d9f7a2 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -50,6 +50,7 @@ use rustc_interface::{Linker, Queries, interface, passes}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; +use rustc_middle::ty::TyCtxt; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ CG_OPTIONS, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, Z_OPTIONS, @@ -102,7 +103,7 @@ mod signal_handler { use crate::session_diagnostics::{ RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch, - RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, + RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -430,6 +431,10 @@ fn run_compiler( // Make sure name resolution and macro expansion is run. queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering()); + if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { + queries.global_ctxt()?.enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir)); + } + if callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); } @@ -474,6 +479,23 @@ fn run_compiler( }) } +fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &PathBuf) { + let output_filenames = tcxt.output_filenames(()); + let mut metrics_file_name = std::ffi::OsString::from("unstable_feature_usage_metrics-"); + let mut metrics_path = output_filenames.with_directory_and_extension(metrics_dir, "json"); + let metrics_file_stem = + metrics_path.file_name().expect("there should be a valid default output filename"); + metrics_file_name.push(metrics_file_stem); + metrics_path.pop(); + metrics_path.push(metrics_file_name); + if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) { + // FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit + // default metrics" to only produce a warning when metrics are enabled by default and emit + // an error only when the user manually enables metrics + tcxt.dcx().emit_err(UnstableFeatureUsage { error }); + } +} + // Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option, Option) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 449878f28c4e..e06c56539d1c 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -1,3 +1,5 @@ +use std::error::Error; + use rustc_macros::{Diagnostic, Subdiagnostic}; #[derive(Diagnostic)] @@ -93,3 +95,9 @@ pub(crate) struct IceFlags { #[derive(Diagnostic)] #[diag(driver_impl_ice_exclude_cargo_defaults)] pub(crate) struct IceExcludeCargoDefaults; + +#[derive(Diagnostic)] +#[diag(driver_impl_unstable_feature_usage)] +pub(crate) struct UnstableFeatureUsage { + pub error: Box, +} diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index 9df320e1279e..77de7fabd4f9 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" # tidy-alphabetical-start rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } +serde = { version = "1.0.125", features = [ "derive" ] } +serde_json = "1.0.59" # tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8326d0031ea6..afd793d71aa1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -1,5 +1,7 @@ //! List of the unstable feature gates. +use std::path::PathBuf; + use rustc_data_structures::fx::FxHashSet; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; @@ -649,6 +651,54 @@ declare_features! ( // ------------------------------------------------------------------------- ); +impl Features { + pub fn dump_feature_usage_metrics( + &self, + metrics_path: PathBuf, + ) -> Result<(), Box> { + #[derive(serde::Serialize)] + struct LibFeature { + symbol: String, + } + + #[derive(serde::Serialize)] + struct LangFeature { + symbol: String, + since: Option, + } + + #[derive(serde::Serialize)] + struct FeatureUsage { + lib_features: Vec, + lang_features: Vec, + } + + let metrics_file = std::fs::File::create(metrics_path)?; + let metrics_file = std::io::BufWriter::new(metrics_file); + + let lib_features = self + .enabled_lib_features + .iter() + .map(|EnabledLibFeature { gate_name, .. }| LibFeature { symbol: gate_name.to_string() }) + .collect(); + + let lang_features = self + .enabled_lang_features + .iter() + .map(|EnabledLangFeature { gate_name, stable_since, .. }| LangFeature { + symbol: gate_name.to_string(), + since: stable_since.map(|since| since.to_string()), + }) + .collect(); + + let feature_usage = FeatureUsage { lib_features, lang_features }; + + serde_json::to_writer(metrics_file, &feature_usage)?; + + Ok(()) + } +} + /// Some features are not allowed to be used together at the same time, if /// the two are present, produce an error. /// diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 44721bd889a0..bfd38728edb6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1068,7 +1068,7 @@ impl OutputFilenames { self.with_directory_and_extension(&self.out_directory, extension) } - fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { + pub fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { let mut path = directory.join(&self.filestem); path.set_extension(extension); path diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f485e8cace54..5d2375759919 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1889,7 +1889,7 @@ options! { meta_stats: bool = (false, parse_bool, [UNTRACKED], "gather metadata statistics (default: no)"), metrics_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], - "stores metrics about the errors being emitted by rustc to disk"), + "the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), diff --git a/tests/run-make/unstable-feature-usage-metrics/lib.rs b/tests/run-make/unstable-feature-usage-metrics/lib.rs new file mode 100644 index 000000000000..2202d722c497 --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics/lib.rs @@ -0,0 +1,9 @@ +#![feature(ascii_char)] // random lib feature +#![feature(box_patterns)] // random lang feature + +// picked arbitrary unstable features, just need a random lib and lang feature, ideally ones that +// won't be stabilized any time soon so we don't have to update this test + +fn main() { + println!("foobar"); +} diff --git a/tests/run-make/unstable-feature-usage-metrics/rmake.rs b/tests/run-make/unstable-feature-usage-metrics/rmake.rs new file mode 100644 index 000000000000..7e122def6b71 --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics/rmake.rs @@ -0,0 +1,87 @@ +//! This test checks if unstable feature usage metric dump files `unstable-feature-usage*.json` work +//! as expected. +//! +//! - Basic sanity checks on a default ICE dump. +//! +//! See . +//! +//! # Test history +//! +//! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming +//! those will be present in this test as well on the same platform + +//@ ignore-windows +//FIXME(#128911): still flakey on i686-mingw. + +use std::path::{Path, PathBuf}; + +use run_make_support::rfs::create_dir_all; +use run_make_support::{ + cwd, filename_contains, has_extension, rfs, run_in_tmpdir, rustc, serde_json, + shallow_find_files, +}; + +fn find_feature_usage_metrics>(dir: P) -> Vec { + shallow_find_files(dir, |path| { + if filename_contains(path, "unstable_feature_usage") && has_extension(path, "json") { + true + } else { + dbg!(path); + false + } + }) +} + +fn main() { + test_metrics_dump(); + test_metrics_errors(); +} + +#[track_caller] +fn test_metrics_dump() { + run_in_tmpdir(|| { + let metrics_dir = cwd().join("metrics"); + create_dir_all(&metrics_dir); + rustc() + .input("lib.rs") + .env("RUST_BACKTRACE", "short") + .arg(format!("-Zmetrics-dir={}", metrics_dir.display())) + .run(); + let mut metrics = find_feature_usage_metrics(&metrics_dir); + let json_path = + metrics.pop().expect("there should be one metrics file in the output directory"); + + assert_eq!( + 0, + metrics.len(), + "there should be no more than one metrics file in the output directory" + ); + + let message = rfs::read_to_string(json_path); + let parsed: serde_json::Value = + serde_json::from_str(&message).expect("metrics should be dumped as json"); + let expected = serde_json::json!( + { + "lib_features":[{"symbol":"ascii_char"}], + "lang_features":[{"symbol":"box_patterns","since":null}] + } + ); + + assert_eq!(expected, parsed); + }); +} + +#[track_caller] +fn test_metrics_errors() { + run_in_tmpdir(|| { + rustc() + .input("lib.rs") + .env("RUST_BACKTRACE", "short") + .arg("-Zmetrics-dir=invaliddirectorythatdefinitelydoesntexist") + .run_fail() + .assert_stderr_contains( + "error: cannot dump feature usage metrics: No such file or directory", + ) + .assert_stdout_not_contains("internal compiler error"); + }); +} From 1dc12367b9a0c3317caaad4ec1f5a8af7484cc19 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 20:11:49 -0300 Subject: [PATCH 21/40] Items --- compiler/rustc_ast/src/mut_visit.rs | 52 +++++++++++++++---- compiler/rustc_ast/src/visit.rs | 24 ++++++--- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_expand/src/placeholders.rs | 2 +- compiler/rustc_lint/src/early.rs | 17 +++--- 6 files changed, 71 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2158ed33e6e3..cb38a16db35f 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -104,8 +104,16 @@ pub trait MutVisitor: Sized { walk_use_tree(self, use_tree); } + fn visit_foreign_item(&mut self, ni: &mut P) { + walk_item(self, ni); + } + fn flat_map_foreign_item(&mut self, ni: P) -> SmallVec<[P; 1]> { - walk_flat_map_item(self, ni) + walk_flat_map_foreign_item(self, ni) + } + + fn visit_item(&mut self, i: &mut P) { + walk_item(self, i); } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { @@ -124,6 +132,10 @@ pub trait MutVisitor: Sized { walk_flat_map_field_def(self, fd) } + fn visit_assoc_item(&mut self, i: &mut P, ctxt: AssocCtxt) { + walk_assoc_item(self, i, ctxt) + } + fn flat_map_assoc_item( &mut self, i: P, @@ -1383,18 +1395,19 @@ pub fn walk_crate(vis: &mut T, krate: &mut Crate) { vis.visit_span(inject_use_span); } -pub fn walk_flat_map_item>( - visitor: &mut impl MutVisitor, - item: P>, -) -> SmallVec<[P>; 1]> { - walk_flat_map_assoc_item(visitor, item, ()) +pub fn walk_item(visitor: &mut impl MutVisitor, item: &mut P>>) { + walk_item_ctxt(visitor, item, ()) } -pub fn walk_flat_map_assoc_item( +pub fn walk_assoc_item(visitor: &mut impl MutVisitor, item: &mut P, ctxt: AssocCtxt) { + walk_item_ctxt(visitor, item, ctxt) +} + +fn walk_item_ctxt( visitor: &mut impl MutVisitor, - mut item: P>, + item: &mut P>, ctxt: K::Ctxt, -) -> SmallVec<[P>; 1]> { +) { let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut(); visitor.visit_id(id); visit_attrs(visitor, attrs); @@ -1403,6 +1416,27 @@ pub fn walk_flat_map_assoc_item( kind.walk(*span, *id, ident, vis, ctxt, visitor); visit_lazy_tts(visitor, tokens); visitor.visit_span(span); +} + +pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P) -> SmallVec<[P; 1]> { + vis.visit_item(&mut item); + smallvec![item] +} + +pub fn walk_flat_map_foreign_item( + vis: &mut impl MutVisitor, + mut item: P, +) -> SmallVec<[P; 1]> { + vis.visit_foreign_item(&mut item); + smallvec![item] +} + +pub fn walk_flat_map_assoc_item( + vis: &mut impl MutVisitor, + mut item: P, + ctxt: AssocCtxt, +) -> SmallVec<[P; 1]> { + vis.visit_assoc_item(&mut item, ctxt); smallvec![item] } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 3500c2153765..fafef4169f49 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -457,13 +457,6 @@ impl WalkItemKind for ItemKind { } } -pub fn walk_item<'a, V: Visitor<'a>>( - visitor: &mut V, - item: &'a Item>, -) -> V::Result { - walk_assoc_item(visitor, item, ()) -} - pub fn walk_enum_def<'a, V: Visitor<'a>>( visitor: &mut V, EnumDef { variants }: &'a EnumDef, @@ -925,7 +918,22 @@ impl WalkItemKind for AssocItemKind { } } -pub fn walk_assoc_item<'a, V: Visitor<'a>, K: WalkItemKind>( +pub fn walk_item<'a, V: Visitor<'a>>( + visitor: &mut V, + item: &'a Item>, +) -> V::Result { + walk_item_ctxt(visitor, item, ()) +} + +pub fn walk_assoc_item<'a, V: Visitor<'a>>( + visitor: &mut V, + item: &'a AssocItem, + ctxt: AssocCtxt, +) -> V::Result { + walk_item_ctxt(visitor, item, ctxt) +} + +fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>( visitor: &mut V, item: &'a Item, ctxt: K::Ctxt, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index e7ee6b43e27a..d46a1bd3d313 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -215,7 +215,7 @@ impl MutVisitor for CfgEval<'_> { foreign_item: P, ) -> SmallVec<[P; 1]> { let foreign_item = configure!(self, foreign_item); - mut_visit::walk_flat_map_item(self, foreign_item) + mut_visit::walk_flat_map_foreign_item(self, foreign_item) } fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 91786462b404..19c2d466f7ca 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1382,7 +1382,7 @@ impl InvocationCollectorNode for P { fragment.make_foreign_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self) + walk_flat_map_foreign_item(visitor, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, ForeignItemKind::MacCall(..)) diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 90206b19bd58..bae16a18bcbf 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -296,7 +296,7 @@ impl MutVisitor for PlaceholderExpander { ) -> SmallVec<[P; 1]> { match item.kind { ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(), - _ => walk_flat_map_item(self, item), + _ => walk_flat_map_foreign_item(self, item), } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index ef9b3dbd13b8..4f3184f1d7cf 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -230,15 +230,16 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) { - self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt { - ast_visit::AssocCtxt::Trait => { - lint_callback!(cx, check_trait_item, item); - ast_visit::walk_assoc_item(cx, item, ctxt); - } - ast_visit::AssocCtxt::Impl => { - lint_callback!(cx, check_impl_item, item); - ast_visit::walk_assoc_item(cx, item, ctxt); + self.with_lint_attrs(item.id, &item.attrs, |cx| { + match ctxt { + ast_visit::AssocCtxt::Trait => { + lint_callback!(cx, check_trait_item, item); + } + ast_visit::AssocCtxt::Impl => { + lint_callback!(cx, check_impl_item, item); + } } + ast_visit::walk_assoc_item(cx, item, ctxt); }); } From 01b26e61987ae2308b62b28bac435605ea021f27 Mon Sep 17 00:00:00 2001 From: maxcabrajac Date: Sun, 17 Nov 2024 23:01:01 -0300 Subject: [PATCH 22/40] Use visit_item instead of flat_map_item in test_harness.rs --- .../rustc_builtin_macros/src/test_harness.rs | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index ba5d34359aa2..b2048c534a48 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -1,6 +1,6 @@ // Code that generates a test runner to run all the tests in a crate -use std::{iter, mem}; +use std::mem; use rustc_ast as ast; use rustc_ast::entry::EntryPointType; @@ -19,7 +19,7 @@ use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency}; use rustc_span::symbol::{Ident, Symbol, sym}; use rustc_span::{DUMMY_SP, Span}; use rustc_target::spec::PanicStrategy; -use smallvec::{SmallVec, smallvec}; +use smallvec::smallvec; use thin_vec::{ThinVec, thin_vec}; use tracing::debug; @@ -129,8 +129,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { c.items.push(mk_main(&mut self.cx)); } - fn flat_map_item(&mut self, mut i: P) -> SmallVec<[P; 1]> { - let item = &mut *i; + fn visit_item(&mut self, item: &mut P) { + let item = &mut **item; + if let Some(name) = get_test_name(&item) { debug!("this is a test item"); @@ -158,7 +159,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // But in those cases, we emit a lint to warn the user of these missing tests. walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item); } - smallvec![i] } } @@ -198,40 +198,30 @@ struct EntryPointCleaner<'a> { } impl<'a> MutVisitor for EntryPointCleaner<'a> { - fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { + fn visit_item(&mut self, item: &mut P) { self.depth += 1; - let item = walk_flat_map_item(self, i).expect_one("noop did something"); + ast::mut_visit::walk_item(self, item); self.depth -= 1; // Remove any #[rustc_main] or #[start] from the AST so it doesn't // clash with the one we're going to add, but mark it as // #[allow(dead_code)] to avoid printing warnings. - let item = match entry_point_type(&item, self.depth == 0) { + match entry_point_type(&item, self.depth == 0) { EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => { - item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { - let allow_dead_code = attr::mk_attr_nested_word( - &self.sess.psess.attr_id_generator, - ast::AttrStyle::Outer, - ast::Safety::Default, - sym::allow, - sym::dead_code, - self.def_site, - ); - let attrs = attrs - .into_iter() - .filter(|attr| { - !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start) - }) - .chain(iter::once(allow_dead_code)) - .collect(); - - ast::Item { id, ident, attrs, kind, vis, span, tokens } - }) + let allow_dead_code = attr::mk_attr_nested_word( + &self.sess.psess.attr_id_generator, + ast::AttrStyle::Outer, + ast::Safety::Default, + sym::allow, + sym::dead_code, + self.def_site, + ); + item.attrs + .retain(|attr| !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start)); + item.attrs.push(allow_dead_code); } - EntryPointType::None | EntryPointType::OtherMain => item, + EntryPointType::None | EntryPointType::OtherMain => {} }; - - smallvec![item] } } @@ -292,7 +282,7 @@ fn generate_test_harness( /// Most of the Ident have the usual def-site hygiene for the AST pass. The /// exception is the `test_const`s. These have a syntax context that has two /// opaque marks: one from the expansion of `test` or `test_case`, and one -/// generated in `TestHarnessGenerator::flat_map_item`. When resolving this +/// generated in `TestHarnessGenerator::visit_item`. When resolving this /// identifier after failing to find a matching identifier in the root module /// we remove the outer mark, and try resolving at its def-site, which will /// then resolve to `test_const`. From 0a14f712d7a2cf42e2e5705b2f5a8f1b8e67c7c2 Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Wed, 20 Nov 2024 12:11:40 -0800 Subject: [PATCH 23/40] Update tests/run-make/unstable-feature-usage-metrics/rmake.rs Co-authored-by: Esteban Kuber --- tests/run-make/unstable-feature-usage-metrics/rmake.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/run-make/unstable-feature-usage-metrics/rmake.rs b/tests/run-make/unstable-feature-usage-metrics/rmake.rs index 7e122def6b71..1397548a6fce 100644 --- a/tests/run-make/unstable-feature-usage-metrics/rmake.rs +++ b/tests/run-make/unstable-feature-usage-metrics/rmake.rs @@ -51,9 +51,9 @@ fn test_metrics_dump() { let json_path = metrics.pop().expect("there should be one metrics file in the output directory"); - assert_eq!( - 0, - metrics.len(), + // After the `pop` above, there should be no files left. + assert!( + metrics.is_empty(), "there should be no more than one metrics file in the output directory" ); From afe238f66fc9348b8c4a1daacefb93c0ec36296a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 09:59:27 +1000 Subject: [PATCH 24/40] Introduce `InvisibleOrigin` on invisible delimiters. It's not used meaningfully yet, but will be needed to get rid of interpolated tokens. --- compiler/rustc_ast/src/attr/mod.rs | 4 +- compiler/rustc_ast/src/token.rs | 114 +++++++++++++++++- compiler/rustc_ast/src/tokenstream.rs | 6 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 5 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_expand/src/mbe/quoted.rs | 11 +- .../rustc_expand/src/proc_macro_server.rs | 4 +- .../rustc_parse/src/parser/attr_wrapper.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 12 +- src/tools/rustfmt/src/macros.rs | 2 +- 10 files changed, 133 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 54e826585d26..888b13efa31a 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -457,7 +457,7 @@ impl MetaItemKind { tokens: &mut impl Iterator, ) -> Option { match tokens.next() { - Some(TokenTree::Delimited(.., Delimiter::Invisible, inner_tokens)) => { + Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees()) } Some(TokenTree::Token(token, _)) => { @@ -605,7 +605,7 @@ impl MetaItemInner { tokens.next(); return Some(MetaItemInner::Lit(lit)); } - Some(TokenTree::Delimited(.., Delimiter::Invisible, inner_tokens)) => { + Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { tokens.next(); return MetaItemInner::from_tokens(&mut inner_tokens.trees().peekable()); } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3b9edef06159..592b56cc08fa 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -42,11 +42,86 @@ pub enum BinOpToken { Shr, } +// This type must not implement `Hash` due to the unusual `PartialEq` impl below. +#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic)] +pub enum InvisibleOrigin { + // From the expansion of a metavariable in a declarative macro. + MetaVar(MetaVarKind), + + // Converted from `proc_macro::Delimiter` in + // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. + ProcMacro, + + // Converted from `TokenKind::Interpolated` in + // `TokenStream::flatten_token`. Treated similarly to `ProcMacro`. + FlattenToken, +} + +impl PartialEq for InvisibleOrigin { + #[inline] + fn eq(&self, _other: &InvisibleOrigin) -> bool { + // When we had AST-based nonterminals we couldn't compare them, and the + // old `Nonterminal` type had an `eq` that always returned false, + // resulting in this restriction: + // https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment + // This `eq` emulates that behaviour. We could consider lifting this + // restriction now but there are still cases involving invisible + // delimiters that make it harder than it first appears. + false + } +} + +/// Annoyingly similar to `NonterminalKind`, but the slight differences are important. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] +pub enum MetaVarKind { + Item, + Block, + Stmt, + Pat(NtPatKind), + Expr { + kind: NtExprKind, + // This field is needed for `Token::can_begin_literal_maybe_minus`. + can_begin_literal_maybe_minus: bool, + // This field is needed for `Token::can_begin_string_literal`. + can_begin_string_literal: bool, + }, + Ty, + Ident, + Lifetime, + Literal, + Meta, + Path, + Vis, + TT, +} + +impl fmt::Display for MetaVarKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let sym = match self { + MetaVarKind::Item => sym::item, + MetaVarKind::Block => sym::block, + MetaVarKind::Stmt => sym::stmt, + MetaVarKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat, + MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param, + MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr, + MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021, + MetaVarKind::Ty => sym::ty, + MetaVarKind::Ident => sym::ident, + MetaVarKind::Lifetime => sym::lifetime, + MetaVarKind::Literal => sym::literal, + MetaVarKind::Meta => sym::meta, + MetaVarKind::Path => sym::path, + MetaVarKind::Vis => sym::vis, + MetaVarKind::TT => sym::tt, + }; + write!(f, "{sym}") + } +} + /// Describes how a sequence of token trees is delimited. /// Cannot use `proc_macro::Delimiter` directly because this /// structure should implement some additional traits. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[derive(Encodable, Decodable, Hash, HashStable_Generic)] +#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum Delimiter { /// `( ... )` Parenthesis, @@ -59,7 +134,34 @@ pub enum Delimiter { /// "macro variable" `$var`. It is important to preserve operator priorities in cases like /// `$var * 3` where `$var` is `1 + 2`. /// Invisible delimiters might not survive roundtrip of a token stream through a string. - Invisible, + Invisible(InvisibleOrigin), +} + +impl Delimiter { + // Should the parser skip these delimiters? Only happens for certain kinds + // of invisible delimiters. Ideally this function will eventually disappear + // and no invisible delimiters will be skipped. + #[inline] + pub fn skip(&self) -> bool { + match self { + Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false, + Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) => false, + Delimiter::Invisible(InvisibleOrigin::FlattenToken | InvisibleOrigin::ProcMacro) => { + true + } + } + } + + // This exists because `InvisibleOrigin`s should be compared. It is only used for assertions. + pub fn eq_ignoring_invisible_origin(&self, other: &Delimiter) -> bool { + match (self, other) { + (Delimiter::Parenthesis, Delimiter::Parenthesis) => true, + (Delimiter::Brace, Delimiter::Brace) => true, + (Delimiter::Bracket, Delimiter::Bracket) => true, + (Delimiter::Invisible(_), Delimiter::Invisible(_)) => true, + _ => false, + } + } } // Note that the suffix is *not* considered when deciding the `LitKind` in this @@ -896,7 +998,7 @@ impl PartialEq for Token { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NtPatKind { // Matches or-patterns. Was written using `pat` in edition 2021 or later. PatWithOr, @@ -906,7 +1008,7 @@ pub enum NtPatKind { PatParam { inferred: bool }, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NtExprKind { // Matches expressions using the post-edition 2024. Was written using // `expr` in edition 2024 or later. @@ -933,7 +1035,7 @@ pub enum Nonterminal { NtVis(P), } -#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NonterminalKind { Item, Block, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 0b4bfc0b36a0..c6b6addc946e 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -24,7 +24,7 @@ use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use crate::ast::{AttrStyle, StmtKind}; use crate::ast_traits::{HasAttrs, HasTokens}; -use crate::token::{self, Delimiter, Nonterminal, Token, TokenKind}; +use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind}; use crate::{AttrVec, Attribute}; /// Part of a `TokenStream`. @@ -484,13 +484,13 @@ impl TokenStream { token::NtLifetime(ident, is_raw) => TokenTree::Delimited( DelimSpan::from_single(token.span), DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible, + Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), token::Interpolated(ref nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible, + Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::from_nonterminal_ast(&nt).flattened(), ), _ => TokenTree::Token(token.clone(), spacing), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index de9f5187be73..d7c531f37608 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -942,9 +942,8 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere token::CloseDelim(Delimiter::Bracket) => "]".into(), token::OpenDelim(Delimiter::Brace) => "{".into(), token::CloseDelim(Delimiter::Brace) => "}".into(), - token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) => { - "".into() - } + token::OpenDelim(Delimiter::Invisible(_)) + | token::CloseDelim(Delimiter::Invisible(_)) => "".into(), token::Pound => "#".into(), token::Dollar => "$".into(), token::Question => "?".into(), diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index fcc90c3ce0dd..a373c753cc11 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -693,7 +693,7 @@ fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { && let mbe::TokenTree::Token(bang) = bang && let TokenKind::Not = bang.kind && let mbe::TokenTree::Delimited(.., del) = args - && del.delim != Delimiter::Invisible + && !del.delim.skip() { true } else { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 1345f06d5ac1..36094707face 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -165,11 +165,12 @@ fn parse_tree<'a>( // during parsing. let mut next = outer_trees.next(); let mut trees: Box>; - if let Some(tokenstream::TokenTree::Delimited(.., Delimiter::Invisible, tts)) = next { - trees = Box::new(tts.trees()); - next = trees.next(); - } else { - trees = Box::new(outer_trees); + match next { + Some(tokenstream::TokenTree::Delimited(.., delim, tts)) if delim.skip() => { + trees = Box::new(tts.trees()); + next = trees.next(); + } + _ => trees = Box::new(outer_trees), } match next { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 0dc35618ff88..263df235b3ec 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -38,7 +38,7 @@ impl FromInternal for Delimiter { token::Delimiter::Parenthesis => Delimiter::Parenthesis, token::Delimiter::Brace => Delimiter::Brace, token::Delimiter::Bracket => Delimiter::Bracket, - token::Delimiter::Invisible => Delimiter::None, + token::Delimiter::Invisible(_) => Delimiter::None, } } } @@ -49,7 +49,7 @@ impl ToInternal for Delimiter { Delimiter::Parenthesis => token::Delimiter::Parenthesis, Delimiter::Brace => token::Delimiter::Brace, Delimiter::Bracket => token::Delimiter::Bracket, - Delimiter::None => token::Delimiter::Invisible, + Delimiter::None => token::Delimiter::Invisible(token::InvisibleOrigin::ProcMacro), } } } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index c85d0bd05cbd..434f71beac24 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -510,8 +510,8 @@ fn make_attr_token_stream( FlatToken::Token((Token { kind: TokenKind::CloseDelim(delim), span }, spacing)) => { let frame_data = mem::replace(&mut stack_top, stack_rest.pop().unwrap()); let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap(); - assert_eq!( - open_delim, delim, + assert!( + open_delim.eq_ignoring_invisible_origin(&delim), "Mismatched open/close delims: open={open_delim:?} close={span:?}" ); let dspan = DelimSpan::from_pair(open_sp, span); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 042ee96bbe85..226f29f99007 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -317,7 +317,7 @@ impl TokenCursor { spacing, delim, )); - if delim != Delimiter::Invisible { + if !delim.skip() { return (Token::new(token::OpenDelim(delim), sp.open), spacing.open); } // No open delimiter to return; continue on to the next iteration. @@ -326,7 +326,7 @@ impl TokenCursor { } else if let Some((tree_cursor, span, spacing, delim)) = self.stack.pop() { // We have exhausted this token stream. Move back to its parent token stream. self.tree_cursor = tree_cursor; - if delim != Delimiter::Invisible { + if !delim.skip() { return (Token::new(token::CloseDelim(delim), span.close), spacing.close); } // No close delimiter to return; continue on to the next iteration. @@ -1163,7 +1163,7 @@ impl<'a> Parser<'a> { } debug_assert!(!matches!( next.0.kind, - token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) + token::OpenDelim(delim) | token::CloseDelim(delim) if delim.skip() )); self.inlined_bump_with(next) } @@ -1187,7 +1187,7 @@ impl<'a> Parser<'a> { match tree { TokenTree::Token(token, _) => return looker(token), &TokenTree::Delimited(dspan, _, delim, _) => { - if delim != Delimiter::Invisible { + if !delim.skip() { return looker(&Token::new(token::OpenDelim(delim), dspan.open)); } } @@ -1197,7 +1197,7 @@ impl<'a> Parser<'a> { // The tree cursor lookahead went (one) past the end of the // current token tree. Try to return a close delimiter. if let Some(&(_, span, _, delim)) = self.token_cursor.stack.last() - && delim != Delimiter::Invisible + && !delim.skip() { // We are not in the outermost token stream, so we have // delimiters. Also, those delimiters are not skipped. @@ -1216,7 +1216,7 @@ impl<'a> Parser<'a> { token = cursor.next().0; if matches!( token.kind, - token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) + token::OpenDelim(delim) | token::CloseDelim(delim) if delim.skip() ) { continue; } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 5a35e115d8f6..4083d9398f6b 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -620,7 +620,7 @@ fn delim_token_to_str( ("{ ", " }") } } - Delimiter::Invisible => unreachable!(), + Delimiter::Invisible(_) => unreachable!(), }; if use_multiple_lines { let indent_str = shape.indent.to_string_with_newline(context.config); From cfafa9380b446b74708986a344172ec48e295740 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 08:58:06 +1000 Subject: [PATCH 25/40] Add metavariables to `TokenDescription`. Pasted metavariables are wrapped in invisible delimiters, which pretty-print as empty strings, and changing that can break some proc macros. But error messages saying "expected identifer, found ``" are bad. So this commit adds support for metavariables in `TokenDescription` so they print as "metavariable" in error messages, instead of "``". It's not used meaningfully yet, but will be needed to get rid of interpolated tokens. --- compiler/rustc_parse/messages.ftl | 7 +++++ compiler/rustc_parse/src/errors.rs | 28 ++++++++++++++++-- compiler/rustc_parse/src/parser/mod.rs | 39 +++++++++++++++++--------- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index ef259703f0cf..cafd4b6dca28 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -216,6 +216,9 @@ parse_expected_identifier_found_doc_comment = expected identifier, found doc com parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}` parse_expected_identifier_found_keyword = expected identifier, found keyword parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}` +parse_expected_identifier_found_metavar = expected identifier, found metavariable +# This one deliberately doesn't print a token. +parse_expected_identifier_found_metavar_str = expected identifier, found metavariable parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}` parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword @@ -227,6 +230,8 @@ parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyw parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}` parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}` +# This one deliberately doesn't print a token. +parse_expected_semi_found_metavar_str = expected `;`, found metavariable parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}` parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}` parse_expected_semi_found_str = expected `;`, found `{$token}` @@ -864,6 +869,8 @@ parse_unexpected_token_after_not_logical = use `!` to perform logical negation parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}` parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}` +# This one deliberately doesn't print a token. +parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}` parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 37eb463cba63..9bdb99dc0007 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1086,6 +1086,8 @@ pub(crate) enum ExpectedIdentifierFound { ReservedKeyword(#[primary_span] Span), #[label(parse_expected_identifier_found_doc_comment)] DocComment(#[primary_span] Span), + #[label(parse_expected_identifier_found_metavar)] + MetaVar(#[primary_span] Span), #[label(parse_expected_identifier)] Other(#[primary_span] Span), } @@ -1099,6 +1101,7 @@ impl ExpectedIdentifierFound { Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword, Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword, Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment, + Some(TokenDescription::MetaVar(_)) => ExpectedIdentifierFound::MetaVar, None => ExpectedIdentifierFound::Other, })(span) } @@ -1117,6 +1120,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let token_descr = TokenDescription::from_token(&self.token); + let mut add_token = true; let mut diag = Diag::new(dcx, level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { fluent::parse_expected_identifier_found_reserved_identifier_str @@ -1128,10 +1132,16 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { Some(TokenDescription::DocComment) => { fluent::parse_expected_identifier_found_doc_comment_str } + Some(TokenDescription::MetaVar(_)) => { + add_token = false; + fluent::parse_expected_identifier_found_metavar_str + } None => fluent::parse_expected_identifier_found_str, }); diag.span(self.span); - diag.arg("token", self.token); + if add_token { + diag.arg("token", self.token); + } if let Some(sugg) = self.suggest_raw { sugg.add_to_diag(&mut diag); @@ -1171,6 +1181,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let token_descr = TokenDescription::from_token(&self.token); + let mut add_token = true; let mut diag = Diag::new(dcx, level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { fluent::parse_expected_semi_found_reserved_identifier_str @@ -1180,10 +1191,16 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { fluent::parse_expected_semi_found_reserved_keyword_str } Some(TokenDescription::DocComment) => fluent::parse_expected_semi_found_doc_comment_str, + Some(TokenDescription::MetaVar(_)) => { + add_token = false; + fluent::parse_expected_semi_found_metavar_str + } None => fluent::parse_expected_semi_found_str, }); diag.span(self.span); - diag.arg("token", self.token); + if add_token { + diag.arg("token", self.token); + } if let Some(unexpected_token_label) = self.unexpected_token_label { diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token); @@ -1925,6 +1942,12 @@ pub(crate) enum UnexpectedTokenAfterStructName { span: Span, token: Token, }, + #[diag(parse_unexpected_token_after_struct_name_found_metavar)] + MetaVar { + #[primary_span] + #[label(parse_unexpected_token_after_struct_name)] + span: Span, + }, #[diag(parse_unexpected_token_after_struct_name_found_other)] Other { #[primary_span] @@ -1941,6 +1964,7 @@ impl UnexpectedTokenAfterStructName { Some(TokenDescription::Keyword) => Self::Keyword { span, token }, Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token }, Some(TokenDescription::DocComment) => Self::DocComment { span, token }, + Some(TokenDescription::MetaVar(_)) => Self::MetaVar { span }, None => Self::Other { span, token }, } } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 226f29f99007..0ed8d152d2d3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -21,7 +21,9 @@ pub(crate) use item::FnParseMode; pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{ + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind, +}; use rustc_ast::tokenstream::{ AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor, }; @@ -410,6 +412,12 @@ pub(super) enum TokenDescription { Keyword, ReservedKeyword, DocComment, + + // Expanded metavariables are wrapped in invisible delimiters which aren't + // pretty-printed. In error messages we must handle these specially + // otherwise we get confusing things in messages like "expected `(`, found + // ``". It's better to say e.g. "expected `(`, found type metavariable". + MetaVar(MetaVarKind), } impl TokenDescription { @@ -419,26 +427,29 @@ impl TokenDescription { _ if token.is_used_keyword() => Some(TokenDescription::Keyword), _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), token::DocComment(..) => Some(TokenDescription::DocComment), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { + Some(TokenDescription::MetaVar(kind)) + } _ => None, } } } pub fn token_descr(token: &Token) -> String { - let name = pprust::token_to_string(token).to_string(); + let s = pprust::token_to_string(token).to_string(); - let kind = match (TokenDescription::from_token(token), &token.kind) { - (Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"), - (Some(TokenDescription::Keyword), _) => Some("keyword"), - (Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"), - (Some(TokenDescription::DocComment), _) => Some("doc comment"), - (None, TokenKind::NtIdent(..)) => Some("identifier"), - (None, TokenKind::NtLifetime(..)) => Some("lifetime"), - (None, TokenKind::Interpolated(node)) => Some(node.descr()), - (None, _) => None, - }; - - if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") } + match (TokenDescription::from_token(token), &token.kind) { + (Some(TokenDescription::ReservedIdentifier), _) => format!("reserved identifier `{s}`"), + (Some(TokenDescription::Keyword), _) => format!("keyword `{s}`"), + (Some(TokenDescription::ReservedKeyword), _) => format!("reserved keyword `{s}`"), + (Some(TokenDescription::DocComment), _) => format!("doc comment `{s}`"), + // Deliberately doesn't print `s`, which is empty. + (Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"), + (None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"), + (None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"), + (None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()), + (None, _) => format!("`{s}`"), + } } impl<'a> Parser<'a> { From 15528b2d6c2d7d83d007440ab84d859bc60ab40d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 20 Nov 2024 10:34:42 +1100 Subject: [PATCH 26/40] Fix `catbat` pager typo. `bat` is known as `batcat` on Ubuntu and Debian, not `catbat`. --- compiler/rustc_driver_impl/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 8dd043be6ad3..038a0d6c2883 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -580,7 +580,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { cmd.arg("-R"); true } else { - ["bat", "catbat", "delta"].iter().any(|v| *v == pager_name) + ["bat", "batcat", "delta"].iter().any(|v| *v == pager_name) }; if color == ColorConfig::Never { From 91164957ec18aa65aa00412f703f2270e47779c1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 20 Nov 2024 14:10:44 +1100 Subject: [PATCH 27/40] Remove redundant `is_terminal` check. It's not necessary because `show_md_content_with_pager` is only ever called if `is_terminal` is true. --- compiler/rustc_driver_impl/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 038a0d6c2883..6198f40e83d9 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -620,8 +620,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { // to standard output if fallback_to_println { let fmt_success = match color { - ColorConfig::Auto => io::stdout().is_terminal() && bufwtr.print(&mdbuf).is_ok(), - ColorConfig::Always => bufwtr.print(&mdbuf).is_ok(), + ColorConfig::Auto | ColorConfig::Always => bufwtr.print(&mdbuf).is_ok(), ColorConfig::Never => false, }; From cee88f7a3f1c5bc284d0c6a87fb1d5535ebb3af8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 09:37:00 +1000 Subject: [PATCH 28/40] Prepare for invisible delimiters. Current places where `Interpolated` is used are going to change to instead use invisible delimiters. This prepares for that. - It adds invisible delimiter cases to the `can_begin_*`/`may_be_*` methods and the `failed_to_match_macro` that are equivalent to the existing `Interpolated` cases. - It adds panics/asserts in some places where invisible delimiters should never occur. - In `Parser::parse_struct_fields` it excludes an ident + invisible delimiter from special consideration in an error message, because that's quite different to an ident + paren/brace/bracket. --- compiler/rustc_ast/src/token.rs | 38 +++++++++++++- compiler/rustc_expand/src/mbe/diagnostics.rs | 6 ++- compiler/rustc_parse/src/lexer/tokentrees.rs | 16 ++++-- compiler/rustc_parse/src/parser/expr.rs | 12 ++++- .../rustc_parse/src/parser/nonterminal.rs | 50 +++++++++++++++++-- 5 files changed, 108 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 592b56cc08fa..678f43e35113 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -598,10 +598,11 @@ impl Token { /// **NB**: Take care when modifying this function, since it will change /// the stable set of tokens that are allowed to match an expr nonterminal. pub fn can_begin_expr(&self) -> bool { + use Delimiter::*; match self.uninterpolate().kind { Ident(name, is_raw) => ident_can_begin_expr(name, self.span, is_raw), // value name or keyword - OpenDelim(..) | // tuple, array or block + OpenDelim(Parenthesis | Brace | Bracket) | // tuple, array or block Literal(..) | // literal Not | // operator not BinOp(Minus) | // unary minus @@ -612,7 +613,7 @@ impl Token { // DotDotDot is no longer supported, but we need some way to display the error DotDot | DotDotDot | DotDotEq | // range notation Lt | BinOp(Shl) | // associated path - PathSep | // global path + PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes Interpolated(ref nt) => @@ -622,6 +623,12 @@ impl Token { NtLiteral(..) | NtPath(..) ), + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Block | + MetaVarKind::Expr { .. } | + MetaVarKind::Literal | + MetaVarKind::Path + ))) => true, _ => false, } } @@ -655,6 +662,14 @@ impl Token { | NtPath(..) | NtTy(..) ), + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Expr { .. } | + MetaVarKind::Literal | + MetaVarKind::Meta | + MetaVarKind::Pat(_) | + MetaVarKind::Path | + MetaVarKind::Ty + ))) => true, _ => false, } } @@ -675,6 +690,10 @@ impl Token { Lt | BinOp(Shl) | // associated path PathSep => true, // global path Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)), + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Ty | + MetaVarKind::Path + ))) => true, // For anonymous structs or unions, which only appear in specific positions // (type of struct fields or union fields), we don't consider them as regular types _ => false, @@ -687,6 +706,9 @@ impl Token { OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, + ))) => true, _ => false, } } @@ -743,6 +765,13 @@ impl Token { }, _ => false, }, + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { + MetaVarKind::Literal => true, + MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { + can_begin_literal_maybe_minus + } + _ => false, + }, _ => false, } } @@ -758,6 +787,11 @@ impl Token { }, _ => false, }, + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { + MetaVarKind::Literal => true, + MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal, + _ => false, + }, _ => false, } } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index ffcce1e52f67..77b8d2289221 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use rustc_ast::token::{self, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage}; use rustc_macros::Subdiagnostic; @@ -68,7 +68,9 @@ pub(super) fn failed_to_match_macro( if let MatcherLoc::Token { token: expected_token } = &remaining_matcher && (matches!(expected_token.kind, TokenKind::Interpolated(_)) - || matches!(token.kind, TokenKind::Interpolated(_))) + || matches!(token.kind, TokenKind::Interpolated(_)) + || matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))) + || matches!(token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_)))) { err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); err.note("see for more information"); diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index d35c9c7bae7d..7b21ffacc841 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -43,11 +43,19 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { let mut buf = Vec::new(); loop { match self.token.kind { - token::OpenDelim(delim) => buf.push(match self.lex_token_tree_open_delim(delim) { - Ok(val) => val, - Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), - }), + token::OpenDelim(delim) => { + // Invisible delimiters cannot occur here because `TokenTreesReader` parses + // code directly from strings, with no macro expansion involved. + debug_assert!(!matches!(delim, Delimiter::Invisible(_))); + buf.push(match self.lex_token_tree_open_delim(delim) { + Ok(val) => val, + Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), + }) + } token::CloseDelim(delim) => { + // Invisible delimiters cannot occur here because `TokenTreesReader` parses + // code directly from strings, with no macro expansion involved. + debug_assert!(!matches!(delim, Delimiter::Invisible(_))); return ( open_spacing, TokenStream::new(buf), diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0012db471ef4..b110d891c841 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3591,11 +3591,19 @@ impl<'a> Parser<'a> { && !self.token.is_reserved_ident() && self.look_ahead(1, |t| { AssocOp::from_token(t).is_some() - || matches!(t.kind, token::OpenDelim(_)) + || matches!( + t.kind, + token::OpenDelim( + Delimiter::Parenthesis + | Delimiter::Bracket + | Delimiter::Brace + ) + ) || *t == token::Dot }) { - // Looks like they tried to write a shorthand, complex expression. + // Looks like they tried to write a shorthand, complex expression, + // E.g.: `n + m`, `f(a)`, `a[i]`, `S { x: 3 }`, or `x.y`. e.span_suggestion_verbose( self.token.span.shrink_to_lo(), "try naming a field", diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 43c3de90d9d9..8fb6f85d0dd8 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -3,7 +3,9 @@ use rustc_ast::ptr::P; use rustc_ast::token::Nonterminal::*; use rustc_ast::token::NtExprKind::*; use rustc_ast::token::NtPatKind::*; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token, +}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; @@ -22,7 +24,28 @@ impl<'a> Parser<'a> { #[inline] pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. - fn may_be_ident(nt: &token::Nonterminal) -> bool { + fn may_be_ident(kind: MetaVarKind) -> bool { + match kind { + MetaVarKind::Stmt + | MetaVarKind::Pat(_) + | MetaVarKind::Expr { .. } + | MetaVarKind::Ty + | MetaVarKind::Literal // `true`, `false` + | MetaVarKind::Meta + | MetaVarKind::Path => true, + + MetaVarKind::Item + | MetaVarKind::Block + | MetaVarKind::Vis => false, + + MetaVarKind::Ident + | MetaVarKind::Lifetime + | MetaVarKind::TT => unreachable!(), + } + } + + /// Old variant of `may_be_ident`. Being phased out. + fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { NtStmt(_) | NtPat(_) @@ -69,7 +92,8 @@ impl<'a> Parser<'a> { | token::Ident(..) | token::NtIdent(..) | token::NtLifetime(..) - | token::Interpolated(_) => true, + | token::Interpolated(_) + | token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true, _ => token.can_begin_type(), }, NonterminalKind::Block => match &token.kind { @@ -79,11 +103,29 @@ impl<'a> Parser<'a> { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false, }, + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { + MetaVarKind::Block + | MetaVarKind::Stmt + | MetaVarKind::Expr { .. } + | MetaVarKind::Literal => true, + MetaVarKind::Item + | MetaVarKind::Pat(_) + | MetaVarKind::Ty + | MetaVarKind::Meta + | MetaVarKind::Path + | MetaVarKind::Vis => false, + MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => { + unreachable!() + } + }, _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::PathSep | token::Ident(..) | token::NtIdent(..) => true, - token::Interpolated(nt) => may_be_ident(nt), + token::Interpolated(nt) => nt_may_be_ident(nt), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { + may_be_ident(*kind) + } _ => false, }, NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind), From 03159d4bff6de12f26daee0f6c6890e71407a389 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2024 13:02:14 +1000 Subject: [PATCH 29/40] Remove `ErrorGuaranteed` retval from `error_unexpected_after_dot`. It was added in #130349, but it's not used meaningfully, and causes difficulties for Nonterminal removal in #124141. --- compiler/rustc_parse/src/parser/expr.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b110d891c841..aa5e9586daf9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -49,7 +49,7 @@ pub(super) enum DestructuredFloat { /// 1.2 | 1.2e3 MiddleDot(Symbol, Span, Span, Symbol, Span), /// Invalid - Error(ErrorGuaranteed), + Error, } impl<'a> Parser<'a> { @@ -1005,7 +1005,7 @@ impl<'a> Parser<'a> { self.mk_expr_tuple_field_access(lo, ident1_span, base, sym1, None); self.mk_expr_tuple_field_access(lo, ident2_span, base1, sym2, suffix) } - DestructuredFloat::Error(_) => base, + DestructuredFloat::Error => base, }) } _ => { @@ -1015,7 +1015,7 @@ impl<'a> Parser<'a> { } } - fn error_unexpected_after_dot(&self) -> ErrorGuaranteed { + fn error_unexpected_after_dot(&self) { let actual = pprust::token_to_string(&self.token); let span = self.token.span; let sm = self.psess.source_map(); @@ -1025,7 +1025,7 @@ impl<'a> Parser<'a> { } _ => (span, actual), }; - self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual }) + self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual }); } /// We need an identifier or integer, but the next token is a float. @@ -1111,8 +1111,8 @@ impl<'a> Parser<'a> { // 1.2e+3 | 1.2e-3 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => { // See the FIXME about `TokenCursor` above. - let guar = self.error_unexpected_after_dot(); - DestructuredFloat::Error(guar) + self.error_unexpected_after_dot(); + DestructuredFloat::Error } _ => panic!("unexpected components in a float token: {components:?}"), } @@ -1178,7 +1178,7 @@ impl<'a> Parser<'a> { fields.insert(start_idx, Ident::new(symbol2, span2)); fields.insert(start_idx, Ident::new(symbol1, span1)); } - DestructuredFloat::Error(_) => { + DestructuredFloat::Error => { trailing_dot = None; fields.insert(start_idx, Ident::new(symbol, self.prev_token.span)); } From 525e1919f730e921f8cc6f917c064c7d083c7048 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 20 Nov 2024 14:15:59 +1100 Subject: [PATCH 30/40] Rewrite `show_md_content_with_pager`. I think the control flow in this function is complicated and confusing, largely due to the use of two booleans `print_formatted` and `fallback_to_println` that are set in multiple places and then used to guide proceedings. As well as hurting readability, this leads to at least one bug: if the `write_termcolor_buf` call fails and the pager also fails, the function will try to print color output to stdout, but that output will be empty because `write_termcolor_buf` failed. I.e. the `if fallback_to_println` body fails to check `print_formatted`. This commit rewrites the function to be neater and more Rust-y, e.g. by putting the result of `write_termcolor_buf` into an `Option` so it can only be used on success, and by using `?` more. It also changes terminology a little, using "pretty" to mean "formatted and colorized". The result is a little shorter, more readable, and less buggy. --- compiler/rustc_driver_impl/src/lib.rs | 94 +++++++++++++-------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 6198f40e83d9..d2333454f289 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -15,6 +15,7 @@ #![feature(panic_update_hook)] #![feature(result_flattening)] #![feature(rustdoc_internals)] +#![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end @@ -564,70 +565,63 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col } } -/// If color is always or auto, print formatted & colorized markdown. If color is never or -/// if formatted printing fails, print the raw text. +/// If `color` is `always` or `auto`, try to print pretty (formatted & colorized) markdown. If +/// that fails or `color` is `never`, print the raw markdown. /// -/// Prefers a pager, falls back standard print +/// Uses a pager if possible, falls back to stdout. fn show_md_content_with_pager(content: &str, color: ColorConfig) { - let mut fallback_to_println = false; let pager_name = env::var_os("PAGER").unwrap_or_else(|| { if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") } }); let mut cmd = Command::new(&pager_name); - // FIXME: find if other pagers accept color options - let mut print_formatted = if pager_name == "less" { - cmd.arg("-R"); - true - } else { - ["bat", "batcat", "delta"].iter().any(|v| *v == pager_name) + if pager_name == "less" { + cmd.arg("-R"); // allows color escape sequences + } + + let pretty_on_pager = match color { + ColorConfig::Auto => { + // Add other pagers that accept color escape sequences here. + ["less", "bat", "batcat", "delta"].iter().any(|v| *v == pager_name) + } + ColorConfig::Always => true, + ColorConfig::Never => false, }; - if color == ColorConfig::Never { - print_formatted = false; - } else if color == ColorConfig::Always { - print_formatted = true; - } + // Try to prettify the raw markdown text. The result can be used by the pager or on stdout. + let pretty_data = { + let mdstream = markdown::MdStream::parse_str(content); + let bufwtr = markdown::create_stdout_bufwtr(); + let mut mdbuf = bufwtr.buffer(); + if mdstream.write_termcolor_buf(&mut mdbuf).is_ok() { Some((bufwtr, mdbuf)) } else { None } + }; - let mdstream = markdown::MdStream::parse_str(content); - let bufwtr = markdown::create_stdout_bufwtr(); - let mut mdbuf = bufwtr.buffer(); - if mdstream.write_termcolor_buf(&mut mdbuf).is_err() { - print_formatted = false; - } + // Try to print via the pager, pretty output if possible. + let pager_res: Option<()> = try { + let mut pager = cmd.stdin(Stdio::piped()).spawn().ok()?; - if let Ok(mut pager) = cmd.stdin(Stdio::piped()).spawn() { - if let Some(pipe) = pager.stdin.as_mut() { - let res = if print_formatted { - pipe.write_all(mdbuf.as_slice()) - } else { - pipe.write_all(content.as_bytes()) - }; - - if res.is_err() { - fallback_to_println = true; - } - } - - if pager.wait().is_err() { - fallback_to_println = true; - } - } else { - fallback_to_println = true; - } - - // If pager fails for whatever reason, we should still print the content - // to standard output - if fallback_to_println { - let fmt_success = match color { - ColorConfig::Auto | ColorConfig::Always => bufwtr.print(&mdbuf).is_ok(), - ColorConfig::Never => false, + let pager_stdin = pager.stdin.as_mut()?; + if pretty_on_pager && let Some((_, mdbuf)) = &pretty_data { + pager_stdin.write_all(mdbuf.as_slice()).ok()?; + } else { + pager_stdin.write_all(content.as_bytes()).ok()?; }; - if !fmt_success { - safe_print!("{content}"); - } + pager.wait().ok()?; + }; + if pager_res.is_some() { + return; } + + // The pager failed. Try to print pretty output to stdout. + if let Some((bufwtr, mdbuf)) = &pretty_data + && bufwtr.print(&mdbuf).is_ok() + { + return; + } + + // Everything failed. Print the raw markdown text. + safe_print!("{content}"); } fn process_rlink(sess: &Session, compiler: &interface::Compiler) { From 61a03fa98f8d9c28a08e80dcc4832728e5eb3241 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 21 Nov 2024 17:20:37 +0800 Subject: [PATCH 31/40] Don't exclude relnotes from `needs-triage` label --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 2483bfc4a411..b7a9b794c8be 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -451,7 +451,6 @@ new_issue = true exclude_labels = [ "C-tracking-issue", "A-diagnostics", - "relnotes-tracking-issue", ] [autolabel."WG-trait-system-refactor"] From 0db9059726dbec82abdc21935f84a7f0e12ea495 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Sun, 17 Nov 2024 21:59:43 -0500 Subject: [PATCH 32/40] aix: fix archive format fmt fix cfg for windows remove unused imports address comments update libc to 0.2.164 fmt remove unused imports --- Cargo.lock | 5 +- compiler/rustc_codegen_ssa/src/back/link.rs | 18 ++++++- .../rustc_codegen_ssa/src/back/metadata.rs | 23 ++++++++- compiler/rustc_metadata/Cargo.toml | 1 + compiler/rustc_metadata/src/creader.rs | 51 ++++++++++++++++++- compiler/rustc_metadata/src/locator.rs | 5 +- src/bootstrap/src/core/build_steps/compile.rs | 8 +-- src/bootstrap/src/core/build_steps/dist.rs | 11 ++-- src/bootstrap/src/core/build_steps/test.rs | 3 +- src/bootstrap/src/utils/helpers.rs | 24 ++++++++- 10 files changed, 127 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8d265597283..1aeab70bfb24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1965,9 +1965,9 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libdbus-sys" @@ -3988,6 +3988,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "bitflags 2.6.0", + "libc", "libloading", "odht", "rustc_abi", diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index fd1126e85284..5149e3a12f23 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -777,6 +777,16 @@ fn link_natively( info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); let self_contained_components = self_contained_components(sess, crate_type); + + // On AIX, we ship all libraries as .a big_af archive + // the expected format is lib.a(libname.so) for the actual + // dynamic library. So we link to a temporary .so file to be archived + // at the final out_filename location + let should_archive = crate_type != CrateType::Executable && sess.target.is_like_aix; + let archive_member = + should_archive.then(|| tmpdir.join(out_filename.file_name().unwrap()).with_extension("so")); + let temp_filename = archive_member.as_deref().unwrap_or(out_filename); + let mut cmd = linker_with_args( &linker_path, flavor, @@ -784,7 +794,7 @@ fn link_natively( archive_builder_builder, crate_type, tmpdir, - out_filename, + temp_filename, codegen_results, self_contained_components, )?; @@ -1158,6 +1168,12 @@ fn link_natively( } } + if should_archive { + let mut ab = archive_builder_builder.new_archive_builder(sess); + ab.add_file(temp_filename); + ab.build(out_filename); + } + Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index bdf7030f946c..ba7b53321a83 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -5,6 +5,7 @@ use std::fs::File; use std::io::Write; use std::path::Path; +use itertools::Itertools; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol, @@ -21,6 +22,7 @@ use rustc_middle::bug; use rustc_session::Session; use rustc_span::sym; use rustc_target::spec::{RelocModel, Target, ef_avr_arch}; +use tracing::debug; use super::apple; @@ -53,6 +55,7 @@ fn load_metadata_with( impl MetadataLoader for DefaultMetadataLoader { fn get_rlib_metadata(&self, target: &Target, path: &Path) -> Result { + debug!("getting rlib metadata for {}", path.display()); load_metadata_with(path, |data| { let archive = object::read::archive::ArchiveFile::parse(&*data) .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?; @@ -77,8 +80,26 @@ impl MetadataLoader for DefaultMetadataLoader { } fn get_dylib_metadata(&self, target: &Target, path: &Path) -> Result { + debug!("getting dylib metadata for {}", path.display()); if target.is_like_aix { - load_metadata_with(path, |data| get_metadata_xcoff(path, data)) + load_metadata_with(path, |data| { + let archive = object::read::archive::ArchiveFile::parse(&*data).map_err(|e| { + format!("failed to parse aix dylib '{}': {}", path.display(), e) + })?; + + match archive.members().exactly_one() { + Ok(lib) => { + let lib = lib.map_err(|e| { + format!("failed to parse aix dylib '{}': {}", path.display(), e) + })?; + let data = lib.data(data).map_err(|e| { + format!("failed to parse aix dylib '{}': {}", path.display(), e) + })?; + get_metadata_xcoff(path, data) + } + Err(e) => Err(format!("failed to parse aix dylib '{}': {}", path.display(), e)), + } + }) } else { load_metadata_with(path, |data| search_for_section(path, data, ".rustc")) } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index cece700b4dd1..12519be9870b 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +libc = "0.2" libloading = "0.8.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index ca16a66763ac..a611e8010be3 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -540,6 +540,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { Some(cnum) } Err(err) => { + debug!("failed to resolve crate {} {:?}", name, dep_kind); let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); err.report(self.sess, span, missing_core); @@ -588,6 +589,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match self.load(&mut locator)? { Some(res) => (res, None), None => { + info!("falling back to loading proc_macro"); dep_kind = CrateDepKind::MacrosOnly; match self.load_proc_macro(&mut locator, path_kind, host_hash)? { Some(res) => res, @@ -599,6 +601,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { + info!("library for `{}` was loaded previously", name); // When `private_dep` is none, it indicates the directly dependent crate. If it is // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to @@ -613,6 +616,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { Ok(cnum) } (LoadResult::Loaded(library), host_library) => { + info!("register newly loaded library for `{}`", name); self.register_crate(host_library, root, library, dep_kind, name, private_dep) } _ => panic!(), @@ -696,7 +700,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacro], CrateError> { let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); - Ok(unsafe { *load_symbol_from_dylib::<*const &[ProcMacro]>(path, &sym_name)? }) + debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); + + unsafe { + let result = load_symbol_from_dylib::<*const &[ProcMacro]>(path, &sym_name); + match result { + Ok(result) => { + debug!("loaded dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); + Ok(*result) + } + Err(err) => { + debug!( + "failed to dlsym proc_macros {} for symbol `{}`", + path.display(), + sym_name + ); + Err(err.into()) + } + } + } } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -1141,6 +1163,29 @@ fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String { e.sources().map(|e| format!(": {e}")).collect() } +fn attempt_load_dylib(path: &Path) -> Result { + #[cfg(target_os = "aix")] + if let Some(ext) = path.extension() + && ext.eq("a") + { + // On AIX, we ship all libraries as .a big_af archive + // the expected format is lib.a(libname.so) for the actual + // dynamic library + let library_name = path.file_stem().expect("expect a library name"); + let mut archive_member = OsString::from("a("); + archive_member.push(library_name); + archive_member.push(".so)"); + let new_path = path.with_extension(archive_member); + + // On AIX, we need RTLD_MEMBER to dlopen an archived shared + let flags = libc::RTLD_LAZY | libc::RTLD_LOCAL | libc::RTLD_MEMBER; + return unsafe { libloading::os::unix::Library::open(Some(&new_path), flags) } + .map(|lib| lib.into()); + } + + unsafe { libloading::Library::new(&path) } +} + // On Windows the compiler would sometimes intermittently fail to open the // proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the // system still holds a lock on the file, so we retry a few times before calling it @@ -1151,7 +1196,8 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result { if attempt > 0 { debug!( @@ -1165,6 +1211,7 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result { // Only try to recover from this specific error. if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { + debug!("Failed to load proc-macro `{}`. Not retrying", path.display()); let err = format_dlopen_err(&err); // We include the path of the dylib in the error ourselves, so // if it's in the error, we strip it. diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 0b53e5eeaa83..d59ec7af6ecc 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -847,7 +847,10 @@ fn get_metadata_section<'p>( ))); }; match blob.check_compatibility(cfg_version) { - Ok(()) => Ok(blob), + Ok(()) => { + debug!("metadata blob read okay"); + Ok(blob) + } Err(None) => Err(MetadataError::LoadFailure(format!( "invalid metadata version found: {}", filename.display() diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 24be705f4819..8e088682f92d 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1457,7 +1457,7 @@ impl Step for CodegenBackend { } let mut files = files.into_iter().filter(|f| { let filename = f.file_name().unwrap().to_str().unwrap(); - is_dylib(filename) && filename.contains("rustc_codegen_") + is_dylib(f) && filename.contains("rustc_codegen_") }); let codegen_backend = match files.next() { Some(f) => f, @@ -1936,7 +1936,7 @@ impl Step for Assemble { let filename = f.file_name().into_string().unwrap(); let is_proc_macro = proc_macros.contains(&filename); - let is_dylib_or_debug = is_dylib(&filename) || is_debug_info(&filename); + let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename); // If we link statically to stdlib, do not copy the libstd dynamic library file // FIXME: Also do this for Windows once incremental post-optimization stage0 tests @@ -2089,7 +2089,7 @@ pub fn run_cargo( if filename.ends_with(".lib") || filename.ends_with(".a") || is_debug_info(&filename) - || is_dylib(&filename) + || is_dylib(Path::new(&*filename)) { // Always keep native libraries, rust dylibs and debuginfo keep = true; @@ -2189,7 +2189,7 @@ pub fn run_cargo( Some(triple) => triple.0.to_str().unwrap(), None => panic!("no output generated for {prefix:?} {extension:?}"), }; - if is_dylib(path_to_add) { + if is_dylib(Path::new(path_to_add)) { let candidate = format!("{path_to_add}.lib"); let candidate = PathBuf::from(candidate); if candidate.exists() { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index c022285211fa..0216ac811621 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -436,13 +436,10 @@ impl Step for Rustc { if libdir_relative.to_str() != Some("bin") { let libdir = builder.rustc_libdir(compiler); for entry in builder.read_dir(&libdir) { - let name = entry.file_name(); - if let Some(s) = name.to_str() { - if is_dylib(s) { - // Don't use custom libdir here because ^lib/ will be resolved again - // with installer - builder.install(&entry.path(), &image.join("lib"), 0o644); - } + if is_dylib(&entry.path()) { + // Don't use custom libdir here because ^lib/ will be resolved again + // with installer + builder.install(&entry.path(), &image.join("lib"), 0o644); } } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 532c8f767eb1..dcea9f5f7d1d 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2949,8 +2949,7 @@ impl Step for RemoteCopyLibs { // Push all our dylibs to the emulator for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) { let f = t!(f); - let name = f.file_name().into_string().unwrap(); - if helpers::is_dylib(&name) { + if helpers::is_dylib(&f.path()) { command(&tool).arg("push").arg(f.path()).run(builder); } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 3fb2330469ae..9ca036a2afd4 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -11,6 +11,7 @@ use std::time::{Instant, SystemTime, UNIX_EPOCH}; use std::{env, fs, io, str}; use build_helper::util::fail; +use object::read::archive::ArchiveFile; use crate::LldMode; use crate::core::builder::Builder; @@ -53,8 +54,27 @@ pub fn exe(name: &str, target: TargetSelection) -> String { } /// Returns `true` if the file name given looks like a dynamic library. -pub fn is_dylib(name: &str) -> bool { - name.ends_with(".dylib") || name.ends_with(".so") || name.ends_with(".dll") +pub fn is_dylib(path: &Path) -> bool { + path.extension().and_then(|ext| ext.to_str()).map_or(false, |ext| { + ext == "dylib" || ext == "so" || ext == "dll" || (ext == "a" && is_aix_shared_archive(path)) + }) +} + +fn is_aix_shared_archive(path: &Path) -> bool { + // FIXME(#133268): reading the entire file as &[u8] into memory seems excessive + // look into either mmap it or use the ReadCache + let data = match fs::read(path) { + Ok(data) => data, + Err(_) => return false, + }; + let file = match ArchiveFile::parse(&*data) { + Ok(file) => file, + Err(_) => return false, + }; + + file.members() + .filter_map(Result::ok) + .any(|entry| String::from_utf8_lossy(entry.name()).contains(".so")) } /// Returns `true` if the file name given looks like a debug info file From 7426066bbc5083d64f6f6f839245dd98c2a2a860 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 21 Nov 2024 18:04:31 -0800 Subject: [PATCH 33/40] Add release notes for Rust 1.83.0 --- RELEASES.md | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 54465621b734..dcf47d30bffe 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,235 @@ +Version 1.83.0 (2024-11-28) +========================== + + + +Language +-------- +- [The `non_local_definitions` lint now uses a syntactic heuristic instead of type system based analysis](https://github.com/rust-lang/rust/pull/127117) +- [atomics: allow atomic and non-atomic reads to race](https://github.com/rust-lang/rust/pull/128778) +- [Non-exhaustive structs may be empty](https://github.com/rust-lang/rust/pull/128934/) +- [Check WF of source type's signature on fn pointer cast](https://github.com/rust-lang/rust/pull/129021) +- [Use equality when resolving type dependent paths](https://github.com/rust-lang/rust/pull/129073) +- [Stabilize `&mut` (and `*mut`) as well as `&Cell` (and `*const Cell`) in const](https://github.com/rust-lang/rust/pull/129195) +- [Disallow implicit coercions from places of type `!`](https://github.com/rust-lang/rust/pull/129392) +- [`const extern` functions can now be defined for other calling conventions.](https://github.com/rust-lang/rust/pull/129753) +- [Allow creating references to statics in `const` initializers](https://github.com/rust-lang/rust/pull/129759) +- [Stabilize `expr_2021` macro fragment specifier in all editions.](https://github.com/rust-lang/rust/pull/129972) + + + + +Compiler +-------- +- [Implement raw lifetimes and labels (`'r#ident`)](https://github.com/rust-lang/rust/pull/126452/) +- [Add `armv7-rtems-eabihf` tier 3 target.](https://github.com/rust-lang/rust/pull/127021) +- [Add `aarch64_unknown_nto_qnx700` tier 3 target - QNX 7.0 support for `aarch64le`](https://github.com/rust-lang/rust/pull/127897) +- [Add `x86_64-unknown-hurd-gnu` tier 3 target.](https://github.com/rust-lang/rust/pull/128345) +- [Deprecate unsound `-Csoft-float` flag](https://github.com/rust-lang/rust/pull/129897) +- [Fix a soundness bug where rustc wouldn't detect unconstrained higher-ranked lifetimes in a `dyn Trait`'s associated types that occur due to supertraits.](https://github.com/rust-lang/rust/pull/130367) +- [Add `x86_64-unknown-trusty` tier 3 target.](https://github.com/rust-lang/rust/pull/130453) +- [Add `riscv32-wrs-vxworks` and `riscv64-wrs-vxworks` tier 3 targets.](https://github.com/rust-lang/rust/pull/130549) +- [Add `riscv32{e|em|emc}-unknown-none-elf` tier 3 targets.](https://github.com/rust-lang/rust/pull/130555) +- [Add `arm64e-apple-tvos` tier 3 target.](https://github.com/rust-lang/rust/pull/130614) +- [Add `loongarch64-unknown-linux-ohos` tier 3 target.](https://github.com/rust-lang/rust/pull/130750) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + + +Libraries +--------- +- [Tracking Issue for `waker_getters`](https://github.com/rust-lang/rust/issues/96992/) +- [Implement `PartialEq` for `ExitCode`.](https://github.com/rust-lang/rust/pull/127633) +- [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) +- [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) +- [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) +- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). +- [Stabilize `const_slice_from_raw_parts_mut`](https://github.com/rust-lang/rust/pull/130403/) + + + + +Stabilized APIs +--------------- + +- [`BufRead::skip_until`](https://doc.rust-lang.org/stable/std/io/trait.BufRead.html#method.skip_until) +- [`ControlFlow::break_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.break_value) +- [`ControlFlow::continue_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.continue_value) +- [`ControlFlow::map_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_break) +- [`ControlFlow::map_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_continue) +- [`DebugList::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugList.html#method.finish_non_exhaustive) +- [`DebugMap::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugMap.html#method.finish_non_exhaustive) +- [`DebugSet::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugSet.html#method.finish_non_exhaustive) +- [`DebugTuple::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugTuple.html#method.finish_non_exhaustive) +- [`ErrorKind::ArgumentListTooLong`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ArgumentListTooLong) +- [`ErrorKind::Deadlock`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.Deadlock) +- [`ErrorKind::DirectoryNotEmpty`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.DirectoryNotEmpty) +- [`ErrorKind::ExecutableFileBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ExecutableFileBusy) +- [`ErrorKind::FileTooLarge`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.FileTooLarge) +- [`ErrorKind::HostUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.HostUnreachable) +- [`ErrorKind::IsADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.IsADirectory) +- [`ErrorKind::NetworkDown`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkDown) +- [`ErrorKind::NetworkUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkUnreachable) +- [`ErrorKind::NotADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotADirectory) +- [`ErrorKind::NotSeekable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotSeekable) +- [`ErrorKind::ReadOnlyFilesystem`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ReadOnlyFilesystem) +- [`ErrorKind::ResourceBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ResourceBusy) +- [`ErrorKind::StaleNetworkFileHandle`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StaleNetworkFileHandle) +- [`ErrorKind::StorageFull`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StorageFull) +- [`ErrorKind::TooManyLinks`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.TooManyLinks) +- [`Option::get_or_insert_default`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.get_or_insert_default) +- [`Waker::data`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.data) +- [`Waker::new`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.new) +- [`Waker::vtable`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.vtable) +- [`char::MIN`](https://doc.rust-lang.org/stable/core/primitive.char.html#associatedconstant.MIN) +- [`hash_map::Entry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/enum.Entry.html#method.insert_entry) +- [`hash_map::VacantEntry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/struct.VacantEntry.html#method.insert_entry) + +These APIs are now stable in const contexts: + +- [`Cell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.Cell.html#method.into_inner) +- [`Duration::as_secs_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f32) +- [`Duration::as_secs_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f64) +- [`Duration::div_duration_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f32) +- [`Duration::div_duration_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f64) +- [`MaybeUninit::as_mut_ptr`](https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#method.as_mut_ptr) +- [`NonNull::as_mut`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.as_mut) +- [`NonNull::copy_from`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from) +- [`NonNull::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from_nonoverlapping) +- [`NonNull::copy_to`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to) +- [`NonNull::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to_nonoverlapping) +- [`NonNull::slice_from_raw_parts`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.slice_from_raw_parts) +- [`NonNull::write`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write) +- [`NonNull::write_bytes`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_bytes) +- [`NonNull::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_unaligned) +- [`OnceCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.OnceCell.html#method.into_inner) +- [`Option::as_mut`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.as_mut) +- [`Option::expect`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.expect) +- [`Option::replace`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.replace) +- [`Option::take`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.take) +- [`Option::unwrap`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap) +- [`Option::unwrap_unchecked`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap_unchecked) +- [`Option::<&_>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied) +- [`Option::<&mut _>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied-1) +- [`Option::>::flatten`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.flatten) +- [`Option::>::transpose`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.transpose) +- [`RefCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html#method.into_inner) +- [`Result::as_mut`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.as_mut) +- [`Result::<&_, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied) +- [`Result::<&mut _, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied-1) +- [`Result::, _>::transpose`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.transpose) +- [`UnsafeCell::get_mut`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.get_mut) +- [`UnsafeCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.into_inner) +- [`array::from_mut`](https://doc.rust-lang.org/stable/core/array/fn.from_mut.html) +- [`char::encode_utf8`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.encode_utf8) +- [`$float::classify`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.classify) +- [`$float::is_finite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_finite) +- [`$float::is_infinite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_infinite) +- [`$float::is_nan`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_nan) +- [`$float::is_normal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_normal) +- [`$float::is_sign_negative`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_negative) +- [`$float::is_sign_positive`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_positive) +- [`$float::is_subnormal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_subnormal) +- [`$float::from_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_bits) +- [`$float::from_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_be_bytes) +- [`$float::from_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_le_bytes) +- [`$float::from_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_ne_bytes) +- [`$float::to_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_bits) +- [`$float::to_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_be_bytes) +- [`$float::to_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_le_bytes) +- [`$float::to_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_ne_bytes) +- [`mem::replace`](https://doc.rust-lang.org/stable/core/mem/fn.replace.html) +- [`ptr::replace`](https://doc.rust-lang.org/stable/core/ptr/fn.replace.html) +- [`ptr::slice_from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.slice_from_raw_parts_mut.html) +- [`ptr::write`](https://doc.rust-lang.org/stable/core/ptr/fn.write.html) +- [`ptr::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/fn.write_unaligned.html) +- [`<*const _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to) +- [`<*const _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping) +- [`<*mut _>::copy_from`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from) +- [`<*mut _>::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from_nonoverlapping) +- [`<*mut _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to-1) +- [`<*mut _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping-1) +- [`<*mut _>::write`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write) +- [`<*mut _>::write_bytes`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_bytes) +- [`<*mut _>::write_unaligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_unaligned) +- [`slice::from_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_mut.html) +- [`slice::from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts_mut.html) +- [`<[_]>::first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_mut) +- [`<[_]>::last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_mut) +- [`<[_]>::first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_chunk_mut) +- [`<[_]>::last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_chunk_mut) +- [`<[_]>::split_at_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut) +- [`<[_]>::split_at_mut_checked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_checked) +- [`<[_]>::split_at_mut_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_unchecked) +- [`<[_]>::split_first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_mut) +- [`<[_]>::split_last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_mut) +- [`<[_]>::split_first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_chunk_mut) +- [`<[_]>::split_last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_chunk_mut) +- [`str::as_bytes_mut`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_bytes_mut) +- [`str::as_mut_ptr`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_mut_ptr) +- [`str::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/core/str/fn.from_utf8_unchecked_mut.html) + + + + +Cargo +----- +- [Introduced a new `CARGO_MANIFEST_PATH` environment variable, similar to `CARGO_MANIFEST_DIR` but pointing directly to the manifest file.](https://github.com/rust-lang/cargo/pull/14404/) +- [Added `package.autolib` to the manifest, allowing `[lib]` auto-discovery to be disabled.](https://github.com/rust-lang/cargo/pull/14591/) +- [Declare support level for each crate in Cargo's Charter / crate docs.](https://github.com/rust-lang/cargo/pull/14600/) +- [Declare new Intentional Artifacts as 'small' changes.](https://github.com/rust-lang/cargo/pull/14599/) + + + + +Rustdoc +------- + +- [The sidebar / hamburger menu table of contents now includes the `# headers` from the main item's doc comment](https://github.com/rust-lang/rust/pull/120736). This is similar to a third-party feature provided by the rustdoc-search-enhancements browser extension. + + + + +Compatibility Notes +------------------- +- [Warn against function pointers using unsupported ABI strings.](https://github.com/rust-lang/rust/pull/128784) +- Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect](https://github.com/rust-lang/rust/pull/129422) +- The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. + Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. + Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. +- Until now, paths into the sysroot were always prefixed with `/rustc/$hash` in diagnostics, codegen, backtrace, e.g. + ``` + thread 'main' panicked at 'hello world', map-panic.rs:2:50 + stack backtrace: + 0: std::panicking::begin_panic + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:616:12 + 1: map_panic::main::{{closure}} + at ./map-panic.rs:2:50 + 2: core::option::Option::map + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/option.rs:929:29 + 3: map_panic::main + at ./map-panic.rs:2:30 + 4: core::ops::function::FnOnce::call_once + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5 + note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + ``` + [RFC 3127 said](https://rust-lang.github.io/rfcs/3127-trim-paths.html#changing-handling-of-sysroot-path-in-rustc) + > We want to change this behaviour such that, when `rust-src` source files can be discovered, the virtual path is discarded and therefore the local path will be embedded, unless there is a `--remap-path-prefix` that causes this local path to be remapped in the usual way. + [#129687](https://github.com/rust-lang/rust/pull/129687) implements this behaviour, when `rust-src` is present at compile time, `rustc` replaces `/rustc/$hash` with a real path into the local `rust-src` component with best effort. + To sanitize this, users must explicitly supply `--remap-path-prefix==foo` or not have the `rust-src` component installed. + - The allow-by-default `missing_docs` lint used to disable itself when invoked through `rustc --test`/`cargo test`, resulting in `#[expect(missing_docs)]` emitting false positives due to the expectation being wrongly unfulfilled. This behavior [has now been removed](https://github.com/rust-lang/rust/pull/130025), which allows `#[expect(missing_docs)]` to be fulfilled in all scenarios, but will also report new `missing_docs` diagnostics for publicly reachable `#[cfg(test)]` items, [integration test](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#integration-tests) crate-level documentation, and publicly reachable items in integration tests. +- [The `armv8r-none-eabihf` target now uses the Armv8-R required set of floating-point features.](https://github.com/rust-lang/rust/pull/130295) +- [Update the minimum external LLVM version to 18.](https://github.com/rust-lang/rust/pull/130487) +- [Remove `aarch64-fuchsia` and `x86_64-fuchsia` target aliases in favor of `aarch64-unknown-fuchsia` and `x86_64-unknown-fuchsia` respectively.](https://github.com/rust-lang/rust/pull/130657) +- [The ABI-level exception class of a Rust panic is now encoded with native-endian bytes, + so it is legible in hex dumps.](https://github.com/rust-lang/rust/pull/130897) +- [Visual Studio 2013 is no longer supported for MSVC targets.](https://github.com/rust-lang/rust/pull/131070) + + Version 1.82.0 (2024-10-17) ========================== From f77817a701c291b94fe6da25c4865bc50a8fcb1d Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 22 Nov 2024 05:20:39 +0000 Subject: [PATCH 34/40] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index effed0cd180d..e5812ae26030 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2d0ea7956c45de6e421fd579e2ded27be405dec6 +5d3c6ee9b34989595d2a72b79e61ca37e949d757 From c14f0a1d5173aefebee20f4c007a54070ac1f049 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 22 Nov 2024 14:15:50 -0800 Subject: [PATCH 35/40] Update relnotes from suggestions and issues sync --- RELEASES.md | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index dcf47d30bffe..2431015d2e9a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,15 +5,14 @@ Version 1.83.0 (2024-11-28) Language -------- -- [The `non_local_definitions` lint now uses a syntactic heuristic instead of type system based analysis](https://github.com/rust-lang/rust/pull/127117) -- [atomics: allow atomic and non-atomic reads to race](https://github.com/rust-lang/rust/pull/128778) -- [Non-exhaustive structs may be empty](https://github.com/rust-lang/rust/pull/128934/) -- [Check WF of source type's signature on fn pointer cast](https://github.com/rust-lang/rust/pull/129021) -- [Use equality when resolving type dependent paths](https://github.com/rust-lang/rust/pull/129073) -- [Stabilize `&mut` (and `*mut`) as well as `&Cell` (and `*const Cell`) in const](https://github.com/rust-lang/rust/pull/129195) +- [Implement raw lifetimes and labels (`'r#ident`).](https://github.com/rust-lang/rust/pull/126452) +- [The `non_local_definitions` lint now fires on less code and warns by default.](https://github.com/rust-lang/rust/pull/127117) +- [Define behavior when atomic and non-atomic reads race.](https://github.com/rust-lang/rust/pull/128778) +- [Non-exhaustive structs may now be empty.](https://github.com/rust-lang/rust/pull/128934) +- [Stabilize `&mut`, `*mut`, `&Cell`, and `*const Cell` in const.](https://github.com/rust-lang/rust/pull/129195) - [Disallow implicit coercions from places of type `!`](https://github.com/rust-lang/rust/pull/129392) - [`const extern` functions can now be defined for other calling conventions.](https://github.com/rust-lang/rust/pull/129753) -- [Allow creating references to statics in `const` initializers](https://github.com/rust-lang/rust/pull/129759) +- [Allow creating references to statics in `const` initializers.](https://github.com/rust-lang/rust/pull/129759) - [Stabilize `expr_2021` macro fragment specifier in all editions.](https://github.com/rust-lang/rust/pull/129972) @@ -21,17 +20,16 @@ Language Compiler -------- -- [Implement raw lifetimes and labels (`'r#ident`)](https://github.com/rust-lang/rust/pull/126452/) -- [Add `armv7-rtems-eabihf` tier 3 target.](https://github.com/rust-lang/rust/pull/127021) -- [Add `aarch64_unknown_nto_qnx700` tier 3 target - QNX 7.0 support for `aarch64le`](https://github.com/rust-lang/rust/pull/127897) -- [Add `x86_64-unknown-hurd-gnu` tier 3 target.](https://github.com/rust-lang/rust/pull/128345) -- [Deprecate unsound `-Csoft-float` flag](https://github.com/rust-lang/rust/pull/129897) -- [Fix a soundness bug where rustc wouldn't detect unconstrained higher-ranked lifetimes in a `dyn Trait`'s associated types that occur due to supertraits.](https://github.com/rust-lang/rust/pull/130367) -- [Add `x86_64-unknown-trusty` tier 3 target.](https://github.com/rust-lang/rust/pull/130453) -- [Add `riscv32-wrs-vxworks` and `riscv64-wrs-vxworks` tier 3 targets.](https://github.com/rust-lang/rust/pull/130549) -- [Add `riscv32{e|em|emc}-unknown-none-elf` tier 3 targets.](https://github.com/rust-lang/rust/pull/130555) -- [Add `arm64e-apple-tvos` tier 3 target.](https://github.com/rust-lang/rust/pull/130614) -- [Add `loongarch64-unknown-linux-ohos` tier 3 target.](https://github.com/rust-lang/rust/pull/130750) +- [Deprecate unsound `-Csoft-float` flag.](https://github.com/rust-lang/rust/pull/129897) +- Add many new tier 3 targets: + - [`aarch64_unknown_nto_qnx700`](https://github.com/rust-lang/rust/pull/127897) + - [`arm64e-apple-tvos`](https://github.com/rust-lang/rust/pull/130614) + - [`armv7-rtems-eabihf`](https://github.com/rust-lang/rust/pull/127021) + - [`loongarch64-unknown-linux-ohos`](https://github.com/rust-lang/rust/pull/130750) + - [`riscv32-wrs-vxworks` and `riscv64-wrs-vxworks`](https://github.com/rust-lang/rust/pull/130549) + - [`riscv32{e|em|emc}-unknown-none-elf`](https://github.com/rust-lang/rust/pull/130555) + - [`x86_64-unknown-hurd-gnu`](https://github.com/rust-lang/rust/pull/128345) + - [`x86_64-unknown-trusty`](https://github.com/rust-lang/rust/pull/130453) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. @@ -41,13 +39,11 @@ for more information on Rust's tiered platform support. Libraries --------- -- [Tracking Issue for `waker_getters`](https://github.com/rust-lang/rust/issues/96992/) - [Implement `PartialEq` for `ExitCode`.](https://github.com/rust-lang/rust/pull/127633) - [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) - [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) - [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) - [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). -- [Stabilize `const_slice_from_raw_parts_mut`](https://github.com/rust-lang/rust/pull/130403/) @@ -196,8 +192,10 @@ Rustdoc Compatibility Notes ------------------- - [Warn against function pointers using unsupported ABI strings.](https://github.com/rust-lang/rust/pull/128784) +- [Check well-formedness of the source type's signature in fn pointer casts.](https://github.com/rust-lang/rust/pull/129021) This partly closes a soundness hole that comes when casting a function item to function pointer +- [Use equality instead of subtyping when resolving type dependent paths.](https://github.com/rust-lang/rust/pull/129073) - Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . -- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect](https://github.com/rust-lang/rust/pull/129422) +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect.](https://github.com/rust-lang/rust/pull/129422) - The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. @@ -223,11 +221,12 @@ Compatibility Notes To sanitize this, users must explicitly supply `--remap-path-prefix==foo` or not have the `rust-src` component installed. - The allow-by-default `missing_docs` lint used to disable itself when invoked through `rustc --test`/`cargo test`, resulting in `#[expect(missing_docs)]` emitting false positives due to the expectation being wrongly unfulfilled. This behavior [has now been removed](https://github.com/rust-lang/rust/pull/130025), which allows `#[expect(missing_docs)]` to be fulfilled in all scenarios, but will also report new `missing_docs` diagnostics for publicly reachable `#[cfg(test)]` items, [integration test](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#integration-tests) crate-level documentation, and publicly reachable items in integration tests. - [The `armv8r-none-eabihf` target now uses the Armv8-R required set of floating-point features.](https://github.com/rust-lang/rust/pull/130295) +- [Fix a soundness bug where rustc wouldn't detect unconstrained higher-ranked lifetimes in a `dyn Trait`'s associated types that occur due to supertraits.](https://github.com/rust-lang/rust/pull/130367) - [Update the minimum external LLVM version to 18.](https://github.com/rust-lang/rust/pull/130487) - [Remove `aarch64-fuchsia` and `x86_64-fuchsia` target aliases in favor of `aarch64-unknown-fuchsia` and `x86_64-unknown-fuchsia` respectively.](https://github.com/rust-lang/rust/pull/130657) -- [The ABI-level exception class of a Rust panic is now encoded with native-endian bytes, - so it is legible in hex dumps.](https://github.com/rust-lang/rust/pull/130897) +- [The ABI-level exception class of a Rust panic is now encoded with native-endian bytes, so it is legible in hex dumps.](https://github.com/rust-lang/rust/pull/130897) - [Visual Studio 2013 is no longer supported for MSVC targets.](https://github.com/rust-lang/rust/pull/131070) +- [The sysroot no longer contains the `std` dynamic library in its top-level `lib/` dir.](https://github.com/rust-lang/rust/pull/131188) Version 1.82.0 (2024-10-17) From 3b8c0cccaaacbd3a2ceb78ccd16fbbca9156d9da Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 22 Nov 2024 14:16:59 -0800 Subject: [PATCH 36/40] Reorder lang relnotes --- RELEASES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 2431015d2e9a..4fedc3be66cc 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,15 +5,15 @@ Version 1.83.0 (2024-11-28) Language -------- +- [Stabilize `&mut`, `*mut`, `&Cell`, and `*const Cell` in const.](https://github.com/rust-lang/rust/pull/129195) +- [Allow creating references to statics in `const` initializers.](https://github.com/rust-lang/rust/pull/129759) - [Implement raw lifetimes and labels (`'r#ident`).](https://github.com/rust-lang/rust/pull/126452) -- [The `non_local_definitions` lint now fires on less code and warns by default.](https://github.com/rust-lang/rust/pull/127117) - [Define behavior when atomic and non-atomic reads race.](https://github.com/rust-lang/rust/pull/128778) - [Non-exhaustive structs may now be empty.](https://github.com/rust-lang/rust/pull/128934) -- [Stabilize `&mut`, `*mut`, `&Cell`, and `*const Cell` in const.](https://github.com/rust-lang/rust/pull/129195) - [Disallow implicit coercions from places of type `!`](https://github.com/rust-lang/rust/pull/129392) - [`const extern` functions can now be defined for other calling conventions.](https://github.com/rust-lang/rust/pull/129753) -- [Allow creating references to statics in `const` initializers.](https://github.com/rust-lang/rust/pull/129759) - [Stabilize `expr_2021` macro fragment specifier in all editions.](https://github.com/rust-lang/rust/pull/129972) +- [The `non_local_definitions` lint now fires on less code and warns by default.](https://github.com/rust-lang/rust/pull/127117) From d3d334294a944266784b96f5ed2859a848979675 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 22 Nov 2024 14:21:16 -0800 Subject: [PATCH 37/40] Add an empty line to fix markdown quoting --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index 4fedc3be66cc..068da5e6e256 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -217,6 +217,7 @@ Compatibility Notes ``` [RFC 3127 said](https://rust-lang.github.io/rfcs/3127-trim-paths.html#changing-handling-of-sysroot-path-in-rustc) > We want to change this behaviour such that, when `rust-src` source files can be discovered, the virtual path is discarded and therefore the local path will be embedded, unless there is a `--remap-path-prefix` that causes this local path to be remapped in the usual way. + [#129687](https://github.com/rust-lang/rust/pull/129687) implements this behaviour, when `rust-src` is present at compile time, `rustc` replaces `/rustc/$hash` with a real path into the local `rust-src` component with best effort. To sanitize this, users must explicitly supply `--remap-path-prefix==foo` or not have the `rust-src` component installed. - The allow-by-default `missing_docs` lint used to disable itself when invoked through `rustc --test`/`cargo test`, resulting in `#[expect(missing_docs)]` emitting false positives due to the expectation being wrongly unfulfilled. This behavior [has now been removed](https://github.com/rust-lang/rust/pull/130025), which allows `#[expect(missing_docs)]` to be fulfilled in all scenarios, but will also report new `missing_docs` diagnostics for publicly reachable `#[cfg(test)]` items, [integration test](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#integration-tests) crate-level documentation, and publicly reachable items in integration tests. From c7195c4447549f8b9b4d0ac035d2e5ec2f55b8a7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 22 Nov 2024 15:59:37 -0800 Subject: [PATCH 38/40] Change `$float` to `{float}` in relnotes Co-authored-by: Urgau <3616612+Urgau@users.noreply.github.com> --- RELEASES.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 068da5e6e256..f58629627ea7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -121,22 +121,22 @@ These APIs are now stable in const contexts: - [`UnsafeCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.into_inner) - [`array::from_mut`](https://doc.rust-lang.org/stable/core/array/fn.from_mut.html) - [`char::encode_utf8`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.encode_utf8) -- [`$float::classify`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.classify) -- [`$float::is_finite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_finite) -- [`$float::is_infinite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_infinite) -- [`$float::is_nan`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_nan) -- [`$float::is_normal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_normal) -- [`$float::is_sign_negative`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_negative) -- [`$float::is_sign_positive`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_positive) -- [`$float::is_subnormal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_subnormal) -- [`$float::from_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_bits) -- [`$float::from_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_be_bytes) -- [`$float::from_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_le_bytes) -- [`$float::from_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_ne_bytes) -- [`$float::to_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_bits) -- [`$float::to_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_be_bytes) -- [`$float::to_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_le_bytes) -- [`$float::to_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_ne_bytes) +- [`{float}::classify`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.classify) +- [`{float}::is_finite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_finite) +- [`{float}::is_infinite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_infinite) +- [`{float}::is_nan`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_nan) +- [`{float}::is_normal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_normal) +- [`{float}::is_sign_negative`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_negative) +- [`{float}::is_sign_positive`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_positive) +- [`{float}::is_subnormal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_subnormal) +- [`{float}::from_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_bits) +- [`{float}::from_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_be_bytes) +- [`{float}::from_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_le_bytes) +- [`{float}::from_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_ne_bytes) +- [`{float}::to_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_bits) +- [`{float}::to_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_be_bytes) +- [`{float}::to_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_le_bytes) +- [`{float}::to_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_ne_bytes) - [`mem::replace`](https://doc.rust-lang.org/stable/core/mem/fn.replace.html) - [`ptr::replace`](https://doc.rust-lang.org/stable/core/ptr/fn.replace.html) - [`ptr::slice_from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.slice_from_raw_parts_mut.html) From 46cd0c526691f485365e57228c99db8f7c16c324 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 22 Nov 2024 16:00:16 -0800 Subject: [PATCH 39/40] Also change an older `$integer` to `{integer}` --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f58629627ea7..3707f170a573 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -357,7 +357,7 @@ These APIs are now stable in const contexts: - [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) - [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker) - [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker) -- [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) +- [`{integer}::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) - [`std::num::ParseIntError::kind`](https://doc.rust-lang.org/nightly/std/num/struct.ParseIntError.html#method.kind) From 7dcba03d28ee69764e5a9492d1f1f2518e36834f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Nov 2024 07:37:38 +0100 Subject: [PATCH 40/40] disable solaris on CI for now --- src/tools/miri/ci/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 0356d7ecf101..9b020d029a68 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -153,7 +153,7 @@ case $HOST_TARGET in TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + # TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std