Skip to content

Commit c37783d

Browse files
committed
Auto merge of rust-lang#118380 - matthiaskrgr:rollup-cfekmpm, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#111133 (Detect Python-like slicing and suggest how to fix) - rust-lang#114708 (Allow setting `rla` labels via `rustbot`) - rust-lang#117526 (Account for `!` arm in tail `match` expr) - rust-lang#118282 (effects: Run `enforce_context_effects` for all method calls) - rust-lang#118366 (Detect and reject malformed `repr(Rust)` hints) - rust-lang#118375 (Add -Zunpretty=stable-mir output test) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b4c4664 + 7969125 commit c37783d

27 files changed

+514
-73
lines changed

compiler/rustc_ast/src/token.rs

+5
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,11 @@ impl Token {
756756
)
757757
}
758758

759+
/// Returns `true` if the token is the integer literal.
760+
pub fn is_integer_lit(&self) -> bool {
761+
matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
762+
}
763+
759764
/// Returns `true` if the token is a non-raw identifier for which `pred` holds.
760765
pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
761766
match self.ident() {

compiler/rustc_attr/src/builtin.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
985985
Ok(literal) => acc.push(ReprPacked(literal)),
986986
Err(message) => literal_error = Some(message),
987987
};
988-
} else if matches!(name, sym::C | sym::simd | sym::transparent)
988+
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
989989
|| int_type_of_word(name).is_some()
990990
{
991991
recognised = true;
@@ -1018,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10181018
});
10191019
} else if matches!(
10201020
meta_item.name_or_empty(),
1021-
sym::C | sym::simd | sym::transparent
1021+
sym::Rust | sym::C | sym::simd | sym::transparent
10221022
) || int_type_of_word(meta_item.name_or_empty()).is_some()
10231023
{
10241024
recognised = true;
@@ -1043,7 +1043,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10431043
);
10441044
} else if matches!(
10451045
meta_item.name_or_empty(),
1046-
sym::C | sym::simd | sym::transparent
1046+
sym::Rust | sym::C | sym::simd | sym::transparent
10471047
) || int_type_of_word(meta_item.name_or_empty()).is_some()
10481048
{
10491049
recognised = true;

compiler/rustc_hir_typeck/src/_match.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
139139
&cause,
140140
Some(arm.body),
141141
arm_ty,
142-
|err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm),
142+
|err| {
143+
self.explain_never_type_coerced_to_unit(err, arm, arm_ty, prior_arm, expr);
144+
},
143145
false,
144146
);
145147

@@ -177,6 +179,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
177179
coercion.complete(self)
178180
}
179181

182+
fn explain_never_type_coerced_to_unit(
183+
&self,
184+
err: &mut Diagnostic,
185+
arm: &hir::Arm<'tcx>,
186+
arm_ty: Ty<'tcx>,
187+
prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
188+
expr: &hir::Expr<'tcx>,
189+
) {
190+
if let hir::ExprKind::Block(block, _) = arm.body.kind
191+
&& let Some(expr) = block.expr
192+
&& let arm_tail_ty = self.node_ty(expr.hir_id)
193+
&& arm_tail_ty.is_never()
194+
&& !arm_ty.is_never()
195+
{
196+
err.span_label(
197+
expr.span,
198+
format!(
199+
"this expression is of type `!`, but it is coerced to `{arm_ty}` due to its \
200+
surrounding expression",
201+
),
202+
);
203+
self.suggest_mismatched_types_on_tail(
204+
err,
205+
expr,
206+
arm_ty,
207+
prior_arm.map_or(arm_tail_ty, |(_, ty, _)| ty),
208+
expr.hir_id,
209+
);
210+
}
211+
self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm)
212+
}
213+
180214
fn suggest_removing_semicolon_for_coerce(
181215
&self,
182216
diag: &mut Diagnostic,

compiler/rustc_hir_typeck/src/callee.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
845845
expected,
846846
);
847847

848-
self.write_method_call(call_expr.hir_id, method_callee);
848+
self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
849849
output_type
850850
}
851851
}
@@ -895,7 +895,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
895895
adjustments.extend(autoref);
896896
fcx.apply_adjustments(self.callee_expr, adjustments);
897897

