Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
f5579e6
Support else-branch for move_guard
A4-Tacks Jan 22, 2026
da57703
Add selection test case
A4-Tacks Jan 22, 2026
2bae85e
Remove `derive(Copy)` on `ArrayWindows`
cuviper Jan 24, 2026
9052155
Manually `impl Clone for ArrayWindows`
cuviper Jan 24, 2026
08cd2ac
`impl FusedIterator for ArrayWindows`
cuviper Jan 24, 2026
8f7d556
`impl TrustedLen for ArrayWindows`
cuviper Jan 24, 2026
129d552
`impl TrustedRandomAccess for ArrayWindows`
cuviper Jan 24, 2026
8321b25
Add test case for select non-first branch
A4-Tacks Jan 26, 2026
5a568d5
fix linking of postcard test
Shourya742 Jan 27, 2026
c99fca1
feat: fallback let postfix completions in condition
A4-Tacks Jan 30, 2026
4e5b645
fix: Fix more glob issues
Veykril Jan 31, 2026
41577bc
refactor: Remove unused comments related to SyntaxErrorKind
Feb 1, 2026
edf20f0
Merge pull request #21561 from Veykril/push-xvymvmuvzuyn
Veykril Feb 2, 2026
c53d127
Merge pull request #21565 from abdul2801/master
Veykril Feb 2, 2026
c836e24
Cover more cases where we need parentheses in `&(impl Trait1 + Trait2)`
ChayimFriedman2 Feb 2, 2026
dbb9b62
internal: Clarify that CargoCheck applies to all check commands
Wilfred Jan 30, 2026
df2a3f8
internal: Document and rename DiagnosticsReceived variants
Wilfred Jan 30, 2026
93dece9
fix: Stale diagnostics with rust-project.json and rustc JSON
Wilfred Feb 2, 2026
301ff3f
Infer the expected len in `include_bytes!()`, to avoid mismatches
ChayimFriedman2 Feb 3, 2026
dc1ac63
Parse `try bikeshed T {}` syntax
goffrie Feb 2, 2026
07213f0
Add Residual, residual_into_try_type to minicore
goffrie Feb 2, 2026
383eb25
Implement homogeneous & heterogeneous try blocks
goffrie Feb 2, 2026
9415ddd
Remove unnecessary `unsafe(non_update_types)`
ChayimFriedman2 Feb 3, 2026
ed58edc
Merge pull request #21572 from goffrie/try
ChayimFriedman2 Feb 3, 2026
8e3c55b
Merge pull request #21576 from ChayimFriedman2/remove-non-update
ChayimFriedman2 Feb 3, 2026
2afde4e
Merge pull request #21557 from A4-Tacks/let-postfix-in-cond
ChayimFriedman2 Feb 3, 2026
492e302
Merge pull request #21508 from A4-Tacks/move-guard-else-if
ChayimFriedman2 Feb 3, 2026
3988689
Use `display_source_code()` in `ReferenceConversion`
ChayimFriedman2 Feb 3, 2026
b4f36ce
Prevent cycles when lowering from supertrait elaboration
ChayimFriedman2 Feb 3, 2026
4c3600c
Provide a cycle handler for `GenericPredicates`
ChayimFriedman2 Feb 3, 2026
b83b375
fix: Fix not complete `.not` in condition
A4-Tacks Jan 26, 2026
34ca201
fix: Truncate display version of commands consistently
Wilfred Feb 3, 2026
51abdca
docs: remove shell prompt symbols and fix code block languages
Act0r1 Feb 4, 2026
9ecd626
docs: additional improvements
Act0r1 Feb 4, 2026
ec6d039
Merge pull request #21526 from A4-Tacks/comp-not-in-cond
ChayimFriedman2 Feb 4, 2026
a72f7fe
docs: use triple backticks for pacman command
Act0r1 Feb 4, 2026
bdf8d3b
Set crt_static_allow_dylibs to true for Emscripten target
hoodmane Feb 4, 2026
17305da
Fix error spans for asm!() args that are macros
gurry Feb 5, 2026
0a4871c
Merge pull request #21585 from Act0r1/docs/improve-documentation
Veykril Feb 5, 2026
e21584e
Merge pull request #21580 from Wilfred/display_command_shortened
Veykril Feb 5, 2026
934eebd
Merge pull request #21579 from ChayimFriedman2/cycle
Veykril Feb 5, 2026
5300804
Merge pull request #21578 from ChayimFriedman2/reparse-unknown
Veykril Feb 5, 2026
82941ed
Merge pull request #21573 from ChayimFriedman2/include-bytes-len
Veykril Feb 5, 2026
a2b126b
Merge pull request #21569 from ChayimFriedman2/parens-multi-impl-trait
Veykril Feb 5, 2026
1a240d6
expand `define_reify_functions!`
cyrgani Feb 5, 2026
749d62b
remove `Closure` generics
cyrgani Feb 5, 2026
0061a22
rustc_parse_format: improve diagnostics for unsupported debug `=` syntax
Unique-Usman Jan 14, 2026
343b469
Update to Xcode 26.2
madsmtm Feb 2, 2026
1a03742
simplify some other generics
cyrgani Feb 5, 2026
18996c6
make `with_api!` take explicit type paths
cyrgani Feb 5, 2026
a6062a8
use `mem::conjure_zst` directly
cyrgani Feb 5, 2026
74d2616
deduplicate `Tag` enum
cyrgani Feb 6, 2026
6fde77c
internal: Simplify binding hash computation in syntax highlighting
Veykril Feb 7, 2026
86cdf24
Merge pull request #21599 from Veykril/push-oqmszvwttzsz
Veykril Feb 7, 2026
3ee0286
internal: Remove `Edition::CURRENT_FIXME`
Veykril Jan 18, 2026
c91e70e
Merge pull request #21488 from Veykril/push-ptvulypwwmvz
Veykril Feb 7, 2026
63eefa9
Bump time from 0.3.44 to 0.3.47
dependabot[bot] Feb 7, 2026
c14eb7f
Merge pull request #21593 from rust-lang/dependabot/cargo/time-0.3.47
Veykril Feb 7, 2026
729f384
Bump salsa
Veykril Feb 7, 2026
84c2a53
Correctly implement client side request cancellation support
Veykril Jan 1, 2026
cee9cc6
Fix an ICE in the vtable iteration for a trait reference in const eva…
jakubadamw Feb 7, 2026
6af91c5
Move tests from tests/crashes to tests/ui now that they don't ICE
jakubadamw Feb 7, 2026
abc2fc0
Merge pull request #21380 from Veykril/push-nolvxuourwru
Veykril Feb 7, 2026
cfe2461
Merge pull request #21570 from Wilfred/clarify_check_struct
Veykril Feb 7, 2026
36058bf
Merge pull request #21571 from Wilfred/check_type_names
Veykril Feb 7, 2026
85ca098
rustc_parse: improve the error diagnostic for "missing let"
Unique-Usman Feb 1, 2026
d0b3a0b
Add some conversion trait impls
Jules-Bertholet Feb 3, 2026
d8ff397
check stalled coroutine obligations eagerly
adwinwhite Feb 8, 2026
81fb703
Fix copy-paste bug: use sub_trace.cause instead of sup_trace.cause in…
cuiweixie Feb 8, 2026
f394d1e
Fix lockfile
lnicola Feb 9, 2026
0e022db
Merge pull request #21607 from lnicola/fix-lockfile
lnicola Feb 9, 2026
5ad44f2
Merge pull request #21538 from Shourya742/2026-01-28-fix-linking-of-p…
lnicola Feb 9, 2026
f248395
bless tests
adwinwhite Feb 8, 2026
88c296a
std: introduce path normalize methods at top of std::path
xizheyin Feb 9, 2026
e04ae80
Rename `JobOwner` to `ActiveJobGuard`
Zalathar Feb 9, 2026
c475bda
Include `key_hash` in `ActiveJobGuard`
Zalathar Feb 9, 2026
2b22150
Port rustc_no_implicit_bounds attribute to parser.
Ozzy1423 Feb 4, 2026
43e5203
compiletest: `-Zunstable-options` for json targets
davidtwco Feb 6, 2026
40a264c
fix: rhs_span to rhs_span_new
cuiweixie Feb 9, 2026
f02f992
Rollup merge of #152388 - lnicola:sync-from-ra, r=lnicola
JonathanBrouwer Feb 9, 2026
5a0a3af
Rollup merge of #151613 - cuviper:array-windows-parity, r=Amanieu
JonathanBrouwer Feb 9, 2026
af99b0a
Rollup merge of #151960 - Unique-Usman:ua/missingletleft, r=estebank
JonathanBrouwer Feb 9, 2026
f6e483d
Rollup merge of #152134 - hoodmane:emscripten-crt-static-allow-dylibs…
JonathanBrouwer Feb 9, 2026
f471f5d
Rollup merge of #152157 - gurry:131292-asm-concat-unicode, r=petroche…
JonathanBrouwer Feb 9, 2026
feb7874
Rollup merge of #152166 - cyrgani:questionable-pm-cleanups, r=petroch…
JonathanBrouwer Feb 9, 2026
458ba4c
Rollup merge of #152236 - davidtwco:compiletest-destabilise-custom-ta…
JonathanBrouwer Feb 9, 2026
11b3cce
Rollup merge of #152287 - jakubadamw:issue-137190, r=petrochenkov
JonathanBrouwer Feb 9, 2026
0efaa3c
Rollup merge of #152317 - cuiweixie:sup_trace, r=jackh726
JonathanBrouwer Feb 9, 2026
24e254c
Rollup merge of #142957 - xizheyin:142931, r=tgross35
JonathanBrouwer Feb 9, 2026
5849e5a
Rollup merge of #145504 - Jules-Bertholet:more_conversion_trait_impls…
JonathanBrouwer Feb 9, 2026
161ba39
Rollup merge of #150897 - Unique-Usman:ua/debug, r=estebank
JonathanBrouwer Feb 9, 2026
b3cbc75
Rollup merge of #152013 - madsmtm:update-xcode, r=shepmaster
JonathanBrouwer Feb 9, 2026
4838fb8
Rollup merge of #152131 - Ozzy1423:attrs6, r=JonathanBrouwer
JonathanBrouwer Feb 9, 2026
ace0387
Rollup merge of #152315 - cuiweixie:bugfix-span, r=jieyouxu
JonathanBrouwer Feb 9, 2026
7d75724
Rollup merge of #152327 - adwinwhite:fix-non-defining-use-ices-ready,…
JonathanBrouwer Feb 9, 2026
5b24d6a
Rollup merge of #152377 - Zalathar:active-job-guard, r=nnethercote
JonathanBrouwer Feb 9, 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
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPreserveUbChecksParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks;
}

