Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
84963f8
run `extern "tail"` with `byval` argument test
folkertdev Aug 28, 2026
a9a7fbd
Only check allow-on-trait
mu001999 Aug 28, 2026
7768834
Add regression test for item-local diagnostic attribute lint levels
chenyukang Sep 7, 2026
38e3714
windows-gnu: document libgcc requirement
mati865 Sep 7, 2026
9dee1dc
Update books
rustbot Sep 7, 2026
fa2850e
misc typo fixes
ada4a Aug 24, 2026
2827a30
remove outdated docs
ada4a Aug 24, 2026
0db592d
realize that `bounds` works a bit differently than advertised
ada4a Aug 24, 2026
ada4f67
add tests for `#[derive(GenericTypeVisitable)]` and `bounds`
ada4a Sep 7, 2026
2e331b1
Update codegen-llvm/inline-debuginfo.rs for distinct DILocation
zmodem Sep 8, 2026
0847dae
call renumberMetadataForAssembly() in LLVMRustPrintModule()
zmodem Sep 8, 2026
8463342
docs(time): replace "method" with "function"
sorairolake Sep 8, 2026
13f707f
Rename `lower_let_expr` to `lower_fallible_let`, and clarify
Zalathar Sep 7, 2026
9bf6ad8
Fix duplicate thanks entry
JonathanBrouwer Sep 8, 2026
8bd0a5a
Refactor `vec::IntoIter::into_vecdeque` to fix unsoundness
maxdexh Sep 8, 2026
29b15e6
Rollup merge of #162462 - maxdexh:issue-162452-vec-into-iter-into-deq…
JonathanBrouwer Sep 8, 2026
ea9dbb3
Rollup merge of #162468 - Zalathar:fallible-let, r=dianne
JonathanBrouwer Sep 8, 2026
6cf6ed8
Rollup merge of #161806 - ada4a:push-olrruxoktqnl, r=JonathanBrouwer
JonathanBrouwer Sep 8, 2026
432a619
Rollup merge of #161912 - folkertdev:extern-tail-x86-byval, r=WaffleL…
JonathanBrouwer Sep 8, 2026
e869b5a
Rollup merge of #161932 - mu001999-contrib:dead-code-refactor, r=chen…
JonathanBrouwer Sep 8, 2026
e6e3455
Rollup merge of #162236 - zmodem:metadata_reordering, r=nikic
JonathanBrouwer Sep 8, 2026
10d166a
Rollup merge of #162435 - mati865:windows-gnu-libgcc-doc, r=nnethercote
JonathanBrouwer Sep 8, 2026
d231332
Rollup merge of #162439 - rustbot:docs-update, r=traviscross
JonathanBrouwer Sep 8, 2026
a84ac06
Rollup merge of #162451 - chenyukang:yukang-fix-135772-local-diagnost…
JonathanBrouwer Sep 8, 2026
33606d4
Rollup merge of #162455 - zmodem:distinct_dilocation, r=nikic
JonathanBrouwer Sep 8, 2026
ed3d4f3
Rollup merge of #162459 - sorairolake:fix-method-to-function, r=Darksonn
JonathanBrouwer Sep 8, 2026
4c1ad93
Rollup merge of #162465 - JonathanBrouwer:fix-mailmap, r=JonathanBrouwer
JonathanBrouwer Sep 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ John Van Enk <vanenkj@gmail.com>
Jon Gjengset <jon@thesquareplanet.com> <jongje@amazon.com>
Jonas Tepe <jonasprogrammer@gmail.com>
Jonathan Bailey <jbailey@mozilla.com> <jbailey@jbailey-20809.local>
Jonathan Brouwer <jonathantbrouwer@gmail.com> <jonathan.brouwer@technolution.nl>
Jonathan Chan Kwan Yin <sofe2038@gmail.com>
Jonathan L <Xmasreturns@users.noreply.github.com>
Jonathan S <gereeter@gmail.com> Jonathan S <gereeter+code@gmail.com>
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir_build/src/builder/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
65 changes: 36 additions & 29 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<SourceScope>,
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
Expand Down
13 changes: 5 additions & 8 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_type_ir_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ decl_derive!(
/// struct Foo {
/// #[generic_type_visitable(bounds())]
/// just_self: Box<Self>,
/// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable))]
/// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable<__V>))]
/// contains_self: (Box<Self>, 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
);

Expand Down Expand Up @@ -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,
Expand Down
7 changes: 6 additions & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// `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(
Expand All @@ -959,9 +960,13 @@ impl<T, A: Allocator> VecDeque<T, A> {
) -> 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),
Expand Down
52 changes: 33 additions & 19 deletions library/alloc/src/vec/into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,39 @@ impl<T, A: Allocator> IntoIter<T, A> {
// 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) }
}
}

Expand Down
15 changes: 15 additions & 0 deletions library/alloctests/tests/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
8 changes: 4 additions & 4 deletions library/core/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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
///
Expand Down
2 changes: 1 addition & 1 deletion src/doc/edition-guide
2 changes: 1 addition & 1 deletion src/doc/reference
Submodule reference updated 51 files
+3 −1 .github/workflows/daily-grammar-check.yml
+1 −1 book.toml
+1 −1 src/attributes.md
+1 −0 src/attributes/codegen.md
+1 −0 src/attributes/debugger.md
+13 −10 src/attributes/diagnostics.md
+1 −0 src/attributes/limits.md
+1 −0 src/attributes/testing.md
+1 −0 src/attributes/type_system.md
+6 −8 src/behavior-considered-undefined.md
+11 −10 src/comments.md
+5 −5 src/conditional-compilation.md
+14 −10 src/destructors.md
+0 −4 src/divergence.md
+4 −22 src/expressions/block-expr.md
+1 −3 src/expressions/match-expr.md
+21 −21 src/inline-assembly.md
+1 −1 src/introduction.md
+1 −1 src/items/associated-items.md
+35 −3 src/items/enumerations.md
+19 −18 src/items/external-blocks.md
+6 −6 src/items/generics.md
+1 −1 src/items/implementations.md
+1 −1 src/items/static-items.md
+1 −1 src/items/unions.md
+6 −5 src/items/use-declarations.md
+1 −0 src/keywords.md
+1 −0 src/lifetime-elision.md
+1 −1 src/linkage.md
+1 −0 src/macro-ambiguity.md
+2 −1 src/macros-by-example.md
+1 −0 src/memory-model.md
+2 −2 src/names/name-resolution.md
+1 −0 src/names/namespaces.md
+2 −0 src/names/scopes.md
+1 −0 src/paths.md
+2 −2 src/patterns.md
+1 −0 src/runtime.md
+1 −0 src/special-types-and-traits.md
+4 −4 src/syntax-index.md
+1 −0 src/tokens.md
+65 −3 src/type-layout.md
+2 −1 src/types/boolean.md
+1 −2 src/types/closure.md
+2 −2 src/types/impl-trait.md
+47 −17 src/types/never.md
+0 −30 src/types/textual.md
+1 −0 src/unsafe-keyword.md
+1 −0 tools/grammar-check/src/main.rs
+27 −0 tools/grammar-check/src/test_cases.rs
+1 −1 tools/grammar/src/lib.rs
Loading
Loading