diff --git a/.mailmap b/.mailmap index 66fe19ac49312..32fbff098127d 100644 --- a/.mailmap +++ b/.mailmap @@ -350,6 +350,7 @@ John Van Enk Jon Gjengset Jonas Tepe Jonathan Bailey +Jonathan Brouwer Jonathan Chan Kwan Yin Jonathan L Jonathan S Jonathan S diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index e77d63d91703b..1bd5094c38f02 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1165,7 +1165,9 @@ extern "C" LLVMRustResult LLVMRustPrintModule(LLVMModuleRef M, const char *Path, LLVMRustSetLastError(ErrorInfo.c_str()); return LLVMRustResult::Failure; } - +#if LLVM_VERSION_GE(24, 0) + unwrap(M)->renumberMetadataForAssembly(); +#endif auto AAW = RustAssemblyAnnotationWriter(Demangle); auto FOS = formatted_raw_ostream(OS); unwrap(M)->print(FOS, &AAW); diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs index 553b7af91e30c..591e4b096b416 100644 --- a/compiler/rustc_mir_build/src/builder/block.rs +++ b/compiler/rustc_mir_build/src/builder/block.rs @@ -207,12 +207,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let else_block_span = this.thir[*else_block].span; let (true_block, false_block) = this.in_if_then_scope(last_remainder_scope, else_block_span, |this| { - // Bypass `lower_if_condition` and call `lower_let_expr` directly, + // Bypass `lower_if_condition` and call `lower_fallible_let` directly, // since we don't have an actual THIR let-expression here. - this.lower_let_expr( + this.lower_fallible_let( block, - *initializer, pattern, + *initializer, None, initializer_span, DeclareLetBindings::No, diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 01505fb9ec8ae..687b03a2741dc 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -50,7 +50,7 @@ pub(crate) struct LowerIfCondArgs { pub(crate) variable_source_info: SourceInfo, /// Determines how bindings should be handled when lowering `let` expressions. /// - /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. + /// Forwarded to [`Builder::lower_fallible_let`] when lowering [`ExprKind::Let`]. pub(crate) declare_let_bindings: DeclareLetBindings, } @@ -62,9 +62,9 @@ impl LowerIfCondArgs { } } -/// Should lowering a `let` expression also declare its bindings? +/// Should lowering a `let` also declare its bindings? /// -/// Used by [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. +/// Used by [`Builder::lower_fallible_let`]. #[derive(Clone, Copy)] pub(crate) enum DeclareLetBindings { /// Yes, declare `let` bindings as normal for `if` conditions. @@ -169,10 +169,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) } ExprKind::ValueExpr { source } => this.lower_if_condition(block, source, args), - ExprKind::Let { expr, ref pat } => this.lower_let_expr( + ExprKind::Let { ref pat, expr } => this.lower_fallible_let( block, - expr, pat, + expr, Some(args.variable_source_info.scope), args.variable_source_info.span, args.declare_let_bindings, @@ -2309,65 +2309,72 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Pat binding - used for `let` and function parameters as well. impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Lowers a `let` expression that appears in a suitable context - /// (e.g. an `if` condition or match guard). - /// - /// Also used for lowering let-else statements, since they have similar - /// needs despite not actually using `let` expressions. + /// Lowers a fallible `let`, which is one of: + /// - A let-expression inside an `if` condition or match guard. + /// - A let-else statement. /// - /// Use [`DeclareLetBindings`] to control whether the `let` bindings are - /// declared or not. + /// (Strictly speaking, the underlying pattern might actually be infallible. + /// What matters here is that it is _allowed_ to be fallible.) /// /// Must be called within a [`Builder::in_if_then_scope`], to indicate where /// to break to if the `let` fails to match. - pub(crate) fn lower_let_expr( + pub(crate) fn lower_fallible_let( &mut self, mut block: BasicBlock, - expr_id: ExprId, pat: &Pat<'tcx>, + scrutinee_id: ExprId, source_scope: Option, scope_span: Span, + // Controls whether bindings are declared or not, as requested by the caller. declare_let_bindings: DeclareLetBindings, ) -> BlockAnd<()> { - let expr_span = self.thir[expr_id].span; - let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id)); + let scrutinee_span = self.thir[scrutinee_id].span; + let scrutinee_place_builder = unpack!(block = self.lower_scrutinee(block, scrutinee_id)); + + // Lower the scrutinee and pattern as though they were desugared to a `match`. let built_tree = self.lower_match_tree( block, - expr_span, - &scrutinee, + scrutinee_span, + &scrutinee_place_builder, pat.span, vec![(pat, HasMatchGuard::No)], Exhaustive::No, ); - let [branch] = built_tree.branches.try_into().unwrap(); + let [true_branch] = built_tree.branches.try_into().unwrap(); + let false_block = built_tree.otherwise_block; // If pattern-matching failed, break out of the enclosing if-then scope. - self.break_from_if_then_scope(built_tree.otherwise_block, self.source_info(expr_span)); + self.break_from_if_then_scope(false_block, self.source_info(scrutinee_span)); match declare_let_bindings { DeclareLetBindings::Yes => { - let expr_place = scrutinee.try_to_place(self); - let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); + let scrutinee_place; + let opt_match_place = try { + scrutinee_place = scrutinee_place_builder.try_to_place(self)?; + (Some(&scrutinee_place), scrutinee_span) + }; self.declare_bindings( source_scope, pat.span.to(scope_span), pat, None, - opt_expr_place, + opt_match_place, ); } DeclareLetBindings::No => {} // Caller is responsible for bindings. - DeclareLetBindings::LetNotPermitted => { - self.tcx.dcx().span_bug(expr_span, "let expression not expected in this context") - } + DeclareLetBindings::LetNotPermitted => self + .tcx + .dcx() + .span_bug(scrutinee_span, "let expression not expected in this context"), } - let success = self.bind_pattern(self.source_info(pat.span), branch, &[], expr_span, None); + let true_block = + self.bind_pattern(self.source_info(pat.span), true_branch, &[], scrutinee_span, None); // If branch coverage is enabled, record this branch. - self.visit_coverage_conditional_let(pat, success, built_tree.otherwise_block); + self.visit_coverage_conditional_let(pat, true_block, false_block); - success.unit() + true_block.unit() } /// Initializes each of the bindings from the candidate by diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d6a8b2c2f5eb6..637052eb87530 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -601,15 +601,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { { if defer_seeds_come_from_allow { return ImplItemCheckResult::Dead { require: adt_def_id }; - } else { - let comes_from_allow = trait_comes_from_allow - .or_else(|| has_allow_dead_code_or_lang_attr(self.tcx, adt_def_id)); - - return match comes_from_allow { - Some(comes_from_allow) => ImplItemCheckResult::Live(comes_from_allow), - None => ImplItemCheckResult::Dead { require: adt_def_id }, - }; } + + return match trait_comes_from_allow { + Some(comes_from_allow) => ImplItemCheckResult::Live(comes_from_allow), + None => ImplItemCheckResult::Dead { require: adt_def_id }, + }; } ImplItemCheckResult::Live(ComesFromAllowExpect::No) diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index e1d2b53366066..8a437c4995724 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -48,11 +48,15 @@ decl_derive!( /// struct Foo { /// #[generic_type_visitable(bounds())] /// just_self: Box, - /// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable))] + /// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable<__V>))] /// contains_self: (Box, Bar), /// } /// struct Bar; /// ``` + /// + /// Note: the `__V` lifetime is an implementation detail of the derive macro. + /// We could probably handle this in a nicer way, but we don't expect this form + /// to really be necessary any time soon, so for now we don't. customizable_type_visitable_derive ); @@ -461,7 +465,7 @@ mod kw { /// Parses a bound like: /// /// ```ignore (would need to import GenericTypeVisitable to get this to compile) -/// #[generic_type_visitable(bounds(Foo: GenericTypeVisitable, Bar: GenericTypeVisitable))] +/// #[generic_type_visitable(bounds(Foo: GenericTypeVisitable<__V>, Bar: GenericTypeVisitable<__V>))] /// ``` fn parse_generic_type_visitable_bound( attr: &Attribute, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index b039fd587df47..5bd43806b1a09 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -949,6 +949,7 @@ impl VecDeque { /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are /// initialized rather than only supporting `0..len`. Requires that /// `initialized.start` ≤ `initialized.end` ≤ `capacity`. + /// Also, `initialized.start` < `capacity`, unless both are 0. #[inline] #[cfg(not(test))] pub(crate) unsafe fn from_contiguous_raw_parts_in( @@ -959,9 +960,13 @@ impl VecDeque { ) -> Self { debug_assert!(initialized.start <= initialized.end); debug_assert!(initialized.end <= capacity); + debug_assert!(initialized.start == 0 && capacity == 0 || initialized.start < capacity); // SAFETY: Our safety precondition guarantees the range length won't wrap, - // and that the allocation is valid for use in `RawVec`. + // that the allocation is valid for use in `RawVec` with `alloc`, + // and that the range contains valid elements. + // We have `head`, `len` ≤ `cap`, since `start`, `end` ≤ `cap`. + // Also, `head` < `cap` unless `head` = `cap` = `0`. unsafe { VecDeque { head: WrappedIndex::from_arbitrary_number(initialized.start), diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 46874ff76c093..d99d2126810ba 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -213,25 +213,39 @@ impl IntoIter { // Keep our `Drop` impl from dropping the elements and the allocator let mut this = ManuallyDrop::new(self); - // SAFETY: This allocation originally came from a `Vec`, so it passes - // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, - // so the `offset_from_unsigned`s below cannot wrap, and will produce a well-formed - // range. `end` ≤ `buf + cap`, so the range will be in-bounds. - // Taking `alloc` is ok because nothing else is going to look at it, - // since our `Drop` impl isn't going to run so there's no more code. - unsafe { - let buf = this.buf.as_ptr(); - let initialized = if T::IS_ZST { - // All the pointers are the same for ZSTs, so it's fine to - // say that they're all at the beginning of the "allocation". - 0..this.len() - } else { - this.ptr.offset_from_unsigned(this.buf)..this.end.offset_from_unsigned(buf) - }; - let cap = this.cap; - let alloc = ManuallyDrop::take(&mut this.alloc); - VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc) - } + let buf = this.buf.as_ptr(); + let initialized = if T::IS_ZST || this.len() == 0 { + // All the pointers are the same for ZSTs, so it's fine to + // say that they're all at the beginning of the "allocation". + // For non-ZSTs, we have length 0, so we can choose the (empty) + // range to be at the start of the buffer. + // + // Due to `0` ≤ `this.len()` ≤ `this.cap`, the range is well-formed, + // and due to the argument above it spans exactly the elements of + // this iterator. Because `init.start` = `0`, it follows that either + // `init.start` < `cap` or `cap` = `init.start` = `0`; thus the range + // satisfies the requirements of `from_contiguous_raw_parts_in`. + 0..this.len() + } else { + // SAFETY: `this.ptr` and `this.end` are created via offsets of `this.buf`, + // so they point to the same allocation. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, + // so this cannot wrap, and will produce a well-formed range that spans exactly + // the elements of this iterator. + // + // Additionally, due to `end ≤ buf + cap`, we have `init.start` ≤ `init.end` ≤ `cap`. + // Due to the length check above, `init.start < cap`, so the range satisfies the + // requirements of `from_contiguous_raw_parts_in`. + unsafe { this.ptr.offset_from_unsigned(this.buf)..this.end.offset_from_unsigned(buf) } + }; + + let cap = this.cap; + // SAFETY: `this` is forgotten afterwards, so we can move out the allocator. + let alloc = unsafe { ManuallyDrop::take(&mut this.alloc) }; + + // SAFETY: This allocation originally came from a `Vec`, so it satisfies all + // requirements for the `buf` pointer with capacity `cap` allocated in `alloc`. + // Correctness of `initialized` was shown above. + unsafe { VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc) } } } diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs index 15cc156d6988f..00b2c2e34d569 100644 --- a/library/alloctests/tests/vec_deque.rs +++ b/library/alloctests/tests/vec_deque.rs @@ -2495,3 +2495,18 @@ fn truncate_to_range_inclusive_end_overflow() { let mut v: VecDeque<_> = (0..6).collect(); v.truncate_to_range(0..=usize::MAX); } + +#[test] +fn issue_162452_vec_deque_from_empty_vec_into_iter() { + for n in 1..20 { + let v = Vec::from_iter(0..n); + + let mut it = v.into_iter(); + for _ in &mut it {} + + let mut d: VecDeque<_> = it.collect(); + + d.push_back(n); + assert_eq!(Some(n), d.pop_front()); + } +} diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f9e2dc6b7f849..c123c66ee3bc0 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -345,7 +345,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of weeks. /// - /// For this method, one week is defined as 7 days, or 604,800 seconds. + /// For this function, one week is defined as 7 days, or 604,800 seconds. /// /// # Panics /// @@ -375,7 +375,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of days. /// - /// For this method, one day is defined as 24 hours, or 86,400 seconds. + /// For this function, one day is defined as 24 hours, or 86,400 seconds. /// /// # Panics /// @@ -405,7 +405,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of hours. /// - /// For this method, one hour is defined as 60 minutes, or 3,600 seconds. + /// For this function, one hour is defined as 60 minutes, or 3,600 seconds. /// /// # Panics /// @@ -435,7 +435,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of minutes. /// - /// For this method, one minute is defined as 60 seconds. + /// For this function, one minute is defined as 60 seconds. /// /// # Panics /// diff --git a/src/doc/book b/src/doc/book index 917544888a55e..1500248d8f230 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 917544888a55e4da7109bdba8c88c893c0da70f4 +Subproject commit 1500248d8f230566e4ec9f27fcbb8fe9e2898ab1 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index f5abcf137698e..ab8544aeed7b7 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit f5abcf137698e5ad6ebed359d69654ff705346af +Subproject commit ab8544aeed7b792984366aa122ac19bd47ad9a2f diff --git a/src/doc/reference b/src/doc/reference index 3b38834b39f73..e24eecf97b0c9 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3b38834b39f732c64686f7c64aa29dcf3cd83ba5 +Subproject commit e24eecf97b0c9a6dbac67191098204dc8a190aaa diff --git a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md index 110fd1331bc44..2b06f5b414c1b 100644 --- a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md +++ b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md @@ -115,7 +115,7 @@ For rust-analyzer, the corresponding implementations are located across several These two traits correspond to the role of [`InferCtxt`][rustc inferctxt] in rustc. [`InferCtxtLike`][ir inferctxtlike] must be defined in `rustc_infer` due to coherence -constraints(orphan rules). +constraints (orphan rules). As a result, it cannot provide functionality that lives in `rustc_trait_selection`. Instead, behavior that depends on trait-solving logic is abstracted into a separate trait, [`SolverDelegate`][ir solverdelegate]. @@ -214,9 +214,9 @@ non-obvious considerations: 1. The generic parameters `I` and `J` are reserved for `I: Interner` and `J` being the interner it is being lifted to. -2. `PhantomData` is handled automatically, creating a new `PhantomData` but - _has_ to be included in the file through; `use std::marker::PhantomData;` - you cannot use `std::marker::PhantomData` directly on the field of a struct. +2. `PhantomData` is handled automatically, creating a new `PhantomData`. But it + _has_ to be used in the fully unqualified form -- you cannot use + `std::marker::PhantomData` directly in the field. 3. The bounds are deliberately written as associated type bounds on the `Interner` trait rather than as `where` clauses on `LiftInto`. Given only `I: LiftInto`, Rust can then treat bounds such as the following as implied: @@ -255,12 +255,6 @@ There is intentionally no ignore attribute. The traversal must visit every field. This is a soundness requirement for rust-analyzer's use of the traversal when tracing and garbage-collecting interned types. -When the macro crate's `nightly` feature is enabled, the derive macro remains -registered but emits no tokens. The `GenericTypeVisitable` trait and its -traversal module are also excluded from the nightly configuration of -`rustc_type_ir`; they exist only in its non-nightly configuration. - - ## Long-term plans for supporting rust-analyzer In general, we aim to support rust-analyzer just as well as rustc in these shared crates—provided @@ -310,4 +304,4 @@ There are still duplicated implementations between rustc and rust-analyzer—suc [r-a coerce]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/infer/coerce.rs [rustc_lift]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/lift.rs#L18 [rustc_typevisitable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/visit.rs#L62 -[rustc_typefoldable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/fold.rs#L71 \ No newline at end of file +[rustc_typefoldable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/fold.rs#L71 diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md index 0151c0482d109..3d66ec272698d 100644 --- a/src/doc/rustc-dev-guide/src/solve/the-solver.md +++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md @@ -7,7 +7,7 @@ as it is very similar to this implementation and also talks about limitations of ## A rough walkthrough -The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. +The entry-point of the solver is `SolverDelegateEvalExt::evaluate_root_goal`. This function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`, to actually enter the trait solver. diff --git a/src/doc/rustc/src/platform-support/windows-gnu.md b/src/doc/rustc/src/platform-support/windows-gnu.md index d7aec5af21dec..595c2a42c81a4 100644 --- a/src/doc/rustc/src/platform-support/windows-gnu.md +++ b/src/doc/rustc/src/platform-support/windows-gnu.md @@ -34,6 +34,7 @@ The targets are built and tested using a reasonably modern C toolchain, and it s * GCC 14.2 * mingw-w64 12.0.0 * MSVCRT library as the default +* Libgcc with DWARF-2 exception handling for i686 and SEH for x86_64 Using older tools (especially Binutils) may not work properly, due to the number of issues plaguing older versions of Binutils. The supported toolchain versions are subject to change. diff --git a/tests/codegen-llvm/inline-debuginfo.rs b/tests/codegen-llvm/inline-debuginfo.rs index 1e1c9037f5c93..95fba918286a1 100644 --- a/tests/codegen-llvm/inline-debuginfo.rs +++ b/tests/codegen-llvm/inline-debuginfo.rs @@ -10,7 +10,7 @@ pub extern "C" fn callee(x: u32) -> u32 { // CHECK-LABEL: caller // CHECK: dbg{{.}}value({{(metadata )?}}i32 %y, {{(metadata )?}}!{{.*}}, {{(metadata )?}}!DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value){{.*}} [[A:![0-9]+]] -// CHECK: [[A]] = !DILocation(line: {{.*}}, scope: {{.*}}, inlinedAt: {{.*}}) +// CHECK: [[A]] = {{(distinct )?}}!DILocation(line: {{.*}}, scope: {{.*}}, inlinedAt: {{.*}}) #[no_mangle] pub extern "C" fn caller(y: u32) -> u32 { callee(y - 3) diff --git a/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs new file mode 100644 index 0000000000000..af44ff7e92252 --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs @@ -0,0 +1,19 @@ +//@ edition: 2024 +//@ check-fail + +#![crate_type = "rlib"] +#![feature(rustc_private)] + +extern crate rustc_type_ir; +extern crate rustc_type_ir_macros; + +use rustc_type_ir_macros::GenericTypeVisitable; + +#[derive(GenericTypeVisitable)] +struct MissingBound { + // This should fail, as `T: GenericTypeVisitable<__V>` wasn't specified + #[generic_type_visitable(bounds())] + //~^ ERROR: the trait bound `T: GenericTypeVisitable<__V>` is not satisfied + partially_rec: (Vec, T), + other: u32, +} diff --git a/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr new file mode 100644 index 0000000000000..44433984e4a7f --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `T: GenericTypeVisitable<__V>` is not satisfied + --> $DIR/derive-generic-type-visitable-missing-bound.rs:15:5 + | +LL | #[derive(GenericTypeVisitable)] + | -------------------- + | | + | required by a bound introduced by this call + | in this derive macro expansion +... +LL | #[generic_type_visitable(bounds())] + | ^ the nightly-only, unstable trait `GenericTypeVisitable<__V>` is not implemented for `T` + | + = note: required for `(Vec>, T)` to implement `GenericTypeVisitable<__V>` + = note: this error originates in the derive macro `GenericTypeVisitable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/derive-generic-type-visitable.rs b/tests/ui-fulldeps/derive-generic-type-visitable.rs new file mode 100644 index 0000000000000..91c7a502a87d8 --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable.rs @@ -0,0 +1,119 @@ +//@ edition: 2024 +//@ run-pass + +#![feature(rustc_private)] + +extern crate rustc_type_ir; +extern crate rustc_type_ir_macros; + +use rustc_type_ir::GenericTypeVisitable; +use rustc_type_ir_macros::GenericTypeVisitable; + +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[expect(unused_extern_crates)] +extern crate rustc_driver; + +#[derive(GenericTypeVisitable)] +struct DerivesGenericTypeVisitable; + +#[derive(GenericTypeVisitable)] +struct Foo { + one: Incrementer, + two: Vec, +} + +#[derive(GenericTypeVisitable)] +enum Enum { + A, + B(Incrementer), + C { one: Incrementer, two: Vec }, +} + +#[derive(GenericTypeVisitable)] +struct Generic(Vec); + +#[derive(GenericTypeVisitable)] +struct Recursive { + #[generic_type_visitable(bounds())] + rec: Vec, + other: Incrementer, +} + +#[derive(GenericTypeVisitable)] +struct PartiallyRecursiveField { + #[generic_type_visitable(bounds(T: GenericTypeVisitable<__V>))] + partially_rec: (Vec, T), + other: Incrementer, +} + +// start testing setup + +use std::sync::atomic::{AtomicU8, Ordering}; + +static COUNT: AtomicU8 = AtomicU8::new(0); + +/// A type that, when visited, increments a global counter. +/// +/// Used to (weakly) test the correctness of the derive by making sure that +/// it traverses all the fields, and thus reaches all the incrementers. +#[derive(Clone)] +struct Incrementer; + +unsafe impl GenericTypeVisitable for Incrementer { + fn generic_visit_with(&self, _visitor: &mut V) { + COUNT.fetch_add(1, Ordering::Relaxed); + } +} + +// end testing setup + +fn main() { + use Incrementer as Inc; // for brevity + + #[track_caller] + fn check>(item: T, count: u8) { + let mut v = (); + item.generic_visit_with(&mut v); + assert_eq!(COUNT.swap(0, Ordering::Relaxed), count); + } + + check(DerivesGenericTypeVisitable, 0); + check(Foo { one: Inc, two: vec![] }, 1); + check(Foo { one: Inc, two: vec![Inc; 2] }, 1 + 2); + check(Enum::A, 0); + check(Enum::B(Inc), 1); + check(Enum::C { one: Inc, two: vec![] }, 1); + check(Enum::C { one: Inc, two: vec![Inc; 3] }, 1 + 3); + check(Generic::(vec![]), 0); + // visits each of the nested `Inc`s + check(Generic(vec![Inc; 5]), 5); + + // Every (nested) `rec!` adds another `Recursive`, and thus 1 more visited `Inc`. + macro_rules! rec { + [$($i:expr),* $(,)?] => { + Recursive { rec: vec![$($i),*], other: Inc } + } + } + check(rec![], 1); + check(rec![rec![]], 2); + check(rec![rec![], rec![]], 3); + check(rec![rec![rec![]]], 3); + + // Every (nested) `prec!` adds another `PartiallyRecursiveField`, and thus 1 more visited `Inc`. + macro_rules! prec { + ([$($i:expr),* $(,)?], $o:expr) => { + PartiallyRecursiveField { partially_rec: (vec![$($i),*], $o), other: Inc } + } + } + // Every nested `a()`, `b()`, and `c()` adds 0, 1, and 2 more visited `Inc`s, respectively. + let a = || Enum::A; + let b = || Enum::B(Inc); + let c = || Enum::C { one: Inc, two: vec![Inc] }; + check(prec!([], a()), 1 + 0); + check(prec!([], b()), 1 + 1); + check(prec!([], c()), 1 + 2); + check(prec!([prec!([], a())], a()), 1 + (1 + 0) + 0); + check(prec!([prec!([], b())], a()), 1 + (1 + 1) + 0); + check(prec!([prec!([], b())], b()), 1 + (1 + 1) + 1); +} diff --git a/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.rs b/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.rs new file mode 100644 index 0000000000000..093ebf0a266ec --- /dev/null +++ b/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.rs @@ -0,0 +1,34 @@ +//! Regression test for . +// Unknown diagnostic attributes must respect item-local lint levels. + +//@ check-pass + +trait _Trait {} + +#[allow(unknown_or_malformed_diagnostic_attributes)] +#[diagnostic::abcdef] +impl _Trait for () {} + +#[diagnostic::abcdef] +#[allow(unknown_or_malformed_diagnostic_attributes)] +impl _Trait for bool {} + +#[expect(unknown_or_malformed_diagnostic_attributes)] +#[diagnostic::abcdef] +impl _Trait for u8 {} + +macro_rules! impl_trait { + ($ty:ty) => { + #[allow(unknown_or_malformed_diagnostic_attributes)] + #[diagnostic::abcdef] + impl _Trait for $ty {} + }; +} + +impl_trait!(u16); + +#[diagnostic::abcdef] +//~^ WARN unknown diagnostic attribute +impl _Trait for u32 {} + +fn main() {} diff --git a/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.stderr b/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.stderr new file mode 100644 index 0000000000000..9d3880fc4e6bd --- /dev/null +++ b/tests/ui/diagnostic_namespace/local-lint-level-issue-135772.stderr @@ -0,0 +1,10 @@ +warning: unknown diagnostic attribute + --> $DIR/local-lint-level-issue-135772.rs:30:15 + | +LL | #[diagnostic::abcdef] + | ^^^^^^ + | + = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default + +warning: 1 warning emitted + diff --git a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs index 9c9085ca1daca..64cea66c1d565 100644 --- a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +++ b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs @@ -1,9 +1,9 @@ //@ run-pass //@ ignore-backends: gcc -//@ min-llvm-version: 22 -//@ revisions: x86_64 aarch64 +//@ min-llvm-version: 23 +//@ revisions: x86 x86_64 aarch64 // -// FIXME: enable x86 on LLVM 23. +//@ [x86] only-x86 //@ [x86_64] only-x86_64 //@ [aarch64] only-aarch64 #![feature(explicit_tail_calls, rust_tail_cc)] @@ -18,6 +18,7 @@ pub extern "tail" fn add() -> u64 { become add(1, 2); } +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] #[inline(never)] pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { #[derive(Clone, Copy)] @@ -42,8 +43,7 @@ pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { fn main() { assert_eq!(add(), 3); - // FIXME: LLVM 22 has a bug which makes this miscompile. - if false { - assert_eq!(pass_struct(5, 6), 5 + 6); - } + // Windows and Aarch64 in LLVM 23 does not support byval arguments. + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] + assert_eq!(pass_struct(5, 6), 5 + 6); } diff --git a/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.rs b/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.rs new file mode 100644 index 0000000000000..72d68c3e91396 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] + +pub trait Tr { + fn foo(&self); +} + +#[allow(dead_code)] +struct Foo; + +impl Tr for Foo { + fn foo(&self) { + bar(); + } +} + +fn bar() {} //~ ERROR function `bar` is never used + +fn main() {} diff --git a/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.stderr b/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.stderr new file mode 100644 index 0000000000000..ba0fe951e4e59 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-adt-propagation-to-impls.stderr @@ -0,0 +1,14 @@ +error: function `bar` is never used + --> $DIR/allow-adt-propagation-to-impls.rs:16:4 + | +LL | fn bar() {} + | ^^^ + | +note: the lint level is defined here + --> $DIR/allow-adt-propagation-to-impls.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error +