pub(crate) struct RustcNoImplicitBoundsParser;

impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitBoundsParser {
const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds;
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcMainParser>>,
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
Single<WithoutArgs<RustcNounwindParser>>,
Single<WithoutArgs<RustcOffloadKernelParser>>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1695,7 +1695,7 @@ fn suggest_ampmut<'tcx>(
&& let Either::Left(rhs_stmt_new) = body.stmt_at(*assign)
&& let StatementKind::Assign(box (_, rvalue_new)) = &rhs_stmt_new.kind
&& let rhs_span_new = rhs_stmt_new.source_info.span
&& let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span)
&& let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span_new)
{
(rvalue, rhs_span, rhs_str) = (rvalue_new, rhs_span_new, rhs_str_new);
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ fn mir_borrowck(
let (input_body, _) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));

// We should eagerly check stalled coroutine obligations from HIR typeck.
// Not doing so leads to silent normalization failures later, which will
// fail to register opaque types in the next solver.
tcx.check_coroutine_obligations(def)?;

let input_body: &Body<'_> = &input_body.borrow();
if let Some(guar) = input_body.tainted_by_errors {
debug!("Skipping borrowck because of tainted body");
Expand Down
33 changes: 17 additions & 16 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ fn expand_preparsed_asm(
let msg = "asm template must be a string literal";
let template_sp = template_expr.span;
let template_is_mac_call = matches!(template_expr.kind, ast::ExprKind::MacCall(_));

// Gets the span inside `template_sp` corresponding to the given range
let span_in_template = |range: std::ops::Range<usize>| -> Span {
if template_is_mac_call {
// When the template is a macro call we can't reliably get inner spans
// so just use the entire template span (see ICEs #129503, #131292)
template_sp
} else {
template_sp.from_inner(InnerSpan::new(range.start, range.end))
}
};

let ExprToSpannedString {
symbol: template_str,
style: template_style,
Expand Down Expand Up @@ -382,13 +394,8 @@ fn expand_preparsed_asm(

if !parser.errors.is_empty() {
let err = parser.errors.remove(0);
let err_sp = if template_is_mac_call {
// If the template is a macro call we can't reliably point to the error's
// span so just use the template's span as the error span (fixes #129503)
template_span
} else {
template_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
};

let err_sp = span_in_template(err.span);

let msg = format!("invalid asm template string: {}", err.description);
let mut e = ecx.dcx().struct_span_err(err_sp, msg);
Expand All @@ -397,8 +404,7 @@ fn expand_preparsed_asm(
e.note(note);
}
if let Some((label, span)) = err.secondary_label {
let err_sp = template_span.from_inner(InnerSpan::new(span.start, span.end));
e.span_label(err_sp, label);
e.span_label(span_in_template(span), label);
}
let guar = e.emit();
return ExpandResult::Ready(Err(guar));
Expand Down Expand Up @@ -477,8 +483,7 @@ fn expand_preparsed_asm(
ecx.dcx()
.create_err(errors::AsmNoMatchedArgumentName {
name: name.to_owned(),
span: template_span
.from_inner(InnerSpan::new(span.start, span.end)),
span: span_in_template(span),
})
.emit();
None
Expand All @@ -490,11 +495,7 @@ fn expand_preparsed_asm(
let mut chars = arg.format.ty.chars();
let mut modifier = chars.next();
if chars.next().is_some() {
let span = arg
.format
.ty_span
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
.unwrap_or(template_sp);
let span = arg.format.ty_span.map(span_in_template).unwrap_or(template_sp);
ecx.dcx().emit_err(errors::AsmModifierInvalid { span });
modifier = None;
}
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,18 @@ pub(crate) enum InvalidFormatStringSuggestion {
#[primary_span]
span: Span,
},

#[suggestion(
"use rust debug printing macro",
code = "{replacement}",
style = "verbose",
applicability = "machine-applicable"
)]
UseRustDebugPrintingMacro {
#[primary_span]
macro_span: Span,
replacement: String,
},
}

#[derive(Diagnostic)]
Expand Down
20 changes: 19 additions & 1 deletion compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ fn make_format_args(
ecx: &mut ExtCtxt<'_>,
input: MacroInput,
append_newline: bool,
macro_span: Span,
) -> ExpandResult<Result<FormatArgs, ErrorGuaranteed>, ()> {
let msg = "format argument must be a string literal";
let unexpanded_fmt_span = input.fmtstr.span;
Expand Down Expand Up @@ -333,6 +334,23 @@ fn make_format_args(
let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::AddMissingColon { span });
}
parse::Suggestion::UseRustDebugPrintingMacro => {
// This targets `println!("{=}", x);` and `println!("{0=}", x);`
if let [arg] = args.all_args() {
let expr_span = arg.expr.span;
if let Ok(expr_snippet) = ecx.source_map().span_to_snippet(expr_span) {
let replacement = format!("{}!({})", "dbg", expr_snippet);

let call_span = macro_span.source_callsite();
e.sugg_ = Some(
errors::InvalidFormatStringSuggestion::UseRustDebugPrintingMacro {
macro_span: call_span,
replacement,
},
);
}
}
}
}
let guar = ecx.dcx().emit_err(e);
return ExpandResult::Ready(Err(guar));
Expand Down Expand Up @@ -1048,7 +1066,7 @@ fn expand_format_args_impl<'cx>(
sp = ecx.with_def_site_ctxt(sp);
ExpandResult::Ready(match parse_args(ecx, sp, tts) {
Ok(input) => {
let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else {
let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl, sp) else {
return ExpandResult::Retry(());
};
match mac {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_no_implicit_autorefs]`
RustcNoImplicitAutorefs,

/// Represents `#[rustc_no_implicit_bounds]`
RustcNoImplicitBounds,

/// Represents `#[rustc_non_const_trait_method]`.
RustcNonConstTraitMethod,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl AttributeKind {
RustcMustImplementOneOf { .. } => No,
RustcNeverReturnsNullPointer => Yes,
RustcNoImplicitAutorefs => Yes,
RustcNoImplicitBounds => No,
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
RustcNounwind => No,
RustcObjcClass { .. } => No,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::PolyTraitRef;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{PolyTraitRef, find_attr};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw};
use rustc_trait_selection::traits;
use smallvec::SmallVec;
use tracing::{debug, instrument};
Expand Down Expand Up @@ -170,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();

// Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) {
return;
}

Expand Down Expand Up @@ -284,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
context: ImpliedBoundsContext<'tcx>,
) -> bool {
let collected = collect_bounds(hir_bounds, context, trait_def_id);
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
!find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds)
&& !collected.any()
}

fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
Expand Down
18 changes: 7 additions & 11 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
{
tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
}
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure_ok().mir_coroutine_witnesses(def_id);
let _ = tcx.ensure_ok().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
if tcx.is_coroutine(def_id.to_def_id())
&& (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
{
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) {
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
}
}
});
});
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/context/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
/// The current `TyCtxt`.
pub tcx: TyCtxt<'tcx>,

