Skip to content

Commit 56ee65a

Browse files
committed
Auto merge of #106743 - matthiaskrgr:rollup-q5dpxms, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #106620 (Detect struct literal needing parentheses) - #106622 (Detect out of bounds range pattern value) - #106703 (Note predicate span on `ImplDerivedObligation`) - #106705 (Report fulfillment errors in new trait solver) - #106726 (Fix some typos in code comments.) - #106734 (Deny having src/test exisiting in tidy) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1e4f900 + 106df9e commit 56ee65a

File tree

70 files changed

+452
-109
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+452
-109
lines changed

compiler/rustc_codegen_ssa/src/back/write.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10981098
// There are a few environmental pre-conditions that shape how the system
10991099
// is set up:
11001100
//
1101-
// - Error reporting only can happen on the main thread because that's the
1101+
// - Error reporting can only happen on the main thread because that's the
11021102
// only place where we have access to the compiler `Session`.
11031103
// - LLVM work can be done on any thread.
11041104
// - Codegen can only happen on the main thread.
@@ -1110,16 +1110,16 @@ fn start_executing_work<B: ExtraBackendMethods>(
11101110
// Error Reporting
11111111
// ===============
11121112
// The error reporting restriction is handled separately from the rest: We
1113-
// set up a `SharedEmitter` the holds an open channel to the main thread.
1113+
// set up a `SharedEmitter` that holds an open channel to the main thread.
11141114
// When an error occurs on any thread, the shared emitter will send the
11151115
// error message to the receiver main thread (`SharedEmitterMain`). The
11161116
// main thread will periodically query this error message queue and emit
11171117
// any error messages it has received. It might even abort compilation if
1118-
// has received a fatal error. In this case we rely on all other threads
1118+
// it has received a fatal error. In this case we rely on all other threads
11191119
// being torn down automatically with the main thread.
11201120
// Since the main thread will often be busy doing codegen work, error
11211121
// reporting will be somewhat delayed, since the message queue can only be
1122-
// checked in between to work packages.
1122+
// checked in between two work packages.
11231123
//
11241124
// Work Processing Infrastructure
11251125
// ==============================
@@ -1133,7 +1133,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
11331133
// thread about what work to do when, and it will spawn off LLVM worker
11341134
// threads as open LLVM WorkItems become available.
11351135
//
1136-
// The job of the main thread is to codegen CGUs into LLVM work package
1136+
// The job of the main thread is to codegen CGUs into LLVM work packages
11371137
// (since the main thread is the only thread that can do this). The main
11381138
// thread will block until it receives a message from the coordinator, upon
11391139
// which it will codegen one CGU, send it to the coordinator and block
@@ -1142,10 +1142,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
11421142
//
11431143
// The coordinator keeps a queue of LLVM WorkItems, and when a `Token` is
11441144
// available, it will spawn off a new LLVM worker thread and let it process
1145-
// that a WorkItem. When a LLVM worker thread is done with its WorkItem,
1145+
// a WorkItem. When a LLVM worker thread is done with its WorkItem,
11461146
// it will just shut down, which also frees all resources associated with
11471147
// the given LLVM module, and sends a message to the coordinator that the
1148-
// has been completed.
1148+
// WorkItem has been completed.
11491149
//
11501150
// Work Scheduling
11511151
// ===============
@@ -1165,7 +1165,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
11651165
//
11661166
// Doing LLVM Work on the Main Thread
11671167
// ----------------------------------
1168-
// Since the main thread owns the compiler processes implicit `Token`, it is
1168+
// Since the main thread owns the compiler process's implicit `Token`, it is
11691169
// wasteful to keep it blocked without doing any work. Therefore, what we do
11701170
// in this case is: We spawn off an additional LLVM worker thread that helps
11711171
// reduce the queue. The work it is doing corresponds to the implicit
@@ -1216,7 +1216,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
12161216
// ------------------------------
12171217
//
12181218
// The final job the coordinator thread is responsible for is managing LTO
1219-
// and how that works. When LTO is requested what we'll to is collect all
1219+
// and how that works. When LTO is requested what we'll do is collect all
12201220
// optimized LLVM modules into a local vector on the coordinator. Once all
12211221
// modules have been codegened and optimized we hand this to the `lto`
12221222
// module for further optimization. The `lto` module will return back a list

compiler/rustc_error_messages/locales/en-US/mir_build.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
206206
.label = lower bound larger than upper bound
207207
.teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
208208
209+
mir_build_literal_in_range_out_of_bounds =
210+
literal out of range for `{$ty}`
211+
.label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
212+
209213
mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
210214
211215
mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->

compiler/rustc_error_messages/locales/en-US/parse.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ parse_struct_literal_body_without_path =
22
struct literal body without path
33
.suggestion = you might have forgotten to add the struct literal inside the block
44
5+
parse_struct_literal_needing_parens =
6+
invalid struct literal
7+
.suggestion = you might need to surround the struct literal in parentheses
8+
59
parse_maybe_report_ambiguous_plus =
610
ambiguous `+` in a type
711
.suggestion = use parentheses to disambiguate

compiler/rustc_mir_build/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,16 @@ pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
493493
pub teach: Option<()>,
494494
}
495495

