Skip to content

Commit

Permalink
Auto merge of rust-lang#118380 - matthiaskrgr:rollup-cfekmpm, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

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
  • Loading branch information
bors committed Nov 27, 2023
2 parents b4c4664 + 7969125 commit c37783d
Show file tree
Hide file tree
Showing 27 changed files with 514 additions and 73 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,11 @@ impl Token {
)
}

/// Returns `true` if the token is the integer literal.
pub fn is_integer_lit(&self) -> bool {
matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
}

/// Returns `true` if the token is a non-raw identifier for which `pred` holds.
pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
match self.ident() {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
Ok(literal) => acc.push(ReprPacked(literal)),
Err(message) => literal_error = Some(message),
};
} else if matches!(name, sym::C | sym::simd | sym::transparent)
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
|| int_type_of_word(name).is_some()
{
recognised = true;
Expand Down Expand Up @@ -1018,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
});
} else if matches!(
meta_item.name_or_empty(),
sym::C | sym::simd | sym::transparent
sym::Rust | sym::C | sym::simd | sym::transparent
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;
Expand All @@ -1043,7 +1043,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
);
} else if matches!(
meta_item.name_or_empty(),
sym::C | sym::simd | sym::transparent
sym::Rust | sym::C | sym::simd | sym::transparent
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;
Expand Down
36 changes: 35 additions & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&cause,
Some(arm.body),
arm_ty,
|err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm),
|err| {
self.explain_never_type_coerced_to_unit(err, arm, arm_ty, prior_arm, expr);
},
false,
);

Expand Down Expand Up @@ -177,6 +179,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coercion.complete(self)
}

fn explain_never_type_coerced_to_unit(
&self,
err: &mut Diagnostic,
arm: &hir::Arm<'tcx>,
arm_ty: Ty<'tcx>,
prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
expr: &hir::Expr<'tcx>,
) {
if let hir::ExprKind::Block(block, _) = arm.body.kind
&& let Some(expr) = block.expr
&& let arm_tail_ty = self.node_ty(expr.hir_id)
&& arm_tail_ty.is_never()
&& !arm_ty.is_never()
{
err.span_label(
expr.span,
format!(
"this expression is of type `!`, but it is coerced to `{arm_ty}` due to its \
surrounding expression",
),
);
self.suggest_mismatched_types_on_tail(
err,
expr,
arm_ty,
prior_arm.map_or(arm_tail_ty, |(_, ty, _)| ty),
expr.hir_id,
);
}
self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm)
}

fn suggest_removing_semicolon_for_coerce(
&self,
diag: &mut Diagnostic,
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
);

self.write_method_call(call_expr.hir_id, method_callee);
self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
output_type
}
}
Expand Down Expand Up @@ -895,7 +895,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
adjustments.extend(autoref);
fcx.apply_adjustments(self.callee_expr, adjustments);

fcx.write_method_call(self.call_expr.hir_id, method_callee);
fcx.write_method_call_and_enforce_effects(
self.call_expr.hir_id,
self.call_expr.span,
method_callee,
);
}
None => {
// This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,6 +1715,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// label pointing out the cause for the type coercion will be wrong
// as prior return coercions would not be relevant (#57664).
let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
fcx.suggest_missing_semicolon(&mut err, expr, expected, false);
let pointing_at_return_type =
fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
if let (Some(cond_expr), true, false) = (
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coerce.coerce_forced_unit(
self,
&cause,
|err| {
self.suggest_mismatched_types_on_tail(err, expr, ty, e_ty, target_id);
|mut err| {
self.suggest_missing_semicolon(&mut err, expr, e_ty, false);
self.suggest_mismatched_types_on_tail(
&mut err, expr, ty, e_ty, target_id,
);
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
self.annotate_loop_expected_due_to_inference(err, expr, error);
if let Some(val) = ty_kind_suggestion(ty) {
Expand Down Expand Up @@ -1312,9 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(method) => {
// We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
// trigger this codepath causing `structurally_resolve_type` to emit an error.

self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args);
self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
Ok(method)
}
Err(error) => {
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

#[instrument(level = "debug", skip(self))]
pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
pub fn write_method_call_and_enforce_effects(
&self,
hir_id: hir::HirId,
span: Span,
method: MethodCallee<'tcx>,
) {
self.enforce_context_effects(hir_id, span, method.def_id, method.args);
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
self.write_args(hir_id, method.args);
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
blk_id: hir::HirId,
) -> bool {
let expr = expr.peel_drop_temps();
self.suggest_missing_semicolon(err, expr, expected, false);
let mut pointing_at_return_type = false;
if let hir::ExprKind::Break(..) = expr.kind {
// `break` type mismatches provide better context for tail `loop` expressions.
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,13 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) {
}
}

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

pub fn provide(providers: &mut Providers) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.push(autoref);
}
}
self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);

method.sig.output()
}
Expand Down Expand Up @@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
assert!(op.is_by_value());
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
Ok(method) => {
self.write_method_call(ex.hir_id, method);
self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method);
method.sig.output()
}
Err(errors) => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/place_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span_bug!(expr.span, "input to deref is not a ref?");
}
let ty = self.make_overloaded_place_return_type(method).ty;
self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
Some(ty)
}

