Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
a630360
Query the trait solver in slow path
mu001999 Jun 12, 2026
1f7863d
tests: adapt two tests for LLVM 23 changes
durin42 Jun 12, 2026
0ab14ca
Don't suggest adding `in` to a `for` loop that already has one
onehr Jun 15, 2026
b77dcf4
fix(rustc_middle): preserve track_caller for vtable shims
kevin-valerio Jun 16, 2026
115338b
rustc_session: accumulate multiple -Zsanitizer target modifiers
PiJoules Jun 11, 2026
439746b
Stabilize `strip_circumfix`
yotamofek Jun 17, 2026
6f4711f
Add simple test for incremental compilation of delegations
aerooneqq Jun 17, 2026
d50d1db
Move `UnusedDuplicate` diag struct to `rustc_attr_parsing`
JonathanBrouwer Jun 17, 2026
de80121
Rollup merge of #157788 - PiJoules:multiple-sanitizer-flags, r=petroc…
JonathanBrouwer Jun 17, 2026
941a78f
Rollup merge of #158012 - yotamofek:pr/stabilize-strip-circumfix, r=j…
JonathanBrouwer Jun 17, 2026
54e884f
Rollup merge of #157810 - mu001999-contrib:fix-157758, r=mati865
JonathanBrouwer Jun 17, 2026
44a2ee3
Rollup merge of #157829 - durin42:llvm-23-pow-fix, r=mati865
JonathanBrouwer Jun 17, 2026
d6dae2b
Rollup merge of #157917 - onehr:fix-for-loop-missing-in-suggestion-10…
JonathanBrouwer Jun 17, 2026
693d522
Rollup merge of #157967 - kevin-valerio:fix-track-caller-vtable-shim,…
JonathanBrouwer Jun 17, 2026
bec267d
Rollup merge of #158019 - aerooneqq:delegation-assert-ignore, r=petro…
JonathanBrouwer Jun 17, 2026
0df317f
Rollup merge of #158023 - JonathanBrouwer:move-unused-duplicate, r=mejrs
JonathanBrouwer Jun 17, 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
8 changes: 2 additions & 6 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::diagnostics::{
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
use crate::session_diagnostics::{
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
DocAttributeNotAttribute, DocKeywordNotKeyword,
DocAttributeNotAttribute, DocKeywordNotKeyword, UnusedDuplicate,
};

fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> bool {
Expand Down Expand Up @@ -159,11 +159,7 @@ impl DocParser {
let unused_span = path.span();
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
rustc_errors::lints::UnusedDuplicate {
this: unused_span,
other: used_span,
warning: true,
},
UnusedDuplicate { this: unused_span, other: used_span, warning: true },
unused_span,
);
return;
Expand Down
14 changes: 3 additions & 11 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ use crate::parser::{
};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions,
ParsedDescription,
ParsedDescription, UnusedDuplicate,
};
use crate::target_checking::AllowedTargets;
use crate::{AttrSuggestionStyle, AttributeParser, AttributeTemplate, EmitAttribute};
Expand Down Expand Up @@ -436,11 +436,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> {
pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
self.emit_lint(
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
rustc_errors::lints::UnusedDuplicate {
this: unused_span,
other: used_span,
warning: false,
},
UnusedDuplicate { this: unused_span, other: used_span, warning: false },
unused_span,
)
}
Expand All @@ -452,11 +448,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> {
) {
self.emit_lint(
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
rustc_errors::lints::UnusedDuplicate {
this: unused_span,
other: used_span,
warning: true,
},
UnusedDuplicate { this: unused_span, other: used_span, warning: true },
unused_span,
)
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,3 +1045,16 @@ pub(crate) struct AdditionalCommaSuggestion {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("unused attribute")]
pub(crate) struct UnusedDuplicate {
#[suggestion("remove this attribute", code = "", applicability = "machine-applicable")]
pub this: Span,
#[note("attribute also specified here")]
pub other: Span,
#[warning(
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
)]
pub warning: bool,
}
1 change: 0 additions & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ mod diagnostic_impls;
pub mod emitter;
pub mod formatting;
pub mod json;
pub mod lints;
mod lock;
pub mod markdown;
pub mod timings;
Expand Down
15 changes: 0 additions & 15 deletions compiler/rustc_errors/src/lints.rs

This file was deleted.

62 changes: 43 additions & 19 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,37 +606,61 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);

impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
let def_id = item.owner_id.def_id;
if !cx.effective_visibilities.is_reachable(def_id) {
return;
}