496+
#[derive(Diagnostic)]
497+
#[diag(mir_build_literal_in_range_out_of_bounds)]
498+
pub struct LiteralOutOfRange<'tcx> {
499+
#[primary_span]
500+
#[label]
501+
pub span: Span,
502+
pub ty: Ty<'tcx>,
503+
pub max: u128,
504+
}
505+
496506
#[derive(Diagnostic)]
497507
#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
498508
pub struct LowerRangeBoundMustBeLessThanUpper {

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+62-6
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
129129
hi: mir::ConstantKind<'tcx>,
130130
end: RangeEnd,
131131
span: Span,
132+
lo_expr: Option<&hir::Expr<'tcx>>,
133+
hi_expr: Option<&hir::Expr<'tcx>>,
132134
) -> PatKind<'tcx> {
133135
assert_eq!(lo.ty(), ty);
134136
assert_eq!(hi.ty(), ty);
135137
let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env);
138+
let max = || {
139+
self.tcx
140+
.layout_of(self.param_env.with_reveal_all_normalized(self.tcx).and(ty))
141+
.ok()
142+
.unwrap()
143+
.size
144+
.unsigned_int_max()
145+
};
136146
match (end, cmp) {
137147
// `x..y` where `x < y`.
138148
// Non-empty because the range includes at least `x`.
@@ -141,7 +151,27 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
141151
}
142152
// `x..y` where `x >= y`. The range is empty => error.
143153
(RangeEnd::Excluded, _) => {
144-
self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span });
154+
let mut lower_overflow = false;
155+
let mut higher_overflow = false;
156+
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
157+
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
158+
{
159+
if lo.eval_bits(self.tcx, self.param_env, ty) != val {
160+
lower_overflow = true;
161+
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
162+
}
163+
}
164+
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
165+
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
166+
{
167+
if hi.eval_bits(self.tcx, self.param_env, ty) != val {
168+
higher_overflow = true;
169+
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
170+
}
171+
}
172+
if !lower_overflow && !higher_overflow {
173+
self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span });
174+
}
145175
PatKind::Wild
146176
}
147177
// `x..=y` where `x == y`.
@@ -152,10 +182,34 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
152182
}
153183
// `x..=y` where `x > y` hence the range is empty => error.
154184
(RangeEnd::Included, _) => {
155-
self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
156-
span,
157-
teach: if self.tcx.sess.teach(&error_code!(E0030)) { Some(()) } else { None },
158-
});
185+
let mut lower_overflow = false;
186+
let mut higher_overflow = false;
187+
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
188+
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
189+
{
190+
if lo.eval_bits(self.tcx, self.param_env, ty) != val {
191+
lower_overflow = true;
192+
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
193+
}
194+
}
195+
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
196+
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
197+
{
198+
if hi.eval_bits(self.tcx, self.param_env, ty) != val {
199+
higher_overflow = true;
200+
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
201+
}
202+
}
203+
if !lower_overflow && !higher_overflow {
204+
self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
205+
span,
206+
teach: if self.tcx.sess.teach(&error_code!(E0030)) {
207+
Some(())
208+
} else {
209+
None
210+
},
211+
});
212+
}
159213
PatKind::Wild
160214
}
161215
}
@@ -201,7 +255,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
201255