/// The current query job, if any. This is updated by `JobOwner::start` in
/// `ty::query::plumbing` when executing a query.
/// The current query job, if any.
pub query: Option<QueryJobId>,

/// Used to prevent queries from calling too deeply.
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,24 @@ pub(crate) struct ExpectedExpressionFoundLet {
pub comparison: Option<MaybeComparison>,
}

#[derive(Diagnostic)]
#[diag("let-chain with missing `let`")]
pub(crate) struct LetChainMissingLet {
#[primary_span]
pub span: Span,
#[label("expected `let` expression, found assignment")]
pub label_span: Span,
#[label("let expression later in the condition")]
pub rhs_span: Span,
#[suggestion(
"add `let` before the expression",
applicability = "maybe-incorrect",
code = "let ",
style = "verbose"
)]
pub sug_span: Span,
}

#[derive(Diagnostic)]
#[diag("`||` operators are not supported in let chain conditions")]
pub(crate) struct OrInLetChain {
Expand Down
47 changes: 46 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4282,7 +4282,52 @@ impl MutVisitor for CondChecker<'_> {
mut_visit::walk_expr(self, e);
self.forbid_let_reason = forbid_let_reason;
}
ExprKind::Assign(ref lhs, _, span) => {
ExprKind::Assign(ref lhs, ref rhs, span) => {
if let ExprKind::Call(_, _) = &lhs.kind {
fn get_path_from_rhs(e: &Expr) -> Option<(u32, &Path)> {
fn inner(e: &Expr, depth: u32) -> Option<(u32, &Path)> {
match &e.kind {
ExprKind::Binary(_, lhs, _) => inner(lhs, depth + 1),
ExprKind::Path(_, path) => Some((depth, path)),
_ => None,
}
}

inner(e, 0)
}

if let Some((depth, path)) = get_path_from_rhs(rhs) {
// For cases like if Some(_) = x && let Some(_) = y && let Some(_) = z
// This return let Some(_) = y expression
fn find_let_some(expr: &Expr) -> Option<&Expr> {
match &expr.kind {
ExprKind::Let(..) => Some(expr),

ExprKind::Binary(op, lhs, rhs) if op.node == BinOpKind::And => {
find_let_some(lhs).or_else(|| find_let_some(rhs))
}

_ => None,
}
}

let expr_span = lhs.span.to(path.span);

if let Some(later_rhs) = find_let_some(rhs)
&& depth > 0
{
let guar = self.parser.dcx().emit_err(errors::LetChainMissingLet {
span: lhs.span,
label_span: expr_span,
rhs_span: later_rhs.span,
sug_span: lhs.span.shrink_to_lo(),
});

self.found_incorrect_let_chain = Some(guar);
}
}
}

let forbid_let_reason = self.forbid_let_reason;
self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden);
let missing_let = self.missing_let;
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ pub enum Suggestion {
/// Add missing colon:
/// `format!("{foo?}")` -> `format!("{foo:?}")`
AddMissingColon(Range<usize>),
/// Use Rust format string:
/// `format!("{x=}")` -> `dbg!(x)`
UseRustDebugPrintingMacro,
}

/// The parser structure for interpreting the input format string. This is
Expand Down Expand Up @@ -462,6 +465,7 @@ impl<'input> Parser<'input> {
('?', _) => self.suggest_format_debug(),
('<' | '^' | '>', _) => self.suggest_format_align(c),
(',', _) => self.suggest_unsupported_python_numeric_grouping(),
('=', '}') => self.suggest_rust_debug_printing_macro(),
_ => self.suggest_positional_arg_instead_of_captured_arg(arg),
}
}
Expand Down Expand Up @@ -871,6 +875,27 @@ impl<'input> Parser<'input> {
}
}

fn suggest_rust_debug_printing_macro(&mut self) {
if let Some((range, _)) = self.consume_pos('=') {
self.errors.insert(
0,
ParseError {
description:
"python's f-string debug `=` is not supported in rust, use `dbg(x)` instead"
.to_owned(),
note: Some(format!("to print `{{`, you can escape it using `{{{{`",)),
label: "expected `}`".to_owned(),
span: range,
secondary_label: self
.last_open_brace
.clone()
.map(|sp| ("because of this opening brace".to_owned(), sp)),
suggestion: Suggestion::UseRustDebugPrintingMacro,
},
);
}
}

fn suggest_format_align(&mut self, alignment: char) {
if let Some((range, _)) = self.consume_pos(alignment) {
self.errors.insert(
Expand Down
Loading
Loading