match item.kind {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {}
let is_generic = match item.kind {
hir::ItemKind::Struct(_, generics, _)
| hir::ItemKind::Union(_, generics, _)
| hir::ItemKind::Enum(_, generics, _) => !generics.params.is_empty(),
_ => return,
}
};

let tcx = cx.tcx;

// Avoid listing trait impls if the trait is allowed.
if cx.tcx.lint_level_spec_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()).is_allow() {
if tcx.lint_level_spec_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()).is_allow() {
return;
}

let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { return };
let Some(debug) = tcx.get_diagnostic_item(sym::Debug) else { return };

let has_impl = cx
.tcx
.non_blanket_impls_for_ty(
debug,
cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip(),
)
let ty = tcx.type_of(item.owner_id);
if tcx
.non_blanket_impls_for_ty(debug, ty.instantiate_identity().skip_norm_wip())
.next()
.is_some();
if !has_impl {
cx.emit_span_lint(
MISSING_DEBUG_IMPLEMENTATIONS,
item.span,
BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug },
);
.is_some()
{
return;
}

let infcx = tcx.infer_ctxt().build(cx.typing_mode());
if is_generic {
let args = infcx.fresh_args_for_item(item.span, def_id.to_def_id());
if infcx
.type_implements_trait_shallow(
debug,
ty.instantiate(tcx, args).skip_norm_wip(),
cx.param_env,
)
.is_some()
{
return;
}
} else if infcx
.type_implements_trait(debug, [ty.instantiate_identity().skip_norm_wip()], cx.param_env)
.must_apply_modulo_regions()
{
return;
}