202256
let (lp, hp) = (lo.as_ref().map(|(x, _)| x), hi.as_ref().map(|(x, _)| x));
203257
let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) {
204-
Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span),
258+
Some((lc, hc)) => {
259+
self.lower_pattern_range(ty, lc, hc, end, lo_span, lo_expr, hi_expr)
260+
}
205261
None => {
206262
let msg = &format!(
207263
"found bad range pattern `{:?}` outside of error recovery",

compiler/rustc_parse/src/errors.rs

+18
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,24 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg {
970970
pub after: Span,
971971
}
972972

973+
#[derive(Diagnostic)]
974+
#[diag(parse_struct_literal_needing_parens)]
975+
pub(crate) struct StructLiteralNeedingParens {
976+
#[primary_span]
977+
pub span: Span,
978+
#[subdiagnostic]
979+
pub sugg: StructLiteralNeedingParensSugg,
980+
}
981+
982+
#[derive(Subdiagnostic)]
983+
#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
984+
pub(crate) struct StructLiteralNeedingParensSugg {
985+
#[suggestion_part(code = "(")]
986+
pub before: Span,
987+
#[suggestion_part(code = ")")]
988+
pub after: Span,
989+
}
990+
973991
#[derive(Diagnostic)]
974992
#[diag(parse_unmatched_angle_brackets)]
975993
pub(crate) struct UnmatchedAngleBrackets {

compiler/rustc_parse/src/parser/diagnostics.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use crate::errors::{
1212
IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead,
1313
ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType,
1414
QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
15-
StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, SuggRemoveComma,
16-
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
17-
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
15+
StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
16+
SuggEscapeToUseAsIdentifier, SuggRemoveComma, UnexpectedConstInGenericParam,
17+
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
18+
UseEqInstead,
1819
};
1920

2021
use crate::lexer::UnmatchedBrace;
@@ -623,12 +624,15 @@ impl<'a> Parser<'a> {
623624
&mut self,
624625
lo: Span,
625626
s: BlockCheckMode,
627+
maybe_struct_name: token::Token,
628+
can_be_struct_literal: bool,
626629
) -> Option<PResult<'a, P<Block>>> {
627630
if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) {
628631
// We might be having a struct literal where people forgot to include the path:
629632
// fn foo() -> Foo {
630633
// field: value,
631634
// }
635+
info!(?maybe_struct_name, ?self.token);
632636
let mut snapshot = self.create_snapshot_for_diagnostic();
633637
let path = Path {
634638
segments: ThinVec::new(),
@@ -648,21 +652,32 @@ impl<'a> Parser<'a> {
648652
// field: value,
649653
// } }
650654
err.delay_as_bug();
651-
self.sess.emit_err(StructLiteralBodyWithoutPath {
652-
span: expr.span,
653-
sugg: StructLiteralBodyWithoutPathSugg {
654-
before: expr.span.shrink_to_lo(),
655-
after: expr.span.shrink_to_hi(),
656-
},
657-
});
658655
self.restore_snapshot(snapshot);
659656
let mut tail = self.mk_block(
660657
vec![self.mk_stmt_err(expr.span)],
661658
s,
662659
lo.to(self.prev_token.span),
663660
);
664661
tail.could_be_bare_literal = true;
665-
Ok(tail)
662+
if maybe_struct_name.is_ident() && can_be_struct_literal {
663+
// Account for `if Example { a: one(), }.is_pos() {}`.
664+
Err(self.sess.create_err(StructLiteralNeedingParens {
665+
span: maybe_struct_name.span.to(expr.span),
666+
sugg: StructLiteralNeedingParensSugg {
667+
before: maybe_struct_name.span.shrink_to_lo(),
668+
after: expr.span.shrink_to_hi(),
669+
},
670+
}))
671+
} else {
672+
self.sess.emit_err(StructLiteralBodyWithoutPath {
673+
span: expr.span,
674+
sugg: StructLiteralBodyWithoutPathSugg {
675+
before: expr.span.shrink_to_lo(),
676+
after: expr.span.shrink_to_hi(),
677+
},
678+
});
679+
Ok(tail)
680+
}
666681
}
667682
(Err(err), Ok(tail)) => {
668683
// We have a block tail that contains a somehow valid type ascription expr.

compiler/rustc_parse/src/parser/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,7 @@ impl<'a> Parser<'a> {
20392039
});
20402040
}
20412041

2042-
let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
2042+
let (attrs, blk) = self.parse_block_common(lo, blk_mode, true)?;
20432043
Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
20442044
}
20452045

compiler/rustc_parse/src/parser/item.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2214,7 +2214,8 @@ impl<'a> Parser<'a> {
22142214
*sig_hi = self.prev_token.span;
22152215
(AttrVec::new(), None)
22162216
} else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() {
2217-
self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
2217+
self.parse_block_common(self.token.span, BlockCheckMode::Default, false)
2218+
.map(|(attrs, body)| (attrs, Some(body)))?
22182219
} else if self.token.kind == token::Eq {
22192220
// Recover `fn foo() = $expr;`.
22202221
self.bump(); // `=`

compiler/rustc_parse/src/parser/stmt.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -498,24 +498,31 @@ impl<'a> Parser<'a> {
498498

499499
/// Parses a block. Inner attributes are allowed.
500500
pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (AttrVec, P<Block>)> {
501-
self.parse_block_common(self.token.span, BlockCheckMode::Default)
501+
self.parse_block_common(self.token.span, BlockCheckMode::Default, true)
502502
}
503503

504504
/// Parses a block. Inner attributes are allowed.
505505
pub(super) fn parse_block_common(
506506
&mut self,
507507
lo: Span,
508508
blk_mode: BlockCheckMode,
509+
can_be_struct_literal: bool,
509510
) -> PResult<'a, (AttrVec, P<Block>)> {
510511
maybe_whole!(self, NtBlock, |x| (AttrVec::new(), x));
511512

513+
let maybe_ident = self.prev_token.clone();
512514
self.maybe_recover_unexpected_block_label();
513515
if !self.eat(&token::OpenDelim(Delimiter::Brace)) {
514516
return self.error_block_no_opening_brace();
515517
}
516518

517519
let attrs = self.parse_inner_attributes()?;
518-
let tail = match self.maybe_suggest_struct_literal(lo, blk_mode) {
520+
let tail = match self.maybe_suggest_struct_literal(
521+
lo,
522+
blk_mode,
523+
maybe_ident,
524+
can_be_struct_literal,
525+
) {
519526
Some(tail) => tail?,
520527
None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
521528
};

0 commit comments

Comments
 (0)