Expand Down Expand Up @@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
self.apply_adjustments(base_expr, adjustments);

self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);

return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
}
Expand Down Expand Up @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => return,
};
debug!("convert_place_op_to_mutable: method={:?}", method);
self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);

let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else {
span_bug!(expr.span, "input to mutable place op is not a mut ref?");
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,13 @@ impl<'tcx> ConstToPat<'tcx> {
// (If there isn't, then we can safely issue a hard
// error, because that's never worked, due to compiler
// using `PartialEq::eq` in this scenario in the past.)
let partial_eq_trait_id =
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
let tcx = self.tcx();
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
let partial_eq_obligation = Obligation::new(
self.tcx(),
tcx,
ObligationCause::dummy(),
self.param_env,
ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]),
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
);

// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
Expand Down
39 changes: 28 additions & 11 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,20 +567,37 @@ impl<'a> Parser<'a> {
snapshot.recover_diff_marker();
}
if self.token == token::Colon {
// if next token is following a colon, it's likely a path
// and we can suggest a path separator
self.bump();
if self.token.span.lo() == self.prev_token.span.hi() {
// if a previous and next token of the current one is
// integer literal (e.g. `1:42`), it's likely a range
// expression for Pythonistas and we can suggest so.
if self.prev_token.is_integer_lit()
&& self.may_recover()
&& self.look_ahead(1, |token| token.is_integer_lit())
{
// FIXME(hkmatsumoto): Might be better to trigger
// this only when parsing an index expression.
err.span_suggestion_verbose(
self.prev_token.span,
"maybe write a path separator here",
"::",
self.token.span,
"you might have meant a range expression",
"..",
Applicability::MaybeIncorrect,
);
}
if self.sess.unstable_features.is_nightly_build() {
// FIXME(Nilstrieb): Remove this again after a few months.
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
} else {
// if next token is following a colon, it's likely a path
// and we can suggest a path separator
self.bump();
if self.token.span.lo() == self.prev_token.span.hi() {
err.span_suggestion_verbose(
self.prev_token.span,
"maybe write a path separator here",
"::",
Applicability::MaybeIncorrect,
);
}
if self.sess.unstable_features.is_nightly_build() {
// FIXME(Nilstrieb): Remove this again after a few months.
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
const ENTRY_LIMIT: usize = 900;
// FIXME: The following limits should be reduced eventually.
const ISSUES_ENTRY_LIMIT: usize = 1852;
const ROOT_ENTRY_LIMIT: usize = 867;
const ROOT_ENTRY_LIMIT: usize = 868;

const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/match/match-tail-expr-never-type-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
fn never() -> ! {
loop {}
}

fn bar(a: bool) {
match a {
true => 1,
false => {
never() //~ ERROR `match` arms have incompatible types
}
}
}
fn main() {
bar(true);
bar(false);
}
21 changes: 21 additions & 0 deletions tests/ui/match/match-tail-expr-never-type-error.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: `match` arms have incompatible types
--> $DIR/match-tail-expr-never-type-error.rs:9:13
|
LL | fn bar(a: bool) {
| - help: try adding a return type: `-> i32`
LL | / match a {
LL | | true => 1,
| | - this is found to be of type `{integer}`
LL | | false => {
LL | | never()
| | ^^^^^^^
| | |
| | expected integer, found `()`
| | this expression is of type `!`, but it is coerced to `()` due to its surrounding expression
LL | | }
LL | | }
| |_____- `match` arms have incompatible types

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ struct S3;
//~^ ERROR: incorrect `repr(align)` attribute format
struct S4;

// Regression test for issue #118334:
#[repr(Rust(u8))]
//~^ ERROR: invalid representation hint
#[repr(Rust(0))]
//~^ ERROR: invalid representation hint
#[repr(Rust = 0)]
//~^ ERROR: invalid representation hint
struct S5;

#[repr(i8())]
//~^ ERROR: invalid representation hint
enum E1 { A, B }
Expand Down

0 comments on commit c37783d

Please sign in to comment.