898-
fcx.write_method_call(self.call_expr.hir_id, method_callee);
898+
fcx.write_method_call_and_enforce_effects(
899+
self.call_expr.hir_id,
900+
self.call_expr.span,
901+
method_callee,
902+
);
899903
}
900904
None => {
901905
// This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`

compiler/rustc_hir_typeck/src/coercion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17151715
// label pointing out the cause for the type coercion will be wrong
17161716
// as prior return coercions would not be relevant (#57664).
17171717
let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
1718+
fcx.suggest_missing_semicolon(&mut err, expr, expected, false);
17181719
let pointing_at_return_type =
17191720
fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
17201721
if let (Some(cond_expr), true, false) = (

compiler/rustc_hir_typeck/src/expr.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
663663
coerce.coerce_forced_unit(
664664
self,
665665
&cause,
666-
|err| {
667-
self.suggest_mismatched_types_on_tail(err, expr, ty, e_ty, target_id);
666+
|mut err| {
667+
self.suggest_missing_semicolon(&mut err, expr, e_ty, false);
668+
self.suggest_mismatched_types_on_tail(
669+
&mut err, expr, ty, e_ty, target_id,
670+
);
668671
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
669672
self.annotate_loop_expected_due_to_inference(err, expr, error);
670673
if let Some(val) = ty_kind_suggestion(ty) {
@@ -1312,9 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13121315
Ok(method) => {
13131316
// We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
13141317
// trigger this codepath causing `structurally_resolve_type` to emit an error.
1315-
1316-
self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args);
1317-
self.write_method_call(expr.hir_id, method);
1318+
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
13181319
Ok(method)
13191320
}
13201321
Err(error) => {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
159159
}
160160

161161
#[instrument(level = "debug", skip(self))]
162-
pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
162+
pub fn write_method_call_and_enforce_effects(
163+
&self,
164+
hir_id: hir::HirId,
165+
span: Span,
166+
method: MethodCallee<'tcx>,
167+
) {
168+
self.enforce_context_effects(hir_id, span, method.def_id, method.args);
163169
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
164170
self.write_args(hir_id, method.args);
165171
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7272
blk_id: hir::HirId,
7373
) -> bool {
7474
let expr = expr.peel_drop_temps();
75-
self.suggest_missing_semicolon(err, expr, expected, false);
7675
let mut pointing_at_return_type = false;
7776
if let hir::ExprKind::Break(..) = expr.kind {
7877
// `break` type mismatches provide better context for tail `loop` expressions.

compiler/rustc_hir_typeck/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,13 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) {
438438
}
439439
}
440440

441+
/// `expected` here is the expected number of explicit generic arguments on the trait.
441442
fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool {
442443
let generics = tcx.generics_of(trait_did);
443-
generics.count() == expected + if generics.has_self { 1 } else { 0 }
444+
generics.count()
445+
== expected
446+
+ if generics.has_self { 1 } else { 0 }
447+
+ if generics.host_effect_index.is_some() { 1 } else { 0 }
444448
}
445449

446450
pub fn provide(providers: &mut Providers) {

compiler/rustc_hir_typeck/src/op.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
291291
.push(autoref);
292292
}
293293
}
294-
self.write_method_call(expr.hir_id, method);
294+
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
295295

296296
method.sig.output()
297297
}
@@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
781781
assert!(op.is_by_value());
782782
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
783783
Ok(method) => {
784-
self.write_method_call(ex.hir_id, method);
784+
self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method);
785785
method.sig.output()
786786
}
787787
Err(errors) => {

compiler/rustc_hir_typeck/src/place_op.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3838
span_bug!(expr.span, "input to deref is not a ref?");
3939
}
4040
let ty = self.make_overloaded_place_return_type(method).ty;
41-
self.write_method_call(expr.hir_id, method);
41+
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
4242
Some(ty)
4343
}
4444

@@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
179179
}
180180
self.apply_adjustments(base_expr, adjustments);
181181

182-
self.write_method_call(expr.hir_id, method);
182+
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
183183

184184
return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
185185
}
@@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
404404
None => return,
405405
};
406406
debug!("convert_place_op_to_mutable: method={:?}", method);
407-
self.write_method_call(expr.hir_id, method);
407+
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
408408