cx.emit_span_lint(
MISSING_DEBUG_IMPLEMENTATIONS,
item.span,
BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug },
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(result_option_map_or_default))]
#![cfg_attr(bootstrap, feature(strip_circumfix))]
#![feature(error_iter)]
#![feature(file_buffered)]
#![feature(gen_blocks)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(proc_macro_internals)]
#![feature(strip_circumfix)]
#![feature(trusted_len)]
// tidy-alphabetical-end

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,9 @@ impl<'tcx> InstanceKind<'tcx> {

pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
InstanceKind::Item(def_id)
| InstanceKind::Virtual(def_id, _)
| InstanceKind::VTableShim(def_id) => {
tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller } => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ pub(crate) struct MissingInInForLoop {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: MissingInInForLoopSub,
pub sub: Option<MissingInInForLoopSub>,
}

#[derive(Subdiagnostic)]
Expand Down
33 changes: 28 additions & 5 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3086,18 +3086,41 @@ impl<'a> Parser<'a> {
}

fn error_missing_in_for_loop(&mut self) {
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
let (span, sub) = if self.token.is_ident_named(sym::of) {
// Possibly using JS syntax (#75311).
let span = self.token.span;
self.bump();
(span, errors::MissingInInForLoopSub::InNotOf)
(span, Some(errors::MissingInInForLoopSub::InNotOf(span)))
} else if self.eat(exp!(Eq)) {
(self.prev_token.span, errors::MissingInInForLoopSub::InNotEq)
let span = self.prev_token.span;
(span, Some(errors::MissingInInForLoopSub::InNotEq(span)))
} else {
(self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
let span = self.prev_token.span.between(self.token.span);
let sub = (!self.for_loop_head_has_in())
.then_some(errors::MissingInInForLoopSub::AddIn(span));
(span, sub)
};

self.dcx().emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
self.dcx().emit_err(errors::MissingInInForLoop { span, sub });
}

/// Whether the `for` loop header already contains an `in` before its body.
/// If it does, the binding is malformed (e.g. `for i i in 0..10`) rather
/// than missing `in`, so suggesting another `in` would just be invalid too.
fn for_loop_head_has_in(&self) -> bool {
let mut dist = 0;
loop {
let (is_in, is_end) = self.look_ahead(dist, |t| {
(t.is_keyword(kw::In), matches!(t.kind, token::OpenBrace | token::Eof))
});
if is_in {
return true;
}
if is_end {
return false;
}
dist += 1;
}
}

/// Parses a `while` or `while let` expression (`while` token already eaten).
Expand Down
20 changes: 19 additions & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,25 @@ fn build_options<O: Default>(
}
if let Some(tmod) = *tmod {
let v = value.map_or(String::new(), ToOwned::to_owned);
collected_options.target_modifiers.insert(tmod, v);

// Accumulate all the -Zsanitizer flags into a single target modifier.
match tmod {
OptionsTargetModifiers::UnstableOptions(
UnstableOptionsTargetModifiers::Sanitizer,
) => {
collected_options
.target_modifiers
.entry(tmod)
.and_modify(|existing| {
existing.push(',');
existing.push_str(&v);
})
.or_insert(v);
}
_ => {
collected_options.target_modifiers.insert(tmod, v);
}
}
}
if let Some(mitigation) = mitigation {
collected_options.mitigations.reset_mitigation(*mitigation, index);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
//! This API is completely unstable and subject to change.

// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(strip_circumfix))]
#![feature(associated_type_defaults)]
#![feature(default_field_values)]
#![feature(deref_patterns)]
#![feature(hash_set_entry)]
#![feature(iter_intersperse)]
#![feature(iterator_try_reduce)]
#![feature(never_type)]
#![feature(strip_circumfix)]
#![feature(try_blocks)]
#![feature(unwrap_infallible)]
#![feature(yeet_expr)]
Expand Down
4 changes: 1 addition & 3 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2744,8 +2744,6 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(strip_circumfix)]
///
/// let v = &[10, 50, 40, 30];
/// assert_eq!(v.strip_circumfix(&[10], &[30]), Some(&[50, 40][..]));
/// assert_eq!(v.strip_circumfix(&[10], &[40, 30]), Some(&[50][..]));
Expand All @@ -2756,7 +2754,7 @@ impl<T> [T] {
/// assert_eq!(v.strip_circumfix(&[10, 50], &[]), Some(&[40, 30][..]));
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[unstable(feature = "strip_circumfix", issue = "147946")]
#[stable(feature = "strip_circumfix", since = "CURRENT_RUSTC_VERSION")]
pub fn strip_circumfix<S, P>(&self, prefix: &P, suffix: &S) -> Option<&[T]>
where
T: PartialEq,
Expand Down
4 changes: 1 addition & 3 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2510,15 +2510,13 @@ impl str {
/// # Examples
///
/// ```
/// #![feature(strip_circumfix)]
///
/// assert_eq!("bar:hello:foo".strip_circumfix("bar:", ":foo"), Some("hello"));
/// assert_eq!("bar:foo".strip_circumfix("foo", "foo"), None);
/// assert_eq!("foo:bar;".strip_circumfix("foo:", ';'), Some("bar"));
/// ```
#[must_use = "this returns the remaining substring as a new slice, \
without modifying the original"]
#[unstable(feature = "strip_circumfix", issue = "147946")]
#[stable(feature = "strip_circumfix", since = "CURRENT_RUSTC_VERSION")]
pub fn strip_circumfix<P: Pattern, S: Pattern>(&self, prefix: P, suffix: S) -> Option<&str>
where
for<'a> S::Searcher<'a>: ReverseSearcher<'a>,
Expand Down
13 changes: 10 additions & 3 deletions tests/codegen-llvm/issues/issue-118306.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//@ compile-flags: -Copt-level=3
//@ only-x86_64
//@ revisions: LLVM22 LLVM23
//@ [LLVM22] max-llvm-major-version: 22
//@ [LLVM23] min-llvm-version: 23

// Test for #118306.
// Make sure we don't create `br` or `select` instructions.
Expand All @@ -11,9 +14,13 @@ pub fn branchy(input: u64) -> u64 {
// CHECK-LABEL: @branchy(
// CHECK-NEXT: start:
// CHECK-NEXT: [[_2:%.*]] = and i64 [[INPUT:%.*]], 3
// CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} {{\[4 x i64\]|i64|\[8 x i8\]}}, ptr @switch.table.branchy{{(, i64 0)?}}, i64 [[_2]]
// CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]]
// CHECK-NEXT: ret i64 [[SWITCH_LOAD]]
// LLVM22-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} {{\[4 x i64\]|i64|\[8 x i8\]}}, ptr @switch.table.branchy{{(, i64 0)?}}, i64 [[_2]]
// LLVM22-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]]
// LLVM22-NEXT: ret i64 [[SWITCH_LOAD]]
// LLVM23-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr @switch.table.branchy, i64 [[_2]]
// LLVM23-NEXT: [[SWITCH_LOAD:%.*]] = load i8, ptr [[SWITCH_GEP]], align 1
// LLVM23-NEXT: [[SWITCH_EXT:%.*]] = zext i8 [[SWITCH_LOAD]] to i64
// LLVM23-NEXT: ret i64 [[SWITCH_EXT]]
match input % 4 {
1 | 2 => 1,
3 => 2,
Expand Down
Loading
Loading