From 4d747128eb1e1c0da7432b071107d29721e19a04 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 26 May 2024 00:11:32 +0100 Subject: [PATCH 01/25] Tweak type inference for `const` operands in inline asm Previously these would be treated like integer literals and default to `i32` if a type could not be determined. To allow for forward-compatibility with `str` constants in the future, this PR changes type inference to use an unbound type variable instead. The actual type checking is deferred until after typeck where we still ensure that the final type for the `const` operand is an integer type. --- .../src/check/intrinsicck.rs | 24 +++++++++++++++---- compiler/rustc_hir_typeck/src/lib.rs | 9 ++++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 2e965c59ebb53..9286d3d83bffc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -455,10 +455,26 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ); } } - // No special checking is needed for these: - // - Typeck has checked that Const operands are integers. - // - AST lowering guarantees that SymStatic points to a static. - hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {} + hir::InlineAsmOperand::Const { anon_const } => { + let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity(); + match ty.kind() { + ty::Error(_) => {} + ty::Int(_) | ty::Uint(_) => {} + _ => { + self.tcx + .dcx() + .struct_span_err(*op_sp, "invalid type for `const` operand") + .with_span_label( + self.tcx.def_span(anon_const.def_id), + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help("`const` operands must be of an integer type") + .emit(); + } + }; + } + // AST lowering guarantees that SymStatic points to a static. + hir::InlineAsmOperand::SymStatic { .. } => {} // Check that sym actually points to a function. Later passes // depend on this. hir::InlineAsmOperand::SymFn { anon_const } => { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 2c79366450909..ebb42e766701d 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -264,11 +264,10 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => { asm.operands.iter().find_map(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { - // Inline assembly constants must be integers. - Some(fcx.next_int_var()) - } - hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => { + hir::InlineAsmOperand::Const { anon_const } + | hir::InlineAsmOperand::SymFn { anon_const } + if anon_const.hir_id == id => + { Some(fcx.next_ty_var(span)) } _ => None, From 575fc72350d46030fd5e187b5d25fd455e43f406 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 11 Jun 2024 15:47:46 +0100 Subject: [PATCH 02/25] Work around #96304 by ignoring one test case --- tests/ui/asm/type-check-1.rs | 13 +++--- tests/ui/asm/type-check-1.stderr | 72 ++++++++++++++++---------------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index b0f1362f54334..09aa4a584ce12 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -55,11 +55,12 @@ fn main() { asm!("{}", const 0i32); asm!("{}", const 0i128); asm!("{}", const 0f32); - //~^ ERROR mismatched types + //~^ ERROR invalid type for `const` operand asm!("{}", const 0 as *mut u8); - //~^ ERROR mismatched types - asm!("{}", const &0); - //~^ ERROR mismatched types + //~^ ERROR invalid type for `const` operand + + // FIXME: Currently ICEs due to #96304 + //asm!("{}", const &0); } } @@ -73,6 +74,6 @@ global_asm!("{}", const 0); global_asm!("{}", const 0i32); global_asm!("{}", const 0i128); global_asm!("{}", const 0f32); -//~^ ERROR mismatched types +//~^ ERROR invalid type for `const` operand global_asm!("{}", const 0 as *mut u8); -//~^ ERROR mismatched types +//~^ ERROR invalid type for `const` operand diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index 1852623211813..30cd7fb42952e 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -39,6 +39,26 @@ LL | asm!("{}", sym x); | = help: `sym` operands must refer to either a function or a static +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:76:19 + | +LL | global_asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:78:19 + | +LL | global_asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -102,49 +122,27 @@ LL | asm!("{}", inout(reg) v[..]); | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error[E0308]: mismatched types - --> $DIR/type-check-1.rs:57:26 +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:57:20 | LL | asm!("{}", const 0f32); - | ^^^^ expected integer, found `f32` - -error[E0308]: mismatched types - --> $DIR/type-check-1.rs:59:26 - | -LL | asm!("{}", const 0 as *mut u8); - | ^^^^^^^^^^^^ expected integer, found `*mut u8` + | ^^^^^^---- + | | + | is an `f32` | - = note: expected type `{integer}` - found raw pointer `*mut u8` + = help: `const` operands must be of an integer type -error[E0308]: mismatched types - --> $DIR/type-check-1.rs:61:26 +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:59:20 | -LL | asm!("{}", const &0); - | ^^ expected integer, found `&{integer}` - | -help: consider removing the borrow - | -LL - asm!("{}", const &0); -LL + asm!("{}", const 0); - | - -error[E0308]: mismatched types - --> $DIR/type-check-1.rs:75:25 - | -LL | global_asm!("{}", const 0f32); - | ^^^^ expected integer, found `f32` - -error[E0308]: mismatched types - --> $DIR/type-check-1.rs:77:25 - | -LL | global_asm!("{}", const 0 as *mut u8); - | ^^^^^^^^^^^^ expected integer, found `*mut u8` +LL | asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` | - = note: expected type `{integer}` - found raw pointer `*mut u8` + = help: `const` operands must be of an integer type -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0277, E0308, E0435. +Some errors have detailed explanations: E0277, E0435. For more information about an error, try `rustc --explain E0277`. From 97738e1b868567f0c1222179945ae3b387630c82 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 21 Jul 2024 18:02:59 +0200 Subject: [PATCH 03/25] apply fix suggested by lcnr --- .../src/check/intrinsicck.rs | 52 ++++---------- .../rustc_hir_analysis/src/collect/type_of.rs | 72 +++++++++++++++++-- tests/ui/asm/type-check-1.rs | 4 +- tests/ui/asm/type-check-1.stderr | 52 ++++++++------ tests/ui/asm/x86_64/type-check-2.stderr | 32 ++++----- 5 files changed, 127 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 9286d3d83bffc..6ea8e838d5cee 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -2,7 +2,7 @@ use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; -use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; +use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::Symbol; @@ -455,48 +455,22 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ); } } + // Typeck has checked that Const operands are integers. hir::InlineAsmOperand::Const { anon_const } => { - let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity(); - match ty.kind() { - ty::Error(_) => {} - ty::Int(_) | ty::Uint(_) => {} - _ => { - self.tcx - .dcx() - .struct_span_err(*op_sp, "invalid type for `const` operand") - .with_span_label( - self.tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ) - .with_help("`const` operands must be of an integer type") - .emit(); - } - }; + debug_assert!(matches!( + self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), + ty::Error(_) | ty::Int(_) | ty::Uint(_) + )); } - // AST lowering guarantees that SymStatic points to a static. - hir::InlineAsmOperand::SymStatic { .. } => {} - // Check that sym actually points to a function. Later passes - // depend on this. + // Typeck has checked that SymFn refers to a function. hir::InlineAsmOperand::SymFn { anon_const } => { - let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity(); - match ty.kind() { - ty::Never | ty::Error(_) => {} - ty::FnDef(..) => {} - _ => { - self.tcx - .dcx() - .struct_span_err(*op_sp, "invalid `sym` operand") - .with_span_label( - self.tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ) - .with_help( - "`sym` operands must refer to either a function or a static", - ) - .emit(); - } - }; + debug_assert!(matches!( + self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), + ty::Error(_) | ty::Never | ty::FnDef(..) + )); } + // AST lowering guarantees that SymStatic points to a static. + hir::InlineAsmOperand::SymStatic { .. } => {} // No special checking is needed for labels. hir::InlineAsmOperand::Label { .. } => {} } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 9affd654366f1..a0d438caf8f93 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -6,7 +6,7 @@ use rustc_hir::HirId; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -35,6 +35,20 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node = tcx.hir_node(parent_node_id); + let find_sym_fn = |&(op, op_sp)| match op { + hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => { + Some((anon_const, op_sp)) + } + _ => None, + }; + + let find_const = |&(op, op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => { + Some((anon_const, op_sp)) + } + _ => None, + }; + match parent_node { // Anon consts "inside" the type system. Node::ConstArg(&ConstArg { @@ -46,13 +60,57 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) - if asm.operands.iter().any(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, - _ => false, - }) => + if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => { - tcx.typeck(def_id).node_type(hir_id) + let ty = tcx.typeck(def_id).node_type(hir_id); + + match ty.kind() { + ty::Never | ty::Error(_) => ty, + ty::FnDef(..) => ty, + _ => { + tcx.dcx() + .struct_span_err(op_sp, "invalid `sym` operand") + .with_span_label( + tcx.def_span(anon_const.def_id), + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help("`sym` operands must refer to either a function or a static") + .emit(); + + Ty::new_error_with_message( + tcx, + span, + format!("invalid type for `const` operand"), + ) + } + } + } + Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => + { + let ty = tcx.typeck(def_id).node_type(hir_id); + + match ty.kind() { + ty::Error(_) => ty, + ty::Int(_) | ty::Uint(_) => ty, + _ => { + tcx.dcx() + .struct_span_err(op_sp, "invalid type for `const` operand") + .with_span_label( + tcx.def_span(anon_const.def_id), + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help("`const` operands must be of an integer type") + .emit(); + + Ty::new_error_with_message( + tcx, + span, + format!("invalid type for `const` operand"), + ) + } + } } Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index 09aa4a584ce12..ad1a391539f1a 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -59,8 +59,8 @@ fn main() { asm!("{}", const 0 as *mut u8); //~^ ERROR invalid type for `const` operand - // FIXME: Currently ICEs due to #96304 - //asm!("{}", const &0); + asm!("{}", const &0); + //~^ ERROR invalid type for `const` operand } } diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index 30cd7fb42952e..bbed571284903 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -39,26 +39,6 @@ LL | asm!("{}", sym x); | = help: `sym` operands must refer to either a function or a static -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:76:19 - | -LL | global_asm!("{}", const 0f32); - | ^^^^^^---- - | | - | is an `f32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:78:19 - | -LL | global_asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type - error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -142,7 +122,37 @@ LL | asm!("{}", const 0 as *mut u8); | = help: `const` operands must be of an integer type -error: aborting due to 16 previous errors +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:62:20 + | +LL | asm!("{}", const &0); + | ^^^^^^-- + | | + | is a `&i32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:76:19 + | +LL | global_asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/type-check-1.rs:78:19 + | +LL | global_asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + +error: aborting due to 17 previous errors Some errors have detailed explanations: E0277, E0435. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index 6ae118b16e766..e82a7c92664e5 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -6,22 +6,6 @@ LL | asm!("{}", sym x); | = help: `sym` operands must refer to either a function or a static -error: invalid `sym` operand - --> $DIR/type-check-2.rs:89:19 - | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - -error: invalid `sym` operand - --> $DIR/type-check-2.rs:36:20 - | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - error: arguments for inline assembly must be copyable --> $DIR/type-check-2.rs:43:32 | @@ -79,6 +63,14 @@ LL | asm!("{}", inout(reg) r); | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly +error: invalid `sym` operand + --> $DIR/type-check-2.rs:36:20 + | +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2.rs:15:28 | @@ -121,6 +113,14 @@ help: consider changing this to be mutable LL | let mut v: Vec = vec![0, 1, 2]; | +++ +error: invalid `sym` operand + --> $DIR/type-check-2.rs:89:19 + | +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + error: aborting due to 13 previous errors Some errors have detailed explanations: E0381, E0596. From c77b56901fc8098c36717a7620b1c89d3f01c14e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 22 Jul 2024 20:44:32 +0200 Subject: [PATCH 04/25] Apply suggestions from code review Co-authored-by: Amanieu d'Antras --- compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 2 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 6ea8e838d5cee..847a1e6470679 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -466,7 +466,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { hir::InlineAsmOperand::SymFn { anon_const } => { debug_assert!(matches!( self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), - ty::Error(_) | ty::Never | ty::FnDef(..) + ty::Error(_) | ty::FnDef(..) )); } // AST lowering guarantees that SymStatic points to a static. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index a0d438caf8f93..001b2190fc715 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -65,7 +65,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let ty = tcx.typeck(def_id).node_type(hir_id); match ty.kind() { - ty::Never | ty::Error(_) => ty, + ty::Error(_) => ty, ty::FnDef(..) => ty, _ => { tcx.dcx() @@ -80,7 +80,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { Ty::new_error_with_message( tcx, span, - format!("invalid type for `const` operand"), + format!("invalid type for `sym` operand"), ) } } From d4ca1ac8b9d96ebb32b9bde8a7485b1ac857c10d Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 23 Jul 2024 23:31:34 +0100 Subject: [PATCH 05/25] rustfmt --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 001b2190fc715..75826936c09fb 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -77,11 +77,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .with_help("`sym` operands must refer to either a function or a static") .emit(); - Ty::new_error_with_message( - tcx, - span, - format!("invalid type for `sym` operand"), - ) + Ty::new_error_with_message(tcx, span, format!("invalid type for `sym` operand")) } } } From be66415e11234832b0ba10007d7445aef6213cb6 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 25 Jul 2024 10:29:59 +0200 Subject: [PATCH 06/25] use `ErrorGuaranteed` from emit --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 75826936c09fb..8b5a8500f71e1 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -68,7 +68,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { ty::Error(_) => ty, ty::FnDef(..) => ty, _ => { - tcx.dcx() + let guar = tcx + .dcx() .struct_span_err(op_sp, "invalid `sym` operand") .with_span_label( tcx.def_span(anon_const.def_id), @@ -77,7 +78,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .with_help("`sym` operands must refer to either a function or a static") .emit(); - Ty::new_error_with_message(tcx, span, format!("invalid type for `sym` operand")) + Ty::new_error(tcx, guar) } } } @@ -91,7 +92,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { ty::Error(_) => ty, ty::Int(_) | ty::Uint(_) => ty, _ => { - tcx.dcx() + let guar = tcx + .dcx() .struct_span_err(op_sp, "invalid type for `const` operand") .with_span_label( tcx.def_span(anon_const.def_id), @@ -100,11 +102,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .with_help("`const` operands must be of an integer type") .emit(); - Ty::new_error_with_message( - tcx, - span, - format!("invalid type for `const` operand"), - ) + Ty::new_error(tcx, guar) } } } From 794434ec639277273d2154607bdcbe033691cc29 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 21:52:32 +0000 Subject: [PATCH 07/25] initial implementation of rustdoc nested aux-build --- src/tools/compiletest/src/command-list.rs | 2 + src/tools/compiletest/src/header.rs | 13 +++ src/tools/compiletest/src/runtest.rs | 104 ++++++++++++------ src/tools/compiletest/src/runtest/coverage.rs | 2 +- .../cargo-transitive-no-index/auxiliary/q.rs | 4 + .../cargo-transitive-no-index/auxiliary/t.rs | 6 + .../cargo-transitive-no-index/s.rs | 17 +++ .../cargo-transitive/auxiliary/q.rs | 6 + .../cargo-transitive/auxiliary/t.rs | 8 ++ .../cross-crate-info/cargo-transitive/s.rs | 24 ++++ .../cargo-two-no-index/auxiliary/f.rs | 4 + .../cross-crate-info/cargo-two-no-index/e.rs | 15 +++ .../cross-crate-info/cargo-two/auxiliary/f.rs | 6 + tests/rustdoc/cross-crate-info/cargo-two/e.rs | 21 ++++ .../index-on-last/auxiliary/f.rs | 4 + .../cross-crate-info/index-on-last/e.rs | 21 ++++ .../kitchen-sink/auxiliary/q.rs | 6 + .../kitchen-sink/auxiliary/r.rs | 8 ++ .../kitchen-sink/auxiliary/s.rs | 9 ++ .../kitchen-sink/auxiliary/t.rs | 8 ++ .../cross-crate-info/kitchen-sink/i.rs | 32 ++++++ .../single-crate-baseline/q.rs | 13 +++ .../single-crate-no-index/q.rs | 8 ++ .../transitive/auxiliary/q.rs | 4 + .../transitive/auxiliary/t.rs | 6 + .../rustdoc/cross-crate-info/transitive/s.rs | 9 ++ .../cross-crate-info/two/auxiliary/f.rs | 4 + tests/rustdoc/cross-crate-info/two/e.rs | 9 ++ .../working-dir-examples/q.rs | 10 ++ .../write-docs-somewhere-else/auxiliary/f.rs | 5 + .../write-docs-somewhere-else/e.rs | 15 +++ 31 files changed, 369 insertions(+), 34 deletions(-) create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/s.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/e.rs create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/e.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/i.rs create mode 100644 tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs create mode 100644 tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/s.rs create mode 100644 tests/rustdoc/cross-crate-info/two/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/two/e.rs create mode 100644 tests/rustdoc/cross-crate-info/working-dir-examples/q.rs create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index c356f4266f016..305bf9c228c43 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -9,6 +9,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "aux-codegen-backend", "aux-crate", "build-aux-docs", + "unique-doc-out-dir", "build-fail", "build-pass", "check-fail", @@ -18,6 +19,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-test-line-numbers-match", "compare-output-lines-by-subset", "compile-flags", + "doc-flags", "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0208ed34ac182..3a08a8e38950c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -95,6 +95,8 @@ pub struct TestProps { pub compile_flags: Vec, // Extra flags to pass when the compiled code is run (such as --bench) pub run_flags: Vec, + /// Extra flags to pass to rustdoc but not the compiler. + pub doc_flags: Vec, // If present, the name of a file that this test should match when // pretty-printed pub pp_exact: Option, @@ -122,6 +124,9 @@ pub struct TestProps { pub unset_exec_env: Vec, // Build documentation for all specified aux-builds as well pub build_aux_docs: bool, + /// Build the documentation for each crate in a unique output directory. + /// Uses /docs//doc + pub unique_doc_out_dir: bool, // Flag to force a crate to be built with the host architecture pub force_host: bool, // Check stdout for error-pattern output as well as stderr @@ -220,8 +225,10 @@ mod directives { pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern"; pub const COMPILE_FLAGS: &'static str = "compile-flags"; pub const RUN_FLAGS: &'static str = "run-flags"; + pub const DOC_FLAGS: &'static str = "doc-flags"; pub const SHOULD_ICE: &'static str = "should-ice"; pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs"; + pub const UNIQUE_DOC_OUT_DIR: &'static str = "unique-doc-out-dir"; pub const FORCE_HOST: &'static str = "force-host"; pub const CHECK_STDOUT: &'static str = "check-stdout"; pub const CHECK_RUN_RESULTS: &'static str = "check-run-results"; @@ -267,6 +274,7 @@ impl TestProps { regex_error_patterns: vec![], compile_flags: vec![], run_flags: vec![], + doc_flags: vec![], pp_exact: None, aux_builds: vec![], aux_bins: vec![], @@ -281,6 +289,7 @@ impl TestProps { exec_env: vec![], unset_exec_env: vec![], build_aux_docs: false, + unique_doc_out_dir: false, force_host: false, check_stdout: false, check_run_results: false, @@ -377,6 +386,8 @@ impl TestProps { |r| r, ); + config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r); + fn split_flags(flags: &str) -> Vec { // Individual flags can be single-quoted to preserve spaces; see // . @@ -414,6 +425,8 @@ impl TestProps { config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs); + config.set_name_directive(ln, UNIQUE_DOC_OUT_DIR, &mut self.unique_doc_out_dir); + config.set_name_directive(ln, FORCE_HOST, &mut self.force_host); config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout); config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6e8fdd624434..2d298dfbc06f7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,5 +1,17 @@ // ignore-tidy-filelength +use crate::compute_diff::{write_diff, write_filtered_diff}; +use crate::errors::{self, Error, ErrorKind}; +use crate::header::TestProps; +use crate::json; +use crate::read2::{read2_abbreviated, Truncated}; +use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt}; +use crate::ColorConfig; +use colored::Colorize; +use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; +use regex::{Captures, Regex}; +use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; use std::fs::{self, create_dir_all, File, OpenOptions}; @@ -723,7 +735,7 @@ impl<'test> TestCx<'test> { self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags); rustc.args(&self.props.compile_flags); - self.compose_and_run_compiler(rustc, Some(src)) + self.compose_and_run_compiler(rustc, Some(src), self.testpaths) } fn run_debuginfo_test(&self) { @@ -1579,13 +1591,15 @@ impl<'test> TestCx<'test> { passes, ); - self.compose_and_run_compiler(rustc, None) + self.compose_and_run_compiler(rustc, None, self.testpaths) } - fn document(&self, out_dir: &Path) -> ProcRes { + /// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run. + /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths. + fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes { if self.props.build_aux_docs { for rel_ab in &self.props.aux_builds { - let aux_testpaths = self.compute_aux_test_paths(&self.testpaths, rel_ab); + let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { @@ -1596,7 +1610,7 @@ impl<'test> TestCx<'test> { }; // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); - let auxres = aux_cx.document(out_dir); + let auxres = aux_cx.document(&root_out_dir, root_testpaths); if !auxres.status.success() { return auxres; } @@ -1606,21 +1620,47 @@ impl<'test> TestCx<'test> { let aux_dir = self.aux_output_dir_name(); let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed"); - let mut rustdoc = Command::new(rustdoc_path); + // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire + // test + let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir { + let file_name = self + .testpaths + .file + .file_name() + .expect("file name should not be empty") + .to_str() + .expect("file name utf8") + .trim_end_matches(".rs"); + let out_dir = PathBuf::from_iter([ + root_out_dir, + Path::new("docs"), + Path::new(file_name), + Path::new("doc"), + ]); + create_dir_all(&out_dir).unwrap(); + Cow::Owned(out_dir) + } else { + Cow::Borrowed(root_out_dir) + }; + + let mut rustdoc = Command::new(rustdoc_path); + let current_dir = output_base_dir(self.config, root_testpaths, self.safe_revision()); + rustdoc.current_dir(current_dir); rustdoc .arg("-L") .arg(self.config.run_lib_path.to_str().unwrap()) .arg("-L") .arg(aux_dir) .arg("-o") - .arg(out_dir) + .arg(out_dir.as_ref()) .arg("--deny") .arg("warnings") .arg(&self.testpaths.file) .arg("-A") .arg("internal_features") - .args(&self.props.compile_flags); + .args(&self.props.compile_flags) + .args(&self.props.doc_flags); if self.config.mode == RustdocJson { rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options"); @@ -1630,7 +1670,7 @@ impl<'test> TestCx<'test> { rustdoc.arg(format!("-Clinker={}", linker)); } - self.compose_and_run_compiler(rustdoc, None) + self.compose_and_run_compiler(rustdoc, None, root_testpaths) } fn exec_compiled_test(&self) -> ProcRes { @@ -1828,9 +1868,16 @@ impl<'test> TestCx<'test> { } } - fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { + /// `root_testpaths` refers to the path of the original test. + /// the auxiliary and the test with an aux-build have the same `root_testpaths`. + fn compose_and_run_compiler( + &self, + mut rustc: Command, + input: Option, + root_testpaths: &TestPaths, + ) -> ProcRes { let aux_dir = self.aux_output_dir(); - self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc); + self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc); rustc.envs(self.props.rustc_env.clone()); self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove); @@ -2545,7 +2592,7 @@ impl<'test> TestCx<'test> { Vec::new(), ); - let proc_res = self.compose_and_run_compiler(rustc, None); + let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); let output_path = self.get_filecheck_file("ll"); (proc_res, output_path) } @@ -2581,7 +2628,7 @@ impl<'test> TestCx<'test> { Vec::new(), ); - let proc_res = self.compose_and_run_compiler(rustc, None); + let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); let output_path = self.get_filecheck_file("s"); (proc_res, output_path) } @@ -2664,7 +2711,7 @@ impl<'test> TestCx<'test> { let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir); - let proc_res = self.document(&out_dir); + let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc failed!", &proc_res); } @@ -2723,7 +2770,7 @@ impl<'test> TestCx<'test> { let aux_dir = new_rustdoc.aux_output_dir(); new_rustdoc.build_all_auxiliary(&new_rustdoc.testpaths, &aux_dir, &mut rustc); - let proc_res = new_rustdoc.document(&compare_dir); + let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths); if !proc_res.status.success() { eprintln!("failed to run nightly rustdoc"); return; @@ -2846,7 +2893,7 @@ impl<'test> TestCx<'test> { let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir); - let proc_res = self.document(&out_dir); + let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc failed!", &proc_res); } @@ -2922,24 +2969,15 @@ impl<'test> TestCx<'test> { fn check_rustdoc_test_option(&self, res: ProcRes) { let mut other_files = Vec::new(); let mut files: HashMap> = HashMap::new(); - let cwd = env::current_dir().unwrap(); - files.insert( - self.testpaths - .file - .strip_prefix(&cwd) - .unwrap_or(&self.testpaths.file) - .to_str() - .unwrap() - .replace('\\', "/"), - self.get_lines(&self.testpaths.file, Some(&mut other_files)), - ); + let normalized = fs::canonicalize(&self.testpaths.file).expect("failed to canonicalize"); + let normalized = normalized.to_str().unwrap().replace('\\', "/"); + files.insert(normalized, self.get_lines(&self.testpaths.file, Some(&mut other_files))); for other_file in other_files { let mut path = self.testpaths.file.clone(); path.set_file_name(&format!("{}.rs", other_file)); - files.insert( - path.strip_prefix(&cwd).unwrap_or(&path).to_str().unwrap().replace('\\', "/"), - self.get_lines(&path, None), - ); + let path = fs::canonicalize(path).expect("failed to canonicalize"); + let normalized = path.to_str().unwrap().replace('\\', "/"); + files.insert(normalized, self.get_lines(&path, None)); } let mut tested = 0; @@ -3778,7 +3816,7 @@ impl<'test> TestCx<'test> { if let Some(nodejs) = &self.config.nodejs { let out_dir = self.output_base_dir(); - self.document(&out_dir); + self.document(&out_dir, &self.testpaths); let root = self.config.find_rust_src_root().unwrap(); let file_stem = @@ -4094,7 +4132,7 @@ impl<'test> TestCx<'test> { rustc.arg(crate_name); } - let res = self.compose_and_run_compiler(rustc, None); + let res = self.compose_and_run_compiler(rustc, None, self.testpaths); if !res.status.success() { self.fatal_proc_rec("failed to compile fixed code", &res); } diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index 6ee147da5a965..05191a159801c 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -191,7 +191,7 @@ impl<'test> TestCx<'test> { rustdoc_cmd.arg(&self.testpaths.file); - let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); + let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None, self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc --test failed!", &proc_res) } diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs new file mode 100644 index 0000000000000..32ad96d3e8e36 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs new file mode 100644 index 0000000000000..e03c9a1c68c3b --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs @@ -0,0 +1,6 @@ +//@ aux-build:q.rs +//@ build-aux-docs + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs new file mode 100644 index 0000000000000..af0d31c733ee1 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -0,0 +1,17 @@ +//@ aux-build:t.rs +//@ build-aux-docs + +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Quebec' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has q/struct.Quebec.html +//@ has s/struct.Sierra.html + +// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs new file mode 100644 index 0000000000000..e32fdbaabfe21 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs new file mode 100644 index 0000000000000..0a49072b68a67 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs @@ -0,0 +1,8 @@ +//@ aux-build:q.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs new file mode 100644 index 0000000000000..b050fbdf67d99 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -0,0 +1,24 @@ +//@ aux-build:t.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has index.html +//@ has q/struct.Quebec.html +//@ has s/struct.Sierra.html + +// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs new file mode 100644 index 0000000000000..1bfc785535b53 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs new file mode 100644 index 0000000000000..d3e42989b7770 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -0,0 +1,15 @@ +//@ aux-build:f.rs +//@ build-aux-docs + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has e/enum.Echo.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// document two crates in the same way that cargo does. do not provide --enable-index-page + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs new file mode 100644 index 0000000000000..e84835b3e3102 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs new file mode 100644 index 0000000000000..bb845877b52f0 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -0,0 +1,21 @@ +//@ aux-build:f.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has index.html '//h1' 'List of all crates' +//@ has e/enum.Echo.html +//@ has index.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// document two crates in the same way that cargo does, writing them both into the same output directory + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs new file mode 100644 index 0000000000000..1bfc785535b53 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs new file mode 100644 index 0000000000000..876b94464c372 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -0,0 +1,21 @@ +//@ aux-build:f.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has index.html '//h1' 'List of all crates' +//@ has e/enum.Echo.html +//@ has index.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// only declare --enable-index-page to the last rustdoc invocation + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs new file mode 100644 index 0000000000000..e32fdbaabfe21 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs new file mode 100644 index 0000000000000..c0ada1aea1a85 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs @@ -0,0 +1,8 @@ +//@ aux-build:s.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate s; +pub type Romeo = s::Sierra; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs new file mode 100644 index 0000000000000..6b414a289f5a8 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs @@ -0,0 +1,9 @@ +//@ aux-build:t.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs new file mode 100644 index 0000000000000..0a49072b68a67 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs @@ -0,0 +1,8 @@ +//@ aux-build:q.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs new file mode 100644 index 0000000000000..9df0e9779ffa7 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -0,0 +1,32 @@ +//@ aux-build:q.rs +//@ aux-build:r.rs +//@ aux-build:t.rs +//@ aux-build:s.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Sierra' +//@ has index.html +//@ has s/struct.Sierra.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i' +//@ has q/struct.Quebec.html +//@ has type.impl/s/struct.Sierra.js +//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' +//@ hasraw type.impl/s/struct.Sierra.js 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ has r/type.Romeo.html +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Romeo' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ has index.html '//h1' 'List of all crates' +//@ hasraw search-index.js 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r' + +// document everything in the default mode + + diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs new file mode 100644 index 0000000000000..a9e03852f2297 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -0,0 +1,13 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ has index.html '//h1' 'List of all crates' +//@ has index.html +//@ has q/struct.Quebec.html + +// there's nothing cross-crate going on here + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs new file mode 100644 index 0000000000000..38471e02a2820 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -0,0 +1,8 @@ +//@ build-aux-docs + +//@ hasraw search-index.js 'Quebec' +//@ has q/struct.Quebec.html + +// there's nothing cross-crate going on here + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs new file mode 100644 index 0000000000000..32ad96d3e8e36 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs new file mode 100644 index 0000000000000..e03c9a1c68c3b --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs @@ -0,0 +1,6 @@ +//@ aux-build:q.rs +//@ build-aux-docs + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs new file mode 100644 index 0000000000000..a758bd68be22f --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/s.rs @@ -0,0 +1,9 @@ +//@ aux-build:t.rs +//@ build-aux-docs + + +// simple test to see if we support building transitive crates + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs new file mode 100644 index 0000000000000..1bfc785535b53 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs new file mode 100644 index 0000000000000..431e73c390d4a --- /dev/null +++ b/tests/rustdoc/cross-crate-info/two/e.rs @@ -0,0 +1,9 @@ +//@ aux-build:f.rs +//@ build-aux-docs + + +// simple test to assert that we can do a two-level aux-build + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs new file mode 100644 index 0000000000000..89d1349e520fa --- /dev/null +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -0,0 +1,10 @@ +//@ build-aux-docs +//@ doc-flags:--scrape-examples-output-path=examples +//@ doc-flags:--scrape-examples-target-crate=q +//@ doc-flags:-Zunstable-options + +//@ has examples + +// where will --scrape-examples-output-path resolve the path to be? should be the root output directory + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs new file mode 100644 index 0000000000000..52e02e8b89715 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs @@ -0,0 +1,5 @@ +//@ build-aux-docs +//@ unique-doc-out-dir + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs new file mode 100644 index 0000000000000..0480a02bf22f7 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -0,0 +1,15 @@ +//@ aux-build:f.rs +//@ build-aux-docs + +//@ hasraw search-index.js 'Echo' +//@ !hasraw search-index.js 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ !has f/trait.Foxtrot.html +//@ has e/enum.Echo.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// test the fact that our test runner will document this crate somewhere else + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} From d8211def61d2b436d2a8335d745105e2de3ac172 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 22:16:01 +0000 Subject: [PATCH 08/25] ordering and wrapping cross-crate-info tests --- src/tools/compiletest/src/command-list.rs | 2 +- .../cargo-transitive-no-index/s.rs | 13 +++++----- .../cross-crate-info/cargo-transitive/s.rs | 21 ++++++++------- .../cross-crate-info/cargo-two-no-index/e.rs | 11 ++++---- tests/rustdoc/cross-crate-info/cargo-two/e.rs | 17 ++++++------ .../cross-crate-info/index-on-last/e.rs | 14 +++++----- .../cross-crate-info/kitchen-sink/i.rs | 26 +++++++++---------- .../single-crate-baseline/q.rs | 6 ++--- .../single-crate-no-index/q.rs | 2 +- .../working-dir-examples/q.rs | 3 ++- .../write-docs-somewhere-else/e.rs | 11 ++++---- 11 files changed, 66 insertions(+), 60 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 305bf9c228c43..68443c300fc5c 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -9,7 +9,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "aux-codegen-backend", "aux-crate", "build-aux-docs", - "unique-doc-out-dir", "build-fail", "build-pass", "check-fail", @@ -227,6 +226,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "should-ice", "stderr-per-bitwidth", "test-mir-pass", + "unique-doc-out-dir", "unset-exec-env", "unset-rustc-env", // Used by the tidy check `unknown_revision`. diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs index af0d31c733ee1..639b772374fc8 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -1,16 +1,17 @@ //@ aux-build:t.rs //@ build-aux-docs +//@ has q/struct.Quebec.html +//@ has s/struct.Sierra.html //@ has t/trait.Tango.html -//@ hasraw search-index.js 'Quebec' -//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' //@ hasraw s/struct.Sierra.html 'Tango' -//@ hasraw search-index.js 'Sierra' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' //@ hasraw search-index.js 'Tango' -//@ has q/struct.Quebec.html -//@ has s/struct.Sierra.html +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' -// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. +// We document multiple crates into the same output directory, which +// merges the cross-crate information. Everything is available. extern crate t; pub struct Sierra; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs index b050fbdf67d99..4383d089c4c73 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -3,21 +3,22 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ has t/trait.Tango.html -//@ hasraw search-index.js 'Quebec' -//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ hasraw s/struct.Sierra.html 'Tango' -//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' -//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html //@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' //@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' -//@ hasraw search-index.js 'Sierra' -//@ hasraw search-index.js 'Tango' -//@ has index.html +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' //@ has q/struct.Quebec.html //@ has s/struct.Sierra.html +//@ has t/trait.Tango.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' -// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. +// We document multiple crates into the same output directory, which +// merges the cross-crate information. Everything is available. extern crate t; pub struct Sierra; diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs index d3e42989b7770..7d64f9481fb80 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -1,14 +1,15 @@ //@ aux-build:f.rs //@ build-aux-docs -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html //@ has e/enum.Echo.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// document two crates in the same way that cargo does. do not provide --enable-index-page +// document two crates in the same way that cargo does. do not provide +// --enable-index-page extern crate f; pub enum Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs index bb845877b52f0..29e3571e6c209 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -3,18 +3,19 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' -//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html +//@ has index.html //@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' //@ has e/enum.Echo.html -//@ has index.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// document two crates in the same way that cargo does, writing them both into the same output directory +// document two crates in the same way that cargo does, writing them both +// into the same output directory extern crate f; pub enum Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs index 876b94464c372..fee9f4bcddbe4 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -3,16 +3,16 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' -//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html +//@ has index.html //@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' //@ has e/enum.Echo.html -//@ has index.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' // only declare --enable-index-page to the last rustdoc invocation diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs index 9df0e9779ffa7..558f47ab7c4c9 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -1,31 +1,31 @@ //@ aux-build:q.rs //@ aux-build:r.rs -//@ aux-build:t.rs //@ aux-build:s.rs +//@ aux-build:t.rs //@ build-aux-docs //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Quebec' -//@ hasraw search-index.js 'Sierra' +//@ has index.html '//h1' 'List of all crates' //@ has index.html -//@ has s/struct.Sierra.html -//@ hasraw s/struct.Sierra.html 'Tango' //@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i' -//@ has q/struct.Quebec.html -//@ has type.impl/s/struct.Sierra.js -//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' -//@ hasraw type.impl/s/struct.Sierra.js 'Tango' //@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r' //@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has q/struct.Quebec.html //@ has r/type.Romeo.html +//@ has s/struct.Sierra.html //@ has t/trait.Tango.html -//@ hasraw search-index.js 'Romeo' +//@ hasraw s/struct.Sierra.html 'Tango' //@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' -//@ has index.html '//h1' 'List of all crates' +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Romeo' +//@ hasraw search-index.js 'Sierra' //@ hasraw search-index.js 'Tango' -//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r' +//@ has type.impl/s/struct.Sierra.js +//@ hasraw type.impl/s/struct.Sierra.js 'Tango' +//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' // document everything in the default mode diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs index a9e03852f2297..aa5cff73e7463 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -2,11 +2,11 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Quebec' -//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ has index.html '//h1' 'List of all crates' //@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' //@ has q/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs index 38471e02a2820..0cd126e8247d9 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -1,7 +1,7 @@ //@ build-aux-docs -//@ hasraw search-index.js 'Quebec' //@ has q/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs index 89d1349e520fa..ceced1fc46dcd 100644 --- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -5,6 +5,7 @@ //@ has examples -// where will --scrape-examples-output-path resolve the path to be? should be the root output directory +// where will --scrape-examples-output-path resolve the path to be? +// should be the root output directory pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs index 0480a02bf22f7..6247ed5fd9660 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -1,14 +1,15 @@ //@ aux-build:f.rs //@ build-aux-docs -//@ hasraw search-index.js 'Echo' -//@ !hasraw search-index.js 'Foxtrot' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ !has f/trait.Foxtrot.html //@ has e/enum.Echo.html +//@ !has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ !hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// test the fact that our test runner will document this crate somewhere else +// test the fact that our test runner will document this crate somewhere +// else extern crate f; pub enum Echo {} From f6f0ef46f5a9f368183e8c59ee82d0319af7ec9c Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 22:35:14 +0000 Subject: [PATCH 09/25] reformatted rustdoc/cross-crate-info, fixing trailing newline issue --- .../cargo-transitive-no-index/auxiliary/q.rs | 2 -- .../cargo-transitive-no-index/auxiliary/t.rs | 2 -- .../rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs | 2 -- .../cross-crate-info/cargo-transitive/auxiliary/q.rs | 1 - .../cross-crate-info/cargo-transitive/auxiliary/t.rs | 1 - tests/rustdoc/cross-crate-info/cargo-transitive/s.rs | 1 - .../cross-crate-info/cargo-two-no-index/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs | 2 -- tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs | 1 - tests/rustdoc/cross-crate-info/cargo-two/e.rs | 1 - tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/index-on-last/e.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/i.rs | 6 ++---- tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs | 1 - tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/s.rs | 3 --- tests/rustdoc/cross-crate-info/two/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/two/e.rs | 3 --- tests/rustdoc/cross-crate-info/working-dir-examples/q.rs | 1 - .../write-docs-somewhere-else/auxiliary/f.rs | 2 -- .../rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs | 2 -- 27 files changed, 2 insertions(+), 46 deletions(-) diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs index 32ad96d3e8e36..5d0881029cb2f 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs index e03c9a1c68c3b..fab9ec4a92b96 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs @@ -1,6 +1,4 @@ //@ aux-build:q.rs //@ build-aux-docs - - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs index 639b772374fc8..85c460ace642f 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -1,6 +1,5 @@ //@ aux-build:t.rs //@ build-aux-docs - //@ has q/struct.Quebec.html //@ has s/struct.Sierra.html //@ has t/trait.Tango.html @@ -12,7 +11,6 @@ // We document multiple crates into the same output directory, which // merges the cross-crate information. Everything is available. - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs index e32fdbaabfe21..932a0b17206d6 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs index 0a49072b68a67..c21a59c65188f 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs index 4383d089c4c73..68bfc34883bd8 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -19,7 +19,6 @@ // We document multiple crates into the same output directory, which // merges the cross-crate information. Everything is available. - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs index 1bfc785535b53..abc580a388cd2 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs index 7d64f9481fb80..c93298f969eab 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -1,6 +1,5 @@ //@ aux-build:f.rs //@ build-aux-docs - //@ has e/enum.Echo.html //@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' @@ -10,7 +9,6 @@ // document two crates in the same way that cargo does. do not provide // --enable-index-page - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs index e84835b3e3102..a2a7033b13112 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs index 29e3571e6c209..00f86cbc34889 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -16,7 +16,6 @@ // document two crates in the same way that cargo does, writing them both // into the same output directory - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs index 1bfc785535b53..abc580a388cd2 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs index fee9f4bcddbe4..ffee898cd966d 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -15,7 +15,6 @@ //@ hasraw search-index.js 'Echo' // only declare --enable-index-page to the last rustdoc invocation - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs index e32fdbaabfe21..932a0b17206d6 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs index c0ada1aea1a85..2c0db2abc53d9 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate s; pub type Romeo = s::Sierra; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs index 6b414a289f5a8..355d3f1aaa883 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs @@ -3,7 +3,6 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs index 0a49072b68a67..c21a59c65188f 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs index 558f47ab7c4c9..bcb9464795af2 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -1,7 +1,7 @@ -//@ aux-build:q.rs //@ aux-build:r.rs -//@ aux-build:s.rs +//@ aux-build:q.rs //@ aux-build:t.rs +//@ aux-build:s.rs //@ build-aux-docs //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -28,5 +28,3 @@ //@ hasraw type.impl/s/struct.Sierra.js 'Romeo' // document everything in the default mode - - diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs index aa5cff73e7463..c5e3dc0a0f4e5 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -9,5 +9,4 @@ //@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs index 0cd126e8247d9..d3e71fa0ce35f 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -1,8 +1,6 @@ //@ build-aux-docs - //@ has q/struct.Quebec.html //@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs index 32ad96d3e8e36..5d0881029cb2f 100644 --- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs index e03c9a1c68c3b..fab9ec4a92b96 100644 --- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs @@ -1,6 +1,4 @@ //@ aux-build:q.rs //@ build-aux-docs - - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs index a758bd68be22f..0a4e5f646ddaa 100644 --- a/tests/rustdoc/cross-crate-info/transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/transitive/s.rs @@ -1,9 +1,6 @@ //@ aux-build:t.rs //@ build-aux-docs - - // simple test to see if we support building transitive crates - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs index 1bfc785535b53..abc580a388cd2 100644 --- a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs index 431e73c390d4a..9665af62706d1 100644 --- a/tests/rustdoc/cross-crate-info/two/e.rs +++ b/tests/rustdoc/cross-crate-info/two/e.rs @@ -1,9 +1,6 @@ //@ aux-build:f.rs //@ build-aux-docs - - // simple test to assert that we can do a two-level aux-build - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs index ceced1fc46dcd..a7ab062fd9e28 100644 --- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -7,5 +7,4 @@ // where will --scrape-examples-output-path resolve the path to be? // should be the root output directory - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs index 52e02e8b89715..f8c9adcaf9cad 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs @@ -1,5 +1,3 @@ //@ build-aux-docs //@ unique-doc-out-dir - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs index 6247ed5fd9660..9dcec211e1787 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -1,6 +1,5 @@ //@ aux-build:f.rs //@ build-aux-docs - //@ has e/enum.Echo.html //@ !has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' @@ -10,7 +9,6 @@ // test the fact that our test runner will document this crate somewhere // else - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} From 12d87ee237a1f79c00ccd22424432f5ab869ed22 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Thu, 25 Jul 2024 17:59:32 +0000 Subject: [PATCH 10/25] file_stem and comment per notriddle --- src/tools/compiletest/src/runtest.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2d298dfbc06f7..2beff593f08ad 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1610,6 +1610,8 @@ impl<'test> TestCx<'test> { }; // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); + // use root_testpaths here, because aux-builds should have the + // same --out-dir and auxiliary directory. let auxres = aux_cx.document(&root_out_dir, root_testpaths); if !auxres.status.success() { return auxres; @@ -1624,14 +1626,7 @@ impl<'test> TestCx<'test> { // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire // test let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir { - let file_name = self - .testpaths - .file - .file_name() - .expect("file name should not be empty") - .to_str() - .expect("file name utf8") - .trim_end_matches(".rs"); + let file_name = self.testpaths.file.file_stem().expect("file name should not be empty"); let out_dir = PathBuf::from_iter([ root_out_dir, Path::new("docs"), From f91da72cb75f03739985926c5e5561611f783b80 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Mon, 29 Jul 2024 14:41:09 +0000 Subject: [PATCH 11/25] merge conflicts; fix rebase duplicating imports --- src/tools/compiletest/src/runtest.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2beff593f08ad..55f676e708670 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,16 +1,5 @@ // ignore-tidy-filelength -use crate::compute_diff::{write_diff, write_filtered_diff}; -use crate::errors::{self, Error, ErrorKind}; -use crate::header::TestProps; -use crate::json; -use crate::read2::{read2_abbreviated, Truncated}; -use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt}; -use crate::ColorConfig; -use colored::Colorize; -use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; -use regex::{Captures, Regex}; -use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; From bd23e0eb2694752f573eafd0d894a2b16d10fd7b Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 31 Jul 2024 00:20:56 +0000 Subject: [PATCH 12/25] canonicalize path in another place to fix #128411 --- src/tools/compiletest/src/runtest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 55f676e708670..2b7601a7c73b5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2968,7 +2968,9 @@ impl<'test> TestCx<'test> { for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| { if let Some((left, right)) = s.split_once(" - ") { let path = left.rsplit("test ").next().unwrap(); - if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) { + let path = fs::canonicalize(&path).expect("failed to canonicalize"); + let path = path.to_str().unwrap().replace('\\', "/"); + if let Some(ref mut v) = files.get_mut(&path) { tested += 1; let mut iter = right.split("(line "); iter.next(); From 281c2fd5bf1604392bde16e32c7d57d2772406e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:08:55 +1000 Subject: [PATCH 13/25] Inline and remove `parse_local_mk`. It has a single use. This makes the `let` handling case in `parse_stmt_without_recovery` more similar to the statement path and statement expression cases. --- compiler/rustc_parse/src/parser/stmt.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7b0daaa14335f..28122a3ae294a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -66,7 +66,12 @@ impl<'a> Parser<'a> { } Ok(Some(if self.token.is_keyword(kw::Let) { - self.parse_local_mk(lo, attrs, capture_semi, force_collect)? + self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + this.expect_keyword(kw::Let)?; + let local = this.parse_local(attrs)?; + let trailing = capture_semi && this.token.kind == token::Semi; + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) + })? } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { self.recover_stmt_local_after_let( lo, @@ -247,21 +252,6 @@ impl<'a> Parser<'a> { Ok(stmt) } - fn parse_local_mk( - &mut self, - lo: Span, - attrs: AttrWrapper, - capture_semi: bool, - force_collect: ForceCollect, - ) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { - this.expect_keyword(kw::Let)?; - let local = this.parse_local(attrs)?; - let trailing = capture_semi && this.token.kind == token::Semi; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) - }) - } - /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; From fe647f053882f5745dfb339f22f13435bf8c4ca5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:56:25 +1000 Subject: [PATCH 14/25] Remove `LhsExpr`. `parse_expr_assoc_with` has an awkward structure -- sometimes the lhs is already parsed. This commit splits the post-lhs part into a new method `parse_expr_assoc_rest_with`, which makes everything shorter and simpler. --- compiler/rustc_parse/src/parser/expr.rs | 57 ++++++++++--------------- compiler/rustc_parse/src/parser/pat.rs | 7 +-- compiler/rustc_parse/src/parser/stmt.rs | 6 +-- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a242dc5cd582d..24e56c5bdee66 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -40,14 +40,6 @@ use super::{ }; use crate::{errors, maybe_recover_from_interpolated_ty_qpath}; -#[derive(Debug)] -pub(super) enum LhsExpr { - // Already parsed just the outer attributes. - Unparsed { attrs: AttrWrapper }, - // Already parsed the expression. - Parsed { expr: P, starts_statement: bool }, -} - #[derive(Debug)] enum DestructuredFloat { /// 1e2 @@ -113,30 +105,31 @@ impl<'a> Parser<'a> { r: Restrictions, attrs: AttrWrapper, ) -> PResult<'a, P> { - self.with_res(r, |this| this.parse_expr_assoc_with(0, LhsExpr::Unparsed { attrs })) + self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. pub(super) fn parse_expr_assoc_with( &mut self, min_prec: usize, - lhs: LhsExpr, + attrs: AttrWrapper, ) -> PResult<'a, P> { - let mut starts_stmt = false; - let mut lhs = match lhs { - LhsExpr::Parsed { expr, starts_statement } => { - starts_stmt = starts_statement; - expr - } - LhsExpr::Unparsed { attrs } => { - if self.token.is_range_separator() { - return self.parse_expr_prefix_range(attrs); - } else { - self.parse_expr_prefix(attrs)? - } - } + let lhs = if self.token.is_range_separator() { + return self.parse_expr_prefix_range(attrs); + } else { + self.parse_expr_prefix(attrs)? }; + self.parse_expr_assoc_rest_with(min_prec, false, lhs) + } + /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators + /// of at least `min_prec` precedence. + pub(super) fn parse_expr_assoc_rest_with( + &mut self, + min_prec: usize, + starts_stmt: bool, + mut lhs: P, + ) -> PResult<'a, P> { if !self.should_continue_as_assoc_expr(&lhs) { return Ok(lhs); } @@ -272,7 +265,7 @@ impl<'a> Parser<'a> { }; let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::Unparsed { attrs }) + this.parse_expr_assoc_with(prec + prec_adjustment, attrs) })?; let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); @@ -447,7 +440,7 @@ impl<'a> Parser<'a> { let maybe_lt = self.token.clone(); let attrs = self.parse_outer_attributes()?; Some( - self.parse_expr_assoc_with(prec + 1, LhsExpr::Unparsed { attrs }) + self.parse_expr_assoc_with(prec + 1, attrs) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, ) } else { @@ -504,12 +497,9 @@ impl<'a> Parser<'a> { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with( - op.unwrap().precedence() + 1, - LhsExpr::Unparsed { attrs }, - ) - .map(|x| (lo.to(x.span), Some(x))) - .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? + this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) + .map(|x| (lo.to(x.span), Some(x))) + .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { (lo, None) }; @@ -2645,10 +2635,7 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_assoc_with( - 1 + prec_let_scrutinee_needs_par(), - LhsExpr::Unparsed { attrs }, - )?; + let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b6f85cc90324c..5bfb8bdf776a0 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -25,7 +25,7 @@ use crate::errors::{ UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; -use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr}; +use crate::parser::expr::could_be_unclosed_char_literal; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; #[derive(PartialEq, Copy, Clone)] @@ -403,8 +403,9 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - let lhs = LhsExpr::Parsed { expr, starts_statement: false }; - if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) { + if let Ok(expr) = + snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) + { // We got a valid expression. self.restore_snapshot(snapshot); self.restrictions.remove(Restrictions::IS_PAT); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 28122a3ae294a..e0676b72634e7 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -17,7 +17,6 @@ use thin_vec::{thin_vec, ThinVec}; use super::attr::InnerAttrForbiddenReason; use super::diagnostics::AttemptLocalParseRecovery; -use super::expr::LhsExpr; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ @@ -178,7 +177,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens_trailing_token` closure, // since our outer attributes do not apply to this part of the expression let expr = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc_with(0, LhsExpr::Parsed { expr, starts_statement: true }) + this.parse_expr_assoc_rest_with(0, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -211,8 +210,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let e = self - .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?; + let e = self.parse_expr_assoc_rest_with(0, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) From 2eb2ef1684e4df67389432fe0c1cc2776c790cd7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 19:16:09 +1000 Subject: [PATCH 15/25] Streamline attribute stitching on AST nodes. It can be done more concisely. --- .../rustc_parse/src/parser/attr_wrapper.rs | 7 +++---- compiler/rustc_parse/src/parser/expr.rs | 18 +++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 611dbc0535c61..ba20bd9daf708 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -53,10 +53,9 @@ impl AttrWrapper { /// Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method - pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) { - let mut self_attrs = self.attrs; - mem::swap(attrs, &mut self_attrs); - attrs.extend(self_attrs); + pub(crate) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) { + mem::swap(attrs, &mut self.attrs); + attrs.extend(self.attrs); } pub fn is_empty(&self) -> bool { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 24e56c5bdee66..ae5c8af7c2d0d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -877,7 +877,7 @@ impl<'a> Parser<'a> { mut e: P, lo: Span, ) -> PResult<'a, P> { - let res = ensure_sufficient_stack(|| { + let mut res = ensure_sufficient_stack(|| { loop { let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { @@ -924,17 +924,13 @@ impl<'a> Parser<'a> { // Stitch the list of outer attributes onto the return value. A little // bit ugly, but the best way given the current code structure. - if attrs.is_empty() { - res - } else { - res.map(|expr| { - expr.map(|mut expr| { - attrs.extend(expr.attrs); - expr.attrs = attrs; - expr - }) - }) + if !attrs.is_empty() + && let Ok(expr) = &mut res + { + mem::swap(&mut expr.attrs, &mut attrs); + expr.attrs.extend(attrs) } + res } pub(super) fn parse_dot_suffix_expr( From 9d77d17f7127def53c6a3555ae9a6a1f271a8e37 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 15:41:51 +1000 Subject: [PATCH 16/25] Move a comment to a better spot. --- compiler/rustc_parse/src/parser/stmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e0676b72634e7..b3efb87a4a26a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -116,13 +116,12 @@ impl<'a> Parser<'a> { } } } else if let Some(item) = self.parse_item_common( - attrs.clone(), + attrs.clone(), // FIXME: unwanted clone of attrs false, true, FnParseMode { req_name: |_| true, req_body: true }, force_collect, )? { - // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { // Do not attempt to parse an expression if we're done here. From d1f05fd1848fc68ed89d17f7937e358dacd8aed4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 06:44:39 +1000 Subject: [PATCH 17/25] Distinguish the two kinds of token range. When collecting tokens there are two kinds of range: - a range relative to the parser's full token stream (which we get when we are parsing); - a range relative to a single AST node's token stream (which we use within `LazyAttrTokenStreamImpl` when replacing tokens). These are currently both represented with `Range` and it's easy to mix them up -- until now I hadn't properly understood the difference. This commit introduces `ParserRange` and `NodeRange` to distinguish them. This also requires splitting `ReplaceRange` in two, giving the new types `ParserReplacement` and `NodeReplacement`. (These latter two names reduce the overloading of the word "range".) The commit also rewrites some comments to be clearer. The end result is a little more verbose, but much clearer. --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 6 +- .../rustc_parse/src/parser/attr_wrapper.rs | 124 ++++++++++-------- compiler/rustc_parse/src/parser/mod.rs | 70 +++++++--- 4 files changed, 124 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index dc1874bfecbda..4b05c144d37d7 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -202,7 +202,7 @@ impl CfgEval<'_> { } // Now that we have our re-parsed `AttrTokenStream`, recursively configuring - // our attribute target will correctly the tokens as well. + // our attribute target will correctly configure the tokens as well. flat_map_annotatable(self, annotatable) } } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 12b9414d1f760..a98382efc3eba 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -8,7 +8,7 @@ use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; -use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle}; use crate::{errors, fluent_generated as fluent, maybe_whole}; // Public for rustfmt usage @@ -307,8 +307,8 @@ impl<'a> Parser<'a> { // inner attribute, for possible later processing in a `LazyAttrTokenStream`. if let Capturing::Yes = self.capture_state.capturing { let end_pos = self.num_bump_calls; - let range = start_pos..end_pos; - self.capture_state.inner_attr_ranges.insert(attr.id, range); + let parser_range = ParserRange(start_pos..end_pos); + self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range); } attrs.push(attr); } else { diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index ba20bd9daf708..abf61036c2deb 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -10,7 +10,10 @@ use rustc_errors::PResult; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, DUMMY_SP}; -use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor}; +use super::{ + Capturing, FlatToken, ForceCollect, NodeRange, NodeReplacement, Parser, ParserRange, + TokenCursor, +}; /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens @@ -28,8 +31,8 @@ use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCurso #[derive(Debug, Clone)] pub struct AttrWrapper { attrs: AttrVec, - // The start of the outer attributes in the token cursor. - // This allows us to create a `ReplaceRange` for the entire attribute + // The start of the outer attributes in the parser's token stream. + // This lets us create a `NodeReplacement` for the entire attribute // target, including outer attributes. start_pos: u32, } @@ -88,7 +91,7 @@ struct LazyAttrTokenStreamImpl { cursor_snapshot: TokenCursor, num_calls: u32, break_last_token: bool, - replace_ranges: Box<[ReplaceRange]>, + node_replacements: Box<[NodeReplacement]>, } impl ToAttrTokenStream for LazyAttrTokenStreamImpl { @@ -103,21 +106,24 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { .chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next()))) .take(self.num_calls as usize); - if self.replace_ranges.is_empty() { + if self.node_replacements.is_empty() { make_attr_token_stream(tokens, self.break_last_token) } else { let mut tokens: Vec<_> = tokens.collect(); - let mut replace_ranges = self.replace_ranges.to_vec(); - replace_ranges.sort_by_key(|(range, _)| range.start); + let mut node_replacements = self.node_replacements.to_vec(); + node_replacements.sort_by_key(|(range, _)| range.0.start); #[cfg(debug_assertions)] - for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() { + for [(node_range, tokens), (next_node_range, next_tokens)] in + node_replacements.array_windows() + { assert!( - range.end <= next_range.start || range.end >= next_range.end, - "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", - range, + node_range.0.end <= next_node_range.0.start + || node_range.0.end >= next_node_range.0.end, + "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", + node_range, tokens, - next_range, + next_node_range, next_tokens, ); } @@ -135,20 +141,23 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { // start position, we ensure that any (outer) replace range which // encloses another (inner) replace range will fully overwrite the // inner range's replacement. - for (range, target) in replace_ranges.into_iter().rev() { - assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}"); + for (node_range, target) in node_replacements.into_iter().rev() { + assert!( + !node_range.0.is_empty(), + "Cannot replace an empty node range: {:?}", + node_range.0 + ); // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the // total length of `tokens` constant throughout the replacement process, allowing - // us to use all of the `ReplaceRanges` entries without adjusting indices. + // us to do all replacements without adjusting indices. let target_len = target.is_some() as usize; tokens.splice( - (range.start as usize)..(range.end as usize), - target - .into_iter() - .map(|target| FlatToken::AttrsTarget(target)) - .chain(iter::repeat(FlatToken::Empty).take(range.len() - target_len)), + (node_range.0.start as usize)..(node_range.0.end as usize), + target.into_iter().map(|target| FlatToken::AttrsTarget(target)).chain( + iter::repeat(FlatToken::Empty).take(node_range.0.len() - target_len), + ), ); } make_attr_token_stream(tokens.into_iter(), self.break_last_token) @@ -215,7 +224,7 @@ impl<'a> Parser<'a> { let cursor_snapshot = self.token_cursor.clone(); let start_pos = self.num_bump_calls; let has_outer_attrs = !attrs.attrs.is_empty(); - let replace_ranges_start = self.capture_state.replace_ranges.len(); + let parser_replacements_start = self.capture_state.parser_replacements.len(); // We set and restore `Capturing::Yes` on either side of the call to // `f`, so we can distinguish the outermost call to @@ -270,7 +279,7 @@ impl<'a> Parser<'a> { return Ok(ret); } - let replace_ranges_end = self.capture_state.replace_ranges.len(); + let parser_replacements_end = self.capture_state.parser_replacements.len(); assert!( !(self.break_last_token && capture_trailing), @@ -287,15 +296,16 @@ impl<'a> Parser<'a> { let num_calls = end_pos - start_pos; - // Take the captured ranges for any inner attributes that we parsed in - // `Parser::parse_inner_attributes`, and pair them in a `ReplaceRange` - // with `None`, which means the relevant tokens will be removed. (More - // details below.) - let mut inner_attr_replace_ranges = Vec::new(); + // Take the captured `ParserRange`s for any inner attributes that we parsed in + // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`, + // which means the relevant tokens will be removed. (More details below.) + let mut inner_attr_parser_replacements = Vec::new(); for attr in ret.attrs() { if attr.style == ast::AttrStyle::Inner { - if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) { - inner_attr_replace_ranges.push((attr_range, None)); + if let Some(inner_attr_parser_range) = + self.capture_state.inner_attr_parser_ranges.remove(&attr.id) + { + inner_attr_parser_replacements.push((inner_attr_parser_range, None)); } else { self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute"); } @@ -304,37 +314,41 @@ impl<'a> Parser<'a> { // This is hot enough for `deep-vector` that checking the conditions for an empty iterator // is measurably faster than actually executing the iterator. - let replace_ranges: Box<[ReplaceRange]> = - if replace_ranges_start == replace_ranges_end && inner_attr_replace_ranges.is_empty() { - Box::new([]) - } else { - // Grab any replace ranges that occur *inside* the current AST node. We will - // perform the actual replacement only when we convert the `LazyAttrTokenStream` to - // an `AttrTokenStream`. - self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] - .iter() - .cloned() - .chain(inner_attr_replace_ranges.iter().cloned()) - .map(|(range, data)| ((range.start - start_pos)..(range.end - start_pos), data)) - .collect() - }; + let node_replacements: Box<[_]> = if parser_replacements_start == parser_replacements_end + && inner_attr_parser_replacements.is_empty() + { + Box::new([]) + } else { + // Grab any replace ranges that occur *inside* the current AST node. Convert them + // from `ParserRange` form to `NodeRange` form. We will perform the actual + // replacement only when we convert the `LazyAttrTokenStream` to an + // `AttrTokenStream`. + self.capture_state.parser_replacements + [parser_replacements_start..parser_replacements_end] + .iter() + .cloned() + .chain(inner_attr_parser_replacements.iter().cloned()) + .map(|(parser_range, data)| (NodeRange::new(parser_range, start_pos), data)) + .collect() + }; // What is the status here when parsing the example code at the top of this method? // // When parsing `g`: // - `start_pos..end_pos` is `12..33` (`fn g { ... }`, excluding the outer attr). - // - `inner_attr_replace_ranges` has one entry (`5..15`, when counting from `fn`), to + // - `inner_attr_parser_replacements` has one entry (`ParserRange(17..27)`), to // delete the inner attr's tokens. - // - This entry is put into the lazy tokens for `g`, i.e. deleting the inner attr from - // those tokens (if they get evaluated). + // - This entry is converted to `NodeRange(5..15)` (relative to the `fn`) and put into + // the lazy tokens for `g`, i.e. deleting the inner attr from those tokens (if they get + // evaluated). // - Those lazy tokens are also put into an `AttrsTarget` that is appended to `self`'s // replace ranges at the bottom of this function, for processing when parsing `m`. - // - `replace_ranges_start..replace_ranges_end` is empty. + // - `parser_replacements_start..parser_replacements_end` is empty. // // When parsing `m`: // - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute). - // - `inner_attr_replace_ranges` is empty. - // - `replace_range_start..replace_ranges_end` has one entry. + // - `inner_attr_parser_replacements` is empty. + // - `parser_replacements_start..parser_replacements_end` has one entry. // - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`, // including its outer attribute), with: // - `attrs`: includes the outer and the inner attr. @@ -345,7 +359,7 @@ impl<'a> Parser<'a> { num_calls, cursor_snapshot, break_last_token: self.break_last_token, - replace_ranges, + node_replacements, }); // If we support tokens and don't already have them, store the newly captured tokens. @@ -366,7 +380,7 @@ impl<'a> Parser<'a> { // What is the status here when parsing the example code at the top of this method? // // When parsing `g`, we add one entry: - // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with: + // - The pushed entry (`ParserRange(3..33)`) has a new `AttrsTarget` with: // - `attrs`: includes the outer and the inner attr. // - `tokens`: lazy tokens for `g` (with its inner attr deleted). // @@ -377,12 +391,14 @@ impl<'a> Parser<'a> { // cfg-expand this AST node. let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens }; - self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target))); + self.capture_state + .parser_replacements + .push((ParserRange(start_pos..end_pos), Some(target))); } else if matches!(self.capture_state.capturing, Capturing::No) { // Only clear the ranges once we've finished capturing entirely, i.e. we've finished // the outermost call to this method. - self.capture_state.replace_ranges.clear(); - self.capture_state.inner_attr_ranges.clear(); + self.capture_state.parser_replacements.clear(); + self.capture_state.inner_attr_parser_ranges.clear(); } Ok(ret) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 26ee5bfdee42c..722fb41cd81ec 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -192,24 +192,54 @@ struct ClosureSpans { body: Span, } -/// Indicates a range of tokens that should be replaced by -/// the tokens in the provided `AttrsTarget`. This is used in two -/// places during token collection: +/// A token range within a `Parser`'s full token stream. +#[derive(Clone, Debug)] +struct ParserRange(Range); + +/// A token range within an individual AST node's (lazy) token stream, i.e. +/// relative to that node's first token. Distinct from `ParserRange` so the two +/// kinds of range can't be mixed up. +#[derive(Clone, Debug)] +struct NodeRange(Range); + +/// Indicates a range of tokens that should be replaced by an `AttrsTarget` +/// (replacement) or be replaced by nothing (deletion). This is used in two +/// places during token collection. +/// +/// 1. Replacement. During the parsing of an AST node that may have a +/// `#[derive]` attribute, when we parse a nested AST node that has `#[cfg]` +/// or `#[cfg_attr]`, we replace the entire inner AST node with +/// `FlatToken::AttrsTarget`. This lets us perform eager cfg-expansion on an +/// `AttrTokenStream`. /// -/// 1. During the parsing of an AST node that may have a `#[derive]` -/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` -/// In this case, we use a `ReplaceRange` to replace the entire inner AST node -/// with `FlatToken::AttrsTarget`, allowing us to perform eager cfg-expansion -/// on an `AttrTokenStream`. +/// 2. Deletion. We delete inner attributes from all collected token streams, +/// and instead track them through the `attrs` field on the AST node. This +/// lets us manipulate them similarly to outer attributes. When we create a +/// `TokenStream`, the inner attributes are inserted into the proper place +/// in the token stream. /// -/// 2. When we parse an inner attribute while collecting tokens. We -/// remove inner attributes from the token stream entirely, and -/// instead track them through the `attrs` field on the AST node. -/// This allows us to easily manipulate them (for example, removing -/// the first macro inner attribute to invoke a proc-macro). -/// When create a `TokenStream`, the inner attributes get inserted -/// into the proper place in the token stream. -type ReplaceRange = (Range, Option); +/// Each replacement starts off in `ParserReplacement` form but is converted to +/// `NodeReplacement` form when it is attached to a single AST node, via +/// `LazyAttrTokenStreamImpl`. +type ParserReplacement = (ParserRange, Option); + +/// See the comment on `ParserReplacement`. +type NodeReplacement = (NodeRange, Option); + +impl NodeRange { + // Converts a range within a parser's tokens to a range within a + // node's tokens beginning at `start_pos`. + // + // For example, imagine a parser with 50 tokens in its token stream, a + // function that spans `ParserRange(20..40)` and an inner attribute within + // that function that spans `ParserRange(30..35)`. We would find the inner + // attribute's range within the function's tokens by subtracting 20, which + // is the position of the function's start token. This gives + // `NodeRange(10..15)`. + fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange { + NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos)) + } +} /// Controls how we capture tokens. Capturing can be expensive, /// so we try to avoid performing capturing in cases where @@ -226,8 +256,8 @@ enum Capturing { #[derive(Clone, Debug)] struct CaptureState { capturing: Capturing, - replace_ranges: Vec, - inner_attr_ranges: FxHashMap>, + parser_replacements: Vec, + inner_attr_parser_ranges: FxHashMap, } /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that @@ -417,8 +447,8 @@ impl<'a> Parser<'a> { subparser_name, capture_state: CaptureState { capturing: Capturing::No, - replace_ranges: Vec::new(), - inner_attr_ranges: Default::default(), + parser_replacements: Vec::new(), + inner_attr_parser_ranges: Default::default(), }, current_closure: None, recovery: Recovery::Allowed, From b73077e3d8cc6f5174e0161ea02792c616189f59 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 1 Aug 2024 18:48:48 +0200 Subject: [PATCH 18/25] separate test file for invalid sym operand --- tests/ui/asm/aarch64/type-check-2.rs | 18 ---------- tests/ui/asm/aarch64/type-check-2.stderr | 34 +++++-------------- tests/ui/asm/invalid-sym-operand.rs | 30 +++++++++++++++++ tests/ui/asm/invalid-sym-operand.stderr | 26 +++++++++++++++ tests/ui/asm/type-check-1.rs | 6 ---- tests/ui/asm/type-check-1.stderr | 20 ++++------- tests/ui/asm/x86_64/type-check-2.rs | 20 ----------- tests/ui/asm/x86_64/type-check-2.stderr | 42 +++++------------------- 8 files changed, 80 insertions(+), 116 deletions(-) create mode 100644 tests/ui/asm/invalid-sym-operand.rs create mode 100644 tests/ui/asm/invalid-sym-operand.stderr diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs index ba68cdd26d94c..46667ae3a6565 100644 --- a/tests/ui/asm/aarch64/type-check-2.rs +++ b/tests/ui/asm/aarch64/type-check-2.rs @@ -15,15 +15,6 @@ fn main() { unsafe { // Inputs must be initialized - // Sym operands must point to a function or static - - const C: i32 = 0; - static S: i32 = 0; - asm!("{}", sym S); - asm!("{}", sym main); - asm!("{}", sym C); - //~^ ERROR invalid `sym` operand - // Register operands must be Copy asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); @@ -65,12 +56,3 @@ fn main() { asm!("{}", in(reg) u); } } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index d647f6a9f0635..b7723fc74d4b6 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -1,29 +1,13 @@ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:75:19 - | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - -error: invalid `sym` operand - --> $DIR/type-check-2.rs:24:20 - | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:29:31 + --> $DIR/type-check-2.rs:20:31 | LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:41:28: 41:36}` for inline assembly - --> $DIR/type-check-2.rs:41:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:32:28: 32:36}` for inline assembly + --> $DIR/type-check-2.rs:32:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -31,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:43:28 + --> $DIR/type-check-2.rs:34:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -40,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:45:28 + --> $DIR/type-check-2.rs:36:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -48,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:47:28 + --> $DIR/type-check-2.rs:38:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -56,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:55:31 + --> $DIR/type-check-2.rs:46:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -64,12 +48,12 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:58:31 + --> $DIR/type-check-2.rs:49:31 | LL | asm!("{}", inout(reg) r); | ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs new file mode 100644 index 0000000000000..25e5fc6f9f6b7 --- /dev/null +++ b/tests/ui/asm/invalid-sym-operand.rs @@ -0,0 +1,30 @@ +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + // Sym operands must point to a function or static + + let x: u64 = 0; + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR invalid `sym` operand + asm!("{}", sym x); + //~^ ERROR invalid `sym` operand + } +} + +unsafe fn generic() { + asm!("{}", sym generic::); +} + +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr new file mode 100644 index 0000000000000..a0b97a96d8a51 --- /dev/null +++ b/tests/ui/asm/invalid-sym-operand.stderr @@ -0,0 +1,26 @@ +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:14:24 + | +LL | asm!("{}", sym x); + | ^ is a local variable + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:12:20 + | +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:29:19 + | +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: aborting due to 3 previous errors + diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index ad1a391539f1a..2d25c6186e759 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -46,8 +46,6 @@ fn main() { asm!("{}", const const_bar(0)); asm!("{}", const const_bar(x)); //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", sym x); - //~^ ERROR invalid `sym` operand // Const operands must be integers and must be constants. @@ -64,10 +62,6 @@ fn main() { } } -unsafe fn generic() { - asm!("{}", sym generic::); -} - // Const operands must be integers and must be constants. global_asm!("{}", const 0); diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index bbed571284903..c2fc8d6690dff 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -31,14 +31,6 @@ help: consider using `const` instead of `let` LL | const x: /* Type */ = 0; | ~~~~~ ++++++++++++ -error: invalid `sym` operand - --> $DIR/type-check-1.rs:49:24 - | -LL | asm!("{}", sym x); - | ^ is a local variable - | - = help: `sym` operands must refer to either a function or a static - error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -103,7 +95,7 @@ LL | asm!("{}", inout(reg) v[..]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: invalid type for `const` operand - --> $DIR/type-check-1.rs:57:20 + --> $DIR/type-check-1.rs:55:20 | LL | asm!("{}", const 0f32); | ^^^^^^---- @@ -113,7 +105,7 @@ LL | asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:59:20 + --> $DIR/type-check-1.rs:57:20 | LL | asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -123,7 +115,7 @@ LL | asm!("{}", const 0 as *mut u8); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:62:20 + --> $DIR/type-check-1.rs:60:20 | LL | asm!("{}", const &0); | ^^^^^^-- @@ -133,7 +125,7 @@ LL | asm!("{}", const &0); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:76:19 + --> $DIR/type-check-1.rs:70:19 | LL | global_asm!("{}", const 0f32); | ^^^^^^---- @@ -143,7 +135,7 @@ LL | global_asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:78:19 + --> $DIR/type-check-1.rs:72:19 | LL | global_asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -152,7 +144,7 @@ LL | global_asm!("{}", const 0 as *mut u8); | = help: `const` operands must be of an integer type -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0277, E0435. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index 4b5d59fdbc785..ff811961462df 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -27,17 +27,6 @@ fn main() { asm!("{}", out(reg) v[0]); asm!("{}", inout(reg) v[0]); - // Sym operands must point to a function or static - - const C: i32 = 0; - static S: i32 = 0; - asm!("{}", sym S); - asm!("{}", sym main); - asm!("{}", sym C); - //~^ ERROR invalid `sym` operand - asm!("{}", sym x); - //~^ ERROR invalid `sym` operand - // Register operands must be Copy asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); @@ -79,12 +68,3 @@ fn main() { asm!("{}", in(reg) u); } } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index e82a7c92664e5..c72e695aefb83 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,21 +1,13 @@ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:38:24 - | -LL | asm!("{}", sym x); - | ^ is a local variable - | - = help: `sym` operands must refer to either a function or a static - error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:43:32 + --> $DIR/type-check-2.rs:32:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:55:28: 55:36}` for inline assembly - --> $DIR/type-check-2.rs:55:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:44:28: 44:36}` for inline assembly + --> $DIR/type-check-2.rs:44:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -23,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:57:28 + --> $DIR/type-check-2.rs:46:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -32,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:59:28 + --> $DIR/type-check-2.rs:48:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -40,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:61:28 + --> $DIR/type-check-2.rs:50:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -48,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:69:31 + --> $DIR/type-check-2.rs:58:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -56,21 +48,13 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:72:31 + --> $DIR/type-check-2.rs:61:31 | LL | asm!("{}", inout(reg) r); | ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: invalid `sym` operand - --> $DIR/type-check-2.rs:36:20 - | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2.rs:15:28 | @@ -113,15 +97,7 @@ help: consider changing this to be mutable LL | let mut v: Vec = vec![0, 1, 2]; | +++ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:89:19 - | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - -error: aborting due to 13 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. From 47e6db542e4a80b6c4b3aa4ab2eb2a991474f24f Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 1 Aug 2024 18:57:59 +0200 Subject: [PATCH 19/25] separate test file for invalid const operand --- tests/ui/asm/invalid-const-operand.rs | 51 +++++++++++++ tests/ui/asm/invalid-const-operand.stderr | 86 ++++++++++++++++++++++ tests/ui/asm/invalid-sym-operand.rs | 18 ++--- tests/ui/asm/invalid-sym-operand.stderr | 14 ++-- tests/ui/asm/type-check-1.rs | 41 ----------- tests/ui/asm/type-check-1.stderr | 88 +---------------------- 6 files changed, 155 insertions(+), 143 deletions(-) create mode 100644 tests/ui/asm/invalid-const-operand.rs create mode 100644 tests/ui/asm/invalid-const-operand.stderr diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs new file mode 100644 index 0000000000000..eff335ff6aaa3 --- /dev/null +++ b/tests/ui/asm/invalid-const-operand.rs @@ -0,0 +1,51 @@ +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +// Const operands must be integers and must be constants. + +global_asm!("{}", const 0); +global_asm!("{}", const 0i32); +global_asm!("{}", const 0i128); +global_asm!("{}", const 0f32); +//~^ ERROR invalid type for `const` operand +global_asm!("{}", const 0 as *mut u8); +//~^ ERROR invalid type for `const` operand + +fn main() { + unsafe { + // Const operands must be integers and must be constants. + + asm!("{}", const 0); + asm!("{}", const 0i32); + asm!("{}", const 0i128); + asm!("{}", const 0f32); + //~^ ERROR invalid type for `const` operand + asm!("{}", const 0 as *mut u8); + //~^ ERROR invalid type for `const` operand + asm!("{}", const &0); + //~^ ERROR invalid type for `const` operand + + // Constants must be... constant + + let x = 0; + const fn const_foo(x: i32) -> i32 { + x + } + const fn const_bar(x: T) -> T { + x + } + asm!("{}", const x); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_foo(0)); + asm!("{}", const const_foo(x)); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_bar(0)); + asm!("{}", const const_bar(x)); + //~^ ERROR attempt to use a non-constant value in a constant + } +} diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr new file mode 100644 index 0000000000000..a6d742b53c217 --- /dev/null +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -0,0 +1,86 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:42:26 + | +LL | asm!("{}", const x); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:45:36 + | +LL | asm!("{}", const const_foo(x)); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:48:36 + | +LL | asm!("{}", const const_bar(x)); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:14:19 + | +LL | global_asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:16:19 + | +LL | global_asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:26:20 + | +LL | asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:28:20 + | +LL | asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:30:20 + | +LL | asm!("{}", const &0); + | ^^^^^^-- + | | + | is a `&i32` + | + = help: `const` operands must be of an integer type + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs index 25e5fc6f9f6b7..69c4695125c43 100644 --- a/tests/ui/asm/invalid-sym-operand.rs +++ b/tests/ui/asm/invalid-sym-operand.rs @@ -1,5 +1,14 @@ use std::arch::{asm, global_asm}; +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand + fn main() { unsafe { // Sym operands must point to a function or static @@ -19,12 +28,3 @@ fn main() { unsafe fn generic() { asm!("{}", sym generic::); } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr index a0b97a96d8a51..8e0676200bb2e 100644 --- a/tests/ui/asm/invalid-sym-operand.stderr +++ b/tests/ui/asm/invalid-sym-operand.stderr @@ -1,5 +1,5 @@ error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:14:24 + --> $DIR/invalid-sym-operand.rs:23:24 | LL | asm!("{}", sym x); | ^ is a local variable @@ -7,18 +7,18 @@ LL | asm!("{}", sym x); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:12:20 + --> $DIR/invalid-sym-operand.rs:9:19 | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` | = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:29:19 + --> $DIR/invalid-sym-operand.rs:21:20 | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` | = help: `sym` operands must refer to either a function or a static diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index 2d25c6186e759..22669dce280bb 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -28,46 +28,5 @@ fn main() { asm!("{}", inout(reg) v[..]); //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time //~| ERROR cannot use value of type `[u64]` for inline assembly - - // Constants must be... constant - - let x = 0; - const fn const_foo(x: i32) -> i32 { - x - } - const fn const_bar(x: T) -> T { - x - } - asm!("{}", const x); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", const const_foo(0)); - asm!("{}", const const_foo(x)); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", const const_bar(0)); - asm!("{}", const const_bar(x)); - //~^ ERROR attempt to use a non-constant value in a constant - - // Const operands must be integers and must be constants. - - asm!("{}", const 0); - asm!("{}", const 0i32); - asm!("{}", const 0i128); - asm!("{}", const 0f32); - //~^ ERROR invalid type for `const` operand - asm!("{}", const 0 as *mut u8); - //~^ ERROR invalid type for `const` operand - - asm!("{}", const &0); - //~^ ERROR invalid type for `const` operand } } - -// Const operands must be integers and must be constants. - -global_asm!("{}", const 0); -global_asm!("{}", const 0i32); -global_asm!("{}", const 0i128); -global_asm!("{}", const 0f32); -//~^ ERROR invalid type for `const` operand -global_asm!("{}", const 0 as *mut u8); -//~^ ERROR invalid type for `const` operand diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index c2fc8d6690dff..d47e6ae1d2a97 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -1,36 +1,3 @@ -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:41:26 - | -LL | asm!("{}", const x); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:44:36 - | -LL | asm!("{}", const const_foo(x)); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:47:36 - | -LL | asm!("{}", const const_bar(x)); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -94,57 +61,6 @@ LL | asm!("{}", inout(reg) v[..]); | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:55:20 - | -LL | asm!("{}", const 0f32); - | ^^^^^^---- - | | - | is an `f32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:57:20 - | -LL | asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:60:20 - | -LL | asm!("{}", const &0); - | ^^^^^^-- - | | - | is a `&i32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:70:19 - | -LL | global_asm!("{}", const 0f32); - | ^^^^^^---- - | | - | is an `f32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:72:19 - | -LL | global_asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type - -error: aborting due to 16 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0277, E0435. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. From 6ba240ab05ac4e3f0f3ed5f3be66e02df794056e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 26 Feb 2024 13:13:43 +0000 Subject: [PATCH 20/25] Promote riscv64gc-unknown-linux-musl to tier 2 --- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 11 +++++++++-- src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 2621e9a603185..52528e7987a10 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -24,7 +24,8 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no # Needed for apt-key to work: dirmngr \ gpg-agent \ - g++-9-arm-linux-gnueabi + g++-9-arm-linux-gnueabi \ + g++-riscv64-linux-gnu RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main' @@ -73,6 +74,10 @@ RUN env \ CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \ CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \ bash musl.sh armv7 && \ + env \ + CC=riscv64-linux-gnu-gcc \ + CXX=riscv64-linux-gnu-g++ \ + bash musl.sh riscv64gc && \ rm -rf /build/* WORKDIR /tmp @@ -125,6 +130,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-none ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi +ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the @@ -133,6 +139,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \ - --musl-root-armv7=/musl-armv7 + --musl-root-armv7=/musl-armv7 \ + --musl-root-riscv64gc=/musl-riscv64gc ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ff475b9571b87..2b263f848e89e 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -141,6 +141,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-hermit", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", + "riscv64gc-unknown-linux-musl", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", From b056ab67f1e6035384dc300cc2d96463e78dd67b Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 22 Jun 2024 16:42:05 +0200 Subject: [PATCH 21/25] Make riscv64gc-unknown-linux-musl dynamically linked by default --- .../src/spec/targets/riscv64gc_unknown_linux_musl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 3e575fdd528de..8b40132986867 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -21,6 +21,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + crt_static_default: false, ..base::linux_musl::opts() }, } From beacd70600c77d460a594dc7dcdae7d30a2cb366 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 22 Jun 2024 17:04:00 +0200 Subject: [PATCH 22/25] Add platform support document for riscv64gc-unknown-linux-musl --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../riscv64gc-unknown-linux-musl.md | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d5141591b97e4..467fd6f43e48f 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -66,6 +66,7 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) + - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f3b49a65aad28..7fd1808a1f026 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -98,6 +98,7 @@ target | notes `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29) +[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3) `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17) `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos @@ -354,7 +355,6 @@ target | std | host | notes [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia -`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.3) [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md new file mode 100644 index 0000000000000..5b3dc68303803 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md @@ -0,0 +1,47 @@ +# riscv64gc-unknown-linux-musl + +**Tier: 2** + +Target for RISC-V Linux programs using musl libc. + +## Target maintainers + +- [@Amanieu](https://github.com/Amanieu) +- [@kraj](https://github.com/kraj) + +## Requirements + +Building the target itself requires a RISC-V compiler that is supported by `cc-rs`. + +## Building the target + +The target can be built by enabling it for a `rustc` build. + +```toml +[build] +target = ["riscv64gc-unknown-linux-musl"] +``` + +Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: + +```toml +[target.riscv64gc-unknown-linux-musl] +cc = "riscv64-linux-gnu-gcc" +cxx = "riscv64-linux-gnu-g++" +ar = "riscv64-linux-gnu-ar" +linker = "riscv64-linux-gnu-gcc" +``` + +## Building Rust programs + +This target are distributed through `rustup`, and otherwise require no +special configuration. + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target can be tested as normal with `x.py` on a RISC-V host or via QEMU +emulation. From 41b017ec9945ce6b514e44b8dd26c9d0c0952c9c Mon Sep 17 00:00:00 2001 From: sayantn Date: Thu, 1 Aug 2024 23:13:51 +0530 Subject: [PATCH 23/25] Add the `sha512`, `sm3` and `sm4` target features Add the feature in `core/lib.rs` --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 3 +++ library/core/src/arch.rs | 9 +++++++++ library/core/src/lib.rs | 1 + tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- .../ui/feature-gates/feature-gate-sha512_sm_x86.rs | 6 ++++++ .../feature-gates/feature-gate-sha512_sm_x86.stderr | 13 +++++++++++++ 10 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 77da4e4caea0f..b52e6259944d7 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -78,6 +78,7 @@ pub fn from_target_feature( Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature, Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature, + Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86, Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, Some(sym::xop_target_feature) => rust_features.xop_target_feature, Some(sym::s390x_target_feature) => rust_features.s390x_target_feature, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 03210085a12c9..86102bbecd04e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -591,6 +591,8 @@ declare_features! ( (incomplete, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), + /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics + (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)), /// Shortern the tail expression lifetime (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8563f50158a5..9977fa7425a3e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1705,6 +1705,7 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + sha512_sm_x86, shadow_call_stack, shl, shl_assign, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 532507cb18244..e52f2fc06df06 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -238,6 +238,9 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("rdseed", Stable), ("rtm", Unstable(sym::rtm_target_feature)), ("sha", Stable), + ("sha512", Unstable(sym::sha512_sm_x86)), + ("sm3", Unstable(sym::sha512_sm_x86)), + ("sm4", Unstable(sym::sha512_sm_x86)), ("sse", Stable), ("sse2", Stable), ("sse3", Stable), diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 31d6bc36fc8b9..d681bd124fe13 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -4,6 +4,15 @@ #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; +#[cfg(bootstrap)] +#[allow(dead_code)] +#[unstable(feature = "sha512_sm_x86", issue = "126624")] +fn dummy() { + // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs + // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a + // library feature until bootstrap gets bumped +} + /// Inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0917631e04500..9306581dca93d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -260,6 +260,7 @@ #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] +#![feature(sha512_sm_x86)] #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 57cbe173c7896..520cffc4b0268 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 199 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 00abb5f5e5ca0..d780e04e729a2 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs new file mode 100644 index 0000000000000..176a40ecf5370 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "sha512")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr new file mode 100644 index 0000000000000..da9eea095a332 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `sha512` is currently unstable + --> $DIR/feature-gate-sha512_sm_x86.rs:2:18 + | +LL | #[target_feature(enable = "sha512")] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #126624 for more information + = help: add `#![feature(sha512_sm_x86)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 2f0aaaf2b9fc401708946e60e0f7dabf3c1bf30e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 1 Aug 2024 20:43:02 -0700 Subject: [PATCH 24/25] std: Remove has_cpuid The one use of it was guaranteed to be always true. --- library/std/src/lib.rs | 4 ---- library/std/src/sys/pal/uefi/time.rs | 8 -------- 2 files changed, 12 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6bd9c59a949c2..a760fee42c830 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -269,10 +269,6 @@ #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] -#![cfg_attr( - all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"), - feature(stdarch_x86_has_cpuid) -)] // // Language features: // tidy-alphabetical-start diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index a97d69f997bf9..495ff2dc930ed 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -175,10 +175,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86_64")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86_64::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); // Get Frequency in Mhz @@ -200,10 +196,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); let freq = FREQUENCY From 36527d691e381403c75bc5e30ad1bfd97de2cf12 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 2 Aug 2024 02:12:29 -0700 Subject: [PATCH 25/25] rustfmt: Remove `has_cpuid` from test --- src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs | 9 --------- src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs | 9 --------- 2 files changed, 18 deletions(-) diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs index 9257b8a4be636..b9adc67221aea 100644 --- a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs index 2e228aa374527..944b51615f8e5 100644 --- a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0,