409409
let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else {
410410
span_bug!(expr.span, "input to mutable place op is not a mut ref?");

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,13 @@ impl<'tcx> ConstToPat<'tcx> {
263263
// (If there isn't, then we can safely issue a hard
264264
// error, because that's never worked, due to compiler
265265
// using `PartialEq::eq` in this scenario in the past.)
266-
let partial_eq_trait_id =
267-
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
266+
let tcx = self.tcx();
267+
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
268268
let partial_eq_obligation = Obligation::new(
269-
self.tcx(),
269+
tcx,
270270
ObligationCause::dummy(),
271271
self.param_env,
272-
ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]),
272+
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
273273
);
274274

275275
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get

compiler/rustc_parse/src/parser/stmt.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -567,20 +567,37 @@ impl<'a> Parser<'a> {
567567
snapshot.recover_diff_marker();
568568
}
569569
if self.token == token::Colon {
570-
// if next token is following a colon, it's likely a path
571-
// and we can suggest a path separator
572-
self.bump();
573-
if self.token.span.lo() == self.prev_token.span.hi() {
570+
// if a previous and next token of the current one is
571+
// integer literal (e.g. `1:42`), it's likely a range
572+
// expression for Pythonistas and we can suggest so.
573+
if self.prev_token.is_integer_lit()
574+
&& self.may_recover()
575+
&& self.look_ahead(1, |token| token.is_integer_lit())
576+
{
577+
// FIXME(hkmatsumoto): Might be better to trigger
578+
// this only when parsing an index expression.
574579
err.span_suggestion_verbose(
575-
self.prev_token.span,
576-
"maybe write a path separator here",
577-
"::",
580+
self.token.span,
581+
"you might have meant a range expression",
582+
"..",
578583
Applicability::MaybeIncorrect,
579584
);
580-
}
581-
if self.sess.unstable_features.is_nightly_build() {
582-
// FIXME(Nilstrieb): Remove this again after a few months.
583-
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
585+
} else {
586+
// if next token is following a colon, it's likely a path
587+
// and we can suggest a path separator
588+
self.bump();
589+
if self.token.span.lo() == self.prev_token.span.hi() {
590+
err.span_suggestion_verbose(
591+
self.prev_token.span,
592+
"maybe write a path separator here",
593+
"::",
594+
Applicability::MaybeIncorrect,
595+
);
596+
}
597+
if self.sess.unstable_features.is_nightly_build() {
598+
// FIXME(Nilstrieb): Remove this again after a few months.
599+
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
600+
}
584601
}
585602
}
586603

src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
1111
const ENTRY_LIMIT: usize = 900;
1212
// FIXME: The following limits should be reduced eventually.
1313
const ISSUES_ENTRY_LIMIT: usize = 1852;
14-
const ROOT_ENTRY_LIMIT: usize = 867;
14+
const ROOT_ENTRY_LIMIT: usize = 868;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
fn never() -> ! {
2+
loop {}
3+
}
4+
5+
fn bar(a: bool) {
6+
match a {
7+
true => 1,
8+
false => {
9+
never() //~ ERROR `match` arms have incompatible types
10+
}
11+
}
12+
}
13+
fn main() {
14+
bar(true);
15+
bar(false);
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: `match` arms have incompatible types
2+
--> $DIR/match-tail-expr-never-type-error.rs:9:13
3+
|
4+
LL | fn bar(a: bool) {
5+
| - help: try adding a return type: `-> i32`
6+
LL | / match a {
7+
LL | | true => 1,
8+
| | - this is found to be of type `{integer}`
9+
LL | | false => {
10+
LL | | never()
11+
| | ^^^^^^^
12+
| | |
13+
| | expected integer, found `()`
14+
| | this expression is of type `!`, but it is coerced to `()` due to its surrounding expression
15+
LL | | }
16+
LL | | }
17+
| |_____- `match` arms have incompatible types
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0308`.

tests/ui/repr/issue-83921-ice.rs tests/ui/repr/malformed-repr-hints.rs

+9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ struct S3;
1919
//~^ ERROR: incorrect `repr(align)` attribute format
2020
struct S4;
2121

22+
// Regression test for issue #118334:
23+
#[repr(Rust(u8))]
24+
//~^ ERROR: invalid representation hint
25+
#[repr(Rust(0))]
26+
//~^ ERROR: invalid representation hint
27+
#[repr(Rust = 0)]
28+
//~^ ERROR: invalid representation hint
29+
struct S5;
30+
2231
#[repr(i8())]
2332
//~^ ERROR: invalid representation hint
2433
enum E1 { A, B }

0 commit comments

Comments
 (0)