diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3189fcf7ff9bf..a7c6f8c5d8c26 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -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() { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 7e87d1c31301b..609d75733b2c8 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -985,7 +985,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { 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; @@ -1018,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { }); } 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; @@ -1043,7 +1043,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { ); } 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; diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index a29d9c95e5ea0..e7cbbc713353f 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -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, ); @@ -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, 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, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ae2a4a9504ce3..587038d57bdfd 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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) = ( diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f16269795e985..7f15478349e79 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6660bea03d8b7..c74ef8f271338 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -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. diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index c3b2309b7cdae..e449928a64357 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -31,8 +31,8 @@ const INDENT: &str = " "; macro_rules! print_indented { ($writer:ident, $s:expr, $indent_lvl:expr) => { - let indent = (0..$indent_lvl).map(|_| INDENT).collect::>().concat(); - writeln!($writer, "{}{}", indent, $s).expect("unable to write to ThirPrinter"); + $writer.indent($indent_lvl); + writeln!($writer, "{}", $s).expect("unable to write to ThirPrinter"); }; } @@ -48,6 +48,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { Self { thir, fmt: String::new() } } + fn indent(&mut self, level: usize) { + for _ in 0..level { + self.fmt.push_str(INDENT); + } + } + fn print(&mut self) { print_indented!(self, "params: [", 0); for param in self.thir.params.iter() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5316dde609605..620ba4a3cb363 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -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 "); + } 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 "); + } } } diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs index 96a118e590f39..14cb1d6d362e2 100644 --- a/compiler/rustc_span/src/edit_distance.rs +++ b/compiler/rustc_span/src/edit_distance.rs @@ -188,7 +188,11 @@ fn find_best_match_for_name_impl( return Some(*c); } - let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); + // `fn edit_distance()` use `chars()` to calculate edit distance, so we must + // also use `chars()` (and not `str::len()`) to calculate length here. + let lookup_len = lookup.chars().count(); + + let mut dist = dist.unwrap_or_else(|| cmp::max(lookup_len, 3) / 3); let mut best = None; // store the candidates with the same distance, only for `use_substring_score` current. let mut next_candidates = vec![]; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dc9098d3ade7b..fe1f43835ef3a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1821,11 +1821,8 @@ fn maybe_expand_private_type_alias<'tcx>( } _ => None, }); - if let Some(ct) = const_ { - args.insert( - param.def_id.to_def_id(), - SubstParam::Constant(clean_const(ct, cx)), - ); + if let Some(_) = const_ { + args.insert(param.def_id.to_def_id(), SubstParam::Constant); } // FIXME(const_generics_defaults) indices.consts += 1; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f079d01bd8422..7a5cf8031375d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2546,7 +2546,7 @@ pub(crate) enum TypeBindingKind { pub(crate) enum SubstParam { Type(Type), Lifetime(Lifetime), - Constant(Constant), + Constant, } impl SubstParam { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index dfa386b49de7c..0fb57bf6f6c80 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -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 diff --git a/tests/ui/match/match-tail-expr-never-type-error.rs b/tests/ui/match/match-tail-expr-never-type-error.rs new file mode 100644 index 0000000000000..786ed3fa904be --- /dev/null +++ b/tests/ui/match/match-tail-expr-never-type-error.rs @@ -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); +} diff --git a/tests/ui/match/match-tail-expr-never-type-error.stderr b/tests/ui/match/match-tail-expr-never-type-error.stderr new file mode 100644 index 0000000000000..226d33daeb254 --- /dev/null +++ b/tests/ui/match/match-tail-expr-never-type-error.stderr @@ -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`. diff --git a/tests/ui/repr/issue-83921-ice.rs b/tests/ui/repr/malformed-repr-hints.rs similarity index 76% rename from tests/ui/repr/issue-83921-ice.rs rename to tests/ui/repr/malformed-repr-hints.rs index 70583eb9bd332..27840b5f835d8 100644 --- a/tests/ui/repr/issue-83921-ice.rs +++ b/tests/ui/repr/malformed-repr-hints.rs @@ -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 } diff --git a/tests/ui/repr/issue-83921-ice.stderr b/tests/ui/repr/malformed-repr-hints.stderr similarity index 58% rename from tests/ui/repr/issue-83921-ice.stderr rename to tests/ui/repr/malformed-repr-hints.stderr index 32c450410eace..6fb927557619f 100644 --- a/tests/ui/repr/issue-83921-ice.stderr +++ b/tests/ui/repr/malformed-repr-hints.stderr @@ -1,46 +1,64 @@ error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - --> $DIR/issue-83921-ice.rs:6:8 + --> $DIR/malformed-repr-hints.rs:6:8 | LL | #[repr(packed())] | ^^^^^^^^ error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/issue-83921-ice.rs:10:8 + --> $DIR/malformed-repr-hints.rs:10:8 | LL | #[repr(align)] | ^^^^^ help: supply an argument here: `align(...)` error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/issue-83921-ice.rs:14:8 + --> $DIR/malformed-repr-hints.rs:14:8 | LL | #[repr(align(2, 4))] | ^^^^^^^^^^^ error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/issue-83921-ice.rs:18:8 + --> $DIR/malformed-repr-hints.rs:18:8 | LL | #[repr(align())] | ^^^^^^^ +error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list + --> $DIR/malformed-repr-hints.rs:23:8 + | +LL | #[repr(Rust(u8))] + | ^^^^^^^^ + +error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list + --> $DIR/malformed-repr-hints.rs:25:8 + | +LL | #[repr(Rust(0))] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `Rust` does not take a value + --> $DIR/malformed-repr-hints.rs:27:8 + | +LL | #[repr(Rust = 0)] + | ^^^^^^^^ + error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list - --> $DIR/issue-83921-ice.rs:22:8 + --> $DIR/malformed-repr-hints.rs:31:8 | LL | #[repr(i8())] | ^^^^ error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list - --> $DIR/issue-83921-ice.rs:26:8 + --> $DIR/malformed-repr-hints.rs:35:8 | LL | #[repr(u32(42))] | ^^^^^^^ error[E0552]: invalid representation hint: `i64` does not take a value - --> $DIR/issue-83921-ice.rs:30:8 + --> $DIR/malformed-repr-hints.rs:39:8 | LL | #[repr(i64 = 2)] | ^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0552, E0589, E0693. For more information about an error, try `rustc --explain E0552`. diff --git a/tests/ui/stable-mir-print/basic_function.rs b/tests/ui/stable-mir-print/basic_function.rs new file mode 100644 index 0000000000000..8b8a3154830ac --- /dev/null +++ b/tests/ui/stable-mir-print/basic_function.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z unpretty=stable-mir +// check-pass + +fn foo(i:i32) -> i32 { + i + 1 +} + +fn bar(vec: &mut Vec) -> Vec { + let mut new_vec = vec.clone(); + new_vec.push(1); + new_vec +} + +fn main(){} diff --git a/tests/ui/stable-mir-print/basic_function.stdout b/tests/ui/stable-mir-print/basic_function.stdout new file mode 100644 index 0000000000000..e54ebe2b2c03f --- /dev/null +++ b/tests/ui/stable-mir-print/basic_function.stdout @@ -0,0 +1,226 @@ +// WARNING: This is highly experimental output it's intended for stable-mir developers only. +// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir. +fn foo(_0: i32) -> i32 { + let mut _0: (i32, bool); +} + bb0: { + _2 = 1 Add const 1_i32 + } + bb1: { + _0 = move _2 + } +fn bar(_0: &mut Ty { + id: 10, + kind: RigidTy( + Adt( + AdtDef( + DefId { + id: 3, + name: "std::vec::Vec", + }, + ), + GenericArgs( + [ + Type( + Ty { + id: 11, + kind: Param( + ParamTy { + index: 0, + name: "T", + }, + ), + }, + ), + Type( + Ty { + id: 12, + kind: Param( + ParamTy { + index: 1, + name: "A", + }, + ), + }, + ), + ], + ), + ), + ), +}) -> Ty { + id: 10, + kind: RigidTy( + Adt( + AdtDef( + DefId { + id: 3, + name: "std::vec::Vec", + }, + ), + GenericArgs( + [ + Type( + Ty { + id: 11, + kind: Param( + ParamTy { + index: 0, + name: "T", + }, + ), + }, + ), + Type( + Ty { + id: 12, + kind: Param( + ParamTy { + index: 1, + name: "A", + }, + ), + }, + ), + ], + ), + ), + ), +} { + let mut _0: Ty { + id: 10, + kind: RigidTy( + Adt( + AdtDef( + DefId { + id: 3, + name: "std::vec::Vec", + }, + ), + GenericArgs( + [ + Type( + Ty { + id: 11, + kind: Param( + ParamTy { + index: 0, + name: "T", + }, + ), + }, + ), + Type( + Ty { + id: 12, + kind: Param( + ParamTy { + index: 1, + name: "A", + }, + ), + }, + ), + ], + ), + ), + ), +}; + let mut _1: &Ty { + id: 10, + kind: RigidTy( + Adt( + AdtDef( + DefId { + id: 3, + name: "std::vec::Vec", + }, + ), + GenericArgs( + [ + Type( + Ty { + id: 11, + kind: Param( + ParamTy { + index: 0, + name: "T", + }, + ), + }, + ), + Type( + Ty { + id: 12, + kind: Param( + ParamTy { + index: 1, + name: "A", + }, + ), + }, + ), + ], + ), + ), + ), +}; + let _2: (); + let mut _3: &mut Ty { + id: 10, + kind: RigidTy( + Adt( + AdtDef( + DefId { + id: 3, + name: "std::vec::Vec", + }, + ), + GenericArgs( + [ + Type( + Ty { + id: 11, + kind: Param( + ParamTy { + index: 0, + name: "T", + }, + ), + }, + ), + Type( + Ty { + id: 12, + kind: Param( + ParamTy { + index: 1, + name: "A", + }, + ), + }, + ), + ], + ), + ), + ), +}; +} + bb0: { + _3 = refShared1 + } + bb1: { + _5 = refMut { + kind: TwoPhaseBorrow, +}2 + } + bb2: { + _0 = move _2 + } + bb3: { + } + bb4: { + } +fn main() -> () { +} + bb0: { + } diff --git a/tests/ui/suggestions/non_ascii_ident.rs b/tests/ui/suggestions/non_ascii_ident.rs new file mode 100644 index 0000000000000..679ac4bcb6e3f --- /dev/null +++ b/tests/ui/suggestions/non_ascii_ident.rs @@ -0,0 +1,4 @@ +fn main() { + // There shall be no suggestions here. In particular not `Ok`. + let _ = 读文; //~ ERROR cannot find value `读文` in this scope +} diff --git a/tests/ui/suggestions/non_ascii_ident.stderr b/tests/ui/suggestions/non_ascii_ident.stderr new file mode 100644 index 0000000000000..79fca3e1f612c --- /dev/null +++ b/tests/ui/suggestions/non_ascii_ident.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `读文` in this scope + --> $DIR/non_ascii_ident.rs:3:13 + | +LL | let _ = 读文; + | ^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs new file mode 100644 index 0000000000000..3267527ecf2a7 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -0,0 +1,7 @@ +// edition:2021 + +fn main() { + &[1, 2, 3][1:2]; + //~^ ERROR: expected one of + //~| HELP: you might have meant a range expression +} diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr new file mode 100644 index 0000000000000..df29356cc16b3 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `:` + --> $DIR/range-index-instead-of-colon.rs:4:17 + | +LL | &[1, 2, 3][1:2]; + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: you might have meant a range expression + | +LL | &[1, 2, 3][1..2]; + | ~~ + +error: aborting due to 1 previous error + diff --git a/triagebot.toml b/triagebot.toml index 593386288b496..ed9d59b1bb9eb 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -18,6 +18,7 @@ allow-unauthenticated = [ "relnotes", "requires-*", "regression-*", + "rla-*", "perf-*", "AsyncAwait-OnDeck", "needs-triage",