Skip to content

Commit 93b6a36

Browse files
committed
Auto merge of rust-lang#116501 - workingjubilee:rollup-fpzov6m, r=workingjubilee
Rollup of 4 pull requests Successful merges: - rust-lang#116277 (dont call mir.post_mono_checks in codegen) - rust-lang#116400 (Detect missing `=>` after match guard during parsing) - rust-lang#116458 (Properly export function defined in test which uses global_asm!()) - rust-lang#116500 (Add tvOS to target_os for register_dtor) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8fdb0a9 + 4b102b0 commit 93b6a36

Some content is hidden

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

41 files changed

+266
-124
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

-11
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,6 @@ pub(crate) fn verify_func(
250250
}
251251

252252
fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
253-
if let Err(err) =
254-
fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
255-
{
256-
err.emit_err(fx.tcx);
257-
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
258-
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
259-
// compilation should have been aborted
260-
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
261-
return;
262-
}
263-
264253
let arg_uninhabited = fx
265254
.mir
266255
.args_iter()

compiler/rustc_codegen_ssa/src/mir/constant.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2121
}
2222

2323
pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::ConstValue<'tcx> {
24+
// `MirUsedCollector` visited all constants before codegen began, so if we got here there
25+
// can be no more constants that fail to evaluate.
2426
self.monomorphize(constant.const_)
2527
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
2628
.expect("erroneous constant not captured by required_consts")

compiler/rustc_codegen_ssa/src/mir/mod.rs

+4-11
Original file line numberDiff line numberDiff line change
@@ -209,18 +209,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
209209
caller_location: None,
210210
};
211211

212-
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
212+
// It may seem like we should iterate over `required_consts` to ensure they all successfully
213+
// evaluate; however, the `MirUsedCollector` already did that during the collection phase of
214+
// monomorphization so we don't have to do it again.
213215

214-
// Rust post-monomorphization checks; we later rely on them.
215-
if let Err(err) =
216-
mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
217-
{
218-
err.emit_err(cx.tcx());
219-
// This IR shouldn't ever be emitted, but let's try to guard against any of this code
220-
// ever running.
221-
start_bx.abort();
222-
return;
223-
}
216+
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
224217

225218
let memory_locals = analyze::non_ssa_locals(&fx);
226219

compiler/rustc_const_eval/src/interpret/eval_context.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -750,12 +750,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
750750

751751
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
752752
if M::POST_MONO_CHECKS {
753-
// `ctfe_query` does some error message decoration that we want to be in effect here.
754-
self.ctfe_query(None, |tcx| {
755-
body.post_mono_checks(*tcx, self.param_env, |c| {
756-
self.subst_from_current_frame_and_normalize_erasing_regions(c)
757-
})
758-
})?;
753+
for &const_ in &body.required_consts {
754+
let c =
755+
self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
756+
c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| {
757+
err.emit_note(*self.tcx);
758+
err
759+
})?;
760+
}
759761
}
760762

761763
// done
@@ -1054,14 +1056,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10541056
Ok(())
10551057
}
10561058

1057-
/// Call a query that can return `ErrorHandled`. If `span` is `Some`, point to that span when an error occurs.
1059+
/// Call a query that can return `ErrorHandled`. Should be used for statics and other globals.
1060+
/// (`mir::Const`/`ty::Const` have `eval` methods that can be used directly instead.)
10581061
pub fn ctfe_query<T>(
10591062
&self,
1060-
span: Option<Span>,
10611063
query: impl FnOnce(TyCtxtAt<'tcx>) -> Result<T, ErrorHandled>,
10621064
) -> Result<T, ErrorHandled> {
10631065
// Use a precise span for better cycle errors.
1064-
query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
1066+
query(self.tcx.at(self.cur_span())).map_err(|err| {
10651067
err.emit_note(*self.tcx);
10661068
err
10671069
})
@@ -1082,7 +1084,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10821084
} else {
10831085
self.param_env
10841086
};
1085-
let val = self.ctfe_query(None, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
1087+
let val = self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
10861088
self.raw_const_to_mplace(val)
10871089
}
10881090

@@ -1092,7 +1094,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10921094
span: Option<Span>,
10931095
layout: Option<TyAndLayout<'tcx>>,
10941096
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
1095-
let const_val = self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?;
1097+
let const_val = val.eval(*self.tcx, self.param_env, span).map_err(|err| {
1098+
// FIXME: somehow this is reachable even when POST_MONO_CHECKS is on.
1099+
// Are we not always populating `required_consts`?
1100+
err.emit_note(*self.tcx);
1101+
err
1102+
})?;
10961103
self.const_val_to_op(const_val, val.ty(), layout)
10971104
}
10981105

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
164164
sym::type_name => Ty::new_static_str(self.tcx.tcx),
165165
_ => bug!(),
166166
};
167-
let val = self.ctfe_query(None, |tcx| {
167+
let val = self.ctfe_query(|tcx| {
168168
tcx.const_eval_global_id(self.param_env, gid, Some(tcx.span))
169169
})?;
170170
let val = self.const_val_to_op(val, ty, Some(dest.layout))?;

compiler/rustc_const_eval/src/interpret/memory.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
536536
}
537537

538538
// We don't give a span -- statics don't need that, they cannot be generic or associated.
539-
let val = self.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?;
539+
let val = self.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
540540
(val, Some(def_id))
541541
}
542542
};

compiler/rustc_middle/src/mir/interpret/error.rs

-15
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,6 @@ impl ErrorHandled {
4343
}
4444
}
4545

46-
pub fn emit_err(&self, tcx: TyCtxt<'_>) -> ErrorGuaranteed {
47-
match self {
48-
&ErrorHandled::Reported(err, span) => {
49-
if !err.is_tainted_by_errors && !span.is_dummy() {
50-
tcx.sess.emit_err(error::ErroneousConstant { span });
51-
}
52-
err.error
53-
}
54-
&ErrorHandled::TooGeneric(span) => tcx.sess.delay_span_bug(
55-
span,
56-
"encountered TooGeneric error when monomorphic data was expected",
57-
),
58-
}
59-
}
60-
6146
pub fn emit_note(&self, tcx: TyCtxt<'_>) {
6247
match self {
6348
&ErrorHandled::Reported(err, span) => {

compiler/rustc_middle/src/mir/mod.rs

+1-29
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
44
5-
use crate::mir::interpret::{AllocRange, ConstAllocation, ErrorHandled, Scalar};
5+
use crate::mir::interpret::{AllocRange, ConstAllocation, Scalar};
66
use crate::mir::visit::MirVisitable;
77
use crate::ty::codec::{TyDecoder, TyEncoder};
88
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
@@ -568,34 +568,6 @@ impl<'tcx> Body<'tcx> {
568568
pub fn is_custom_mir(&self) -> bool {
569569
self.injection_phase.is_some()
570570
}
571-
572-
/// *Must* be called once the full substitution for this body is known, to ensure that the body
573-
/// is indeed fit for code generation or consumption more generally.
574-
///
575-
/// Sadly there's no nice way to represent an "arbitrary normalizer", so we take one for
576-
/// constants specifically. (`Option<GenericArgsRef>` could be used for that, but the fact
577-
/// that `Instance::args_for_mir_body` is private and instead instance exposes normalization
578-
/// functions makes it seem like exposing the generic args is not the intended strategy.)
579-
///
580-
/// Also sadly, CTFE doesn't even know whether it runs on MIR that is already polymorphic or still monomorphic,
581-
/// so we cannot just immediately ICE on TooGeneric.
582-
///
583-
/// Returns Ok(()) if everything went fine, and `Err` if a problem occurred and got reported.
584-
pub fn post_mono_checks(
585-
&self,
586-
tcx: TyCtxt<'tcx>,
587-
param_env: ty::ParamEnv<'tcx>,
588-
normalize_const: impl Fn(Const<'tcx>) -> Result<Const<'tcx>, ErrorHandled>,
589-
) -> Result<(), ErrorHandled> {
590-
// For now, the only thing we have to check is is to ensure that all the constants used in
591-
// the body successfully evaluate.
592-
for &const_ in &self.required_consts {
593-
let c = normalize_const(const_.const_)?;
594-
c.eval(tcx, param_env, Some(const_.span))?;
595-
}
596-
597-
Ok(())
598-
}
599571
}
600572

601573
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]

compiler/rustc_middle/src/mir/visit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ macro_rules! make_mir_visitor {
184184

185185
visit_place_fns!($($mutability)?);
186186

187+
/// This is called for every constant in the MIR body and every `required_consts`
188+
/// (i.e., including consts that have been dead-code-eliminated).
187189
fn visit_constant(
188190
&mut self,
189191
constant: & $($mutability)? ConstOperand<'tcx>,

compiler/rustc_monomorphize/src/collector.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,8 @@ fn collect_used_items<'tcx>(
14261426
);
14271427
}
14281428

1429+
// Here we rely on the visitor also visiting `required_consts`, so that we evaluate them
1430+
// and abort compilation if any of them errors.
14291431
MirUsedCollector {
14301432
tcx,
14311433
body: &body,

compiler/rustc_parse/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ parse_expected_semi_found_str = expected `;`, found `{$token}`
225225
226226
parse_expected_statement_after_outer_attr = expected statement after outer attribute
227227
228+
parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$token}`
229+
.label = expected one of `,`, `:`, or `{"}"}`
230+
.ident_label = while parsing this struct field
231+
228232
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
229233
230234
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements

compiler/rustc_parse/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,17 @@ pub(crate) struct ExpectedElseBlock {
430430
pub condition_start: Span,
431431
}
432432

433+
#[derive(Diagnostic)]
434+
#[diag(parse_expected_struct_field)]
435+
pub(crate) struct ExpectedStructField {
436+
#[primary_span]
437+
#[label]
438+
pub span: Span,
439+
pub token: Token,
440+
#[label(parse_ident_label)]
441+
pub ident_span: Span,
442+
}
443+
433444
#[derive(Diagnostic)]
434445
#[diag(parse_outer_attribute_not_allowed_on_if_else)]
435446
pub(crate) struct OuterAttributeNotAllowedOnIfElse {

compiler/rustc_parse/src/parser/expr.rs

+73-19
Original file line numberDiff line numberDiff line change
@@ -2834,7 +2834,7 @@ impl<'a> Parser<'a> {
28342834
)?;
28352835
let guard = if this.eat_keyword(kw::If) {
28362836
let if_span = this.prev_token.span;
2837-
let mut cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
2837+
let mut cond = this.parse_match_guard_condition()?;
28382838

28392839
CondChecker { parser: this, forbid_let_reason: None }.visit_expr(&mut cond);
28402840

@@ -2860,9 +2860,9 @@ impl<'a> Parser<'a> {
28602860
{
28612861
err.span_suggestion(
28622862
this.token.span,
2863-
"try using a fat arrow here",
2863+
"use a fat arrow to start a match arm",
28642864
"=>",
2865-
Applicability::MaybeIncorrect,
2865+
Applicability::MachineApplicable,
28662866
);
28672867
err.emit();
28682868
this.bump();
@@ -2979,6 +2979,33 @@ impl<'a> Parser<'a> {
29792979
})
29802980
}
29812981

2982+
fn parse_match_guard_condition(&mut self) -> PResult<'a, P<Expr>> {
2983+
self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, None).map_err(
2984+
|mut err| {
2985+
if self.prev_token == token::OpenDelim(Delimiter::Brace) {
2986+
let sugg_sp = self.prev_token.span.shrink_to_lo();
2987+
// Consume everything within the braces, let's avoid further parse
2988+
// errors.
2989+
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
2990+
let msg = "you might have meant to start a match arm after the match guard";
2991+
if self.eat(&token::CloseDelim(Delimiter::Brace)) {
2992+
let applicability = if self.token.kind != token::FatArrow {
2993+
// We have high confidence that we indeed didn't have a struct
2994+
// literal in the match guard, but rather we had some operation
2995+
// that ended in a path, immediately followed by a block that was
2996+
// meant to be the match arm.
2997+
Applicability::MachineApplicable
2998+
} else {
2999+
Applicability::MaybeIncorrect
3000+
};
3001+
err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability);
3002+
}
3003+
}
3004+
err
3005+
},
3006+
)
3007+
}
3008+
29823009
pub(crate) fn is_builtin(&self) -> bool {
29833010
self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
29843011
}
@@ -3049,9 +3076,10 @@ impl<'a> Parser<'a> {
30493076
|| self.look_ahead(2, |t| t == &token::Colon)
30503077
&& (
30513078
// `{ ident: token, ` cannot start a block.
3052-
self.look_ahead(4, |t| t == &token::Comma) ||
3053-
// `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`.
3054-
self.look_ahead(3, |t| !t.can_begin_type())
3079+
self.look_ahead(4, |t| t == &token::Comma)
3080+
// `{ ident: ` cannot start a block unless it's a type ascription
3081+
// `ident: Type`.
3082+
|| self.look_ahead(3, |t| !t.can_begin_type())
30553083
)
30563084
)
30573085
}
@@ -3091,6 +3119,7 @@ impl<'a> Parser<'a> {
30913119
let mut fields = ThinVec::new();
30923120
let mut base = ast::StructRest::None;
30933121
let mut recover_async = false;
3122+
let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
30943123

30953124
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
30963125
recover_async = true;
@@ -3128,6 +3157,26 @@ impl<'a> Parser<'a> {
31283157
e.span_label(pth.span, "while parsing this struct");
31293158
}
31303159

3160+
if let Some((ident, _)) = self.token.ident()
3161+
&& !self.token.is_reserved_ident()
3162+
&& self.look_ahead(1, |t| {
3163+
AssocOp::from_token(&t).is_some()
3164+
|| matches!(t.kind, token::OpenDelim(_))
3165+
|| t.kind == token::Dot
3166+
})
3167+
{
3168+
// Looks like they tried to write a shorthand, complex expression.
3169+
e.span_suggestion_verbose(
3170+
self.token.span.shrink_to_lo(),
3171+
"try naming a field",
3172+
&format!("{ident}: ", ),
3173+
Applicability::MaybeIncorrect,
3174+
);
3175+
}
3176+
if in_if_guard && close_delim == Delimiter::Brace {
3177+
return Err(e);
3178+
}
3179+
31313180
if !recover {
31323181
return Err(e);
31333182
}
@@ -3173,19 +3222,6 @@ impl<'a> Parser<'a> {
31733222
",",
31743223
Applicability::MachineApplicable,
31753224
);
3176-
} else if is_shorthand
3177-
&& (AssocOp::from_token(&self.token).is_some()
3178-
|| matches!(&self.token.kind, token::OpenDelim(_))
3179-
|| self.token.kind == token::Dot)
3180-
{
3181-
// Looks like they tried to write a shorthand, complex expression.
3182-
let ident = parsed_field.expect("is_shorthand implies Some").ident;
3183-
e.span_suggestion(
3184-
ident.span.shrink_to_lo(),
3185-
"try naming a field",
3186-
&format!("{ident}: "),
3187-
Applicability::HasPlaceholders,
3188-
);
31893225
}
31903226
}
31913227
if !recover {
@@ -3288,6 +3324,24 @@ impl<'a> Parser<'a> {
32883324

32893325
// Check if a colon exists one ahead. This means we're parsing a fieldname.
32903326
let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
3327+
// Proactively check whether parsing the field will be incorrect.
3328+
let is_wrong = this.token.is_ident()
3329+
&& !this.token.is_reserved_ident()
3330+
&& !this.look_ahead(1, |t| {
3331+
t == &token::Colon
3332+
|| t == &token::Eq
3333+
|| t == &token::Comma
3334+
|| t == &token::CloseDelim(Delimiter::Brace)
3335+
|| t == &token::CloseDelim(Delimiter::Parenthesis)
3336+
});
3337+
if is_wrong {
3338+
return Err(errors::ExpectedStructField {
3339+
span: this.look_ahead(1, |t| t.span),
3340+
ident_span: this.token.span,
3341+
token: this.look_ahead(1, |t| t.clone()),
3342+
}
3343+
.into_diagnostic(&self.sess.span_diagnostic));
3344+
}
32913345
let (ident, expr) = if is_shorthand {
32923346
// Mimic `x: x` for the `x` field shorthand.
32933347
let ident = this.parse_ident_common(false)?;

compiler/rustc_parse/src/parser/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ bitflags::bitflags! {
5252
const NO_STRUCT_LITERAL = 1 << 1;
5353
const CONST_EXPR = 1 << 2;
5454
const ALLOW_LET = 1 << 3;
55+
const IN_IF_GUARD = 1 << 4;
5556
}
5657
}
5758

0 commit comments

Comments
 (0)