Skip to content

Rollup of 6 pull requests #118380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading