From b1ad22941b6fc90a177ba896d60b367a8c216a55 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 10 Aug 2023 16:27:49 -0400 Subject: [PATCH 01/14] Allow setting `rla-*` labels via `rustbot` https://github.com/rust-lang/rust-log-analyzer/pull/75 adds a `rla-silenced` label flag that will turn off RLA updates for non-bors tests. Allow setting that labels and others via `rustbot`. --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 6b36e59dfc84d..0b71a67ebd56a 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -18,6 +18,7 @@ allow-unauthenticated = [ "relnotes", "requires-*", "regression-*", + "rla-*", "perf-*", "AsyncAwait-OnDeck", "needs-triage", From 879c7f91ab498df8bdf7f391de31dcd5557b9719 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Wed, 22 Nov 2023 15:05:32 +0300 Subject: [PATCH 02/14] add pretty_terminator --- compiler/stable_mir/src/lib.rs | 2 +- compiler/stable_mir/src/mir/body.rs | 3 +- compiler/stable_mir/src/mir/pretty.rs | 131 ++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 1f75dfb69cfd9..94d17a2fa6794 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -184,7 +184,7 @@ impl std::fmt::Display for Opaque { impl std::fmt::Debug for Opaque { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) + write!(f, "{}", self.0) } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 8d237fc9f1d95..0966f9198a251 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,4 +1,4 @@ -use crate::mir::pretty::{function_body, pretty_statement}; +use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator}; use crate::ty::{ AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, }; @@ -83,6 +83,7 @@ impl Body { Ok(()) }) .collect::>(); + writeln!(w, "{}", pretty_terminator(&block.terminator.kind))?; writeln!(w, " }}").unwrap(); Ok(()) }) diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index e7bca295b5a04..6fa440887427f 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -3,6 +3,8 @@ use crate::mir::{Operand, Rvalue, StatementKind}; use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy}; use crate::{with, Body, CrateItem, Mutability}; +use super::{AssertMessage, BinOp, TerminatorKind}; + pub fn function_name(item: CrateItem) -> String { let mut pretty_name = String::new(); let body = item.body(); @@ -70,6 +72,135 @@ pub fn pretty_statement(statement: &StatementKind) -> String { pretty } +pub fn pretty_terminator(terminator: &TerminatorKind) -> String { + let mut pretty = String::new(); + match terminator { + TerminatorKind::Goto { .. } => format!(" goto"), + TerminatorKind::SwitchInt { discr, .. } => { + format!(" switch({})", pretty_operand(discr)) + } + TerminatorKind::Resume => format!(" resume"), + TerminatorKind::Abort => format!(" abort"), + TerminatorKind::Return => format!(" return"), + TerminatorKind::Unreachable => format!(" unreachable"), + TerminatorKind::Drop { place, .. } => format!(" drop({:?})", place.local), + TerminatorKind::Call { func, args, destination, .. } => { + pretty.push_str(" "); + pretty.push_str(format!("{} = ", destination.local).as_str()); + pretty.push_str(&pretty_operand(func)); + pretty.push_str("("); + args.iter().enumerate().for_each(|(i, arg)| { + if i > 0 { + pretty.push_str(", "); + } + pretty.push_str(&pretty_operand(arg)); + }); + pretty.push_str(")"); + pretty + } + TerminatorKind::Assert { cond, expected, msg, target: _, unwind: _ } => { + pretty.push_str(" assert("); + if !expected { + pretty.push_str("!"); + } + pretty.push_str(&pretty_operand(cond)); + pretty.push_str(&pretty_assert_message(msg)); + pretty.push_str(")"); + pretty + } + TerminatorKind::CoroutineDrop => format!(" coroutine_drop"), + TerminatorKind::InlineAsm { .. } => todo!(), + } +} + +pub fn pretty_assert_message(msg: &AssertMessage) -> String { + let mut pretty = String::new(); + match msg { + AssertMessage::BoundsCheck { len, index } => { + let pretty_len = pretty_operand(len); + let pretty_index = pretty_operand(index); + pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Add, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Sub, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Mul, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Div, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Rem, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Shr, _, r) => { + let pretty_r = pretty_operand(r); + pretty.push_str( + format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}") + .as_str(), + ); + pretty + } + AssertMessage::Overflow(BinOp::Shl, _, r) => { + let pretty_r = pretty_operand(r); + pretty.push_str( + format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}") + .as_str(), + ); + pretty + } + AssertMessage::OverflowNeg(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str( + format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(), + ); + pretty + } + AssertMessage::DivisionByZero(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str()); + pretty + } + AssertMessage::RemainderByZero(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str( + format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(), + ); + pretty + } + AssertMessage::ResumedAfterReturn(_) => { + format!("attempt to resume a generator after completion") + } + AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"), + AssertMessage::MisalignedPointerDereference { required, found } => { + let pretty_required = pretty_operand(required); + let pretty_found = pretty_operand(found); + pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str()); + pretty + } + _ => todo!(), + } +} + pub fn pretty_operand(operand: &Operand) -> String { let mut pretty = String::new(); match operand { From de2779077a95cdf41b5fd9d8b89221318af1bfe1 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 24 Nov 2023 14:34:27 +0300 Subject: [PATCH 03/14] add successors and their formatter --- .../rustc_smir/src/rustc_smir/convert/mir.rs | 12 +- compiler/stable_mir/src/lib.rs | 2 +- compiler/stable_mir/src/mir/body.rs | 76 +++++++++++-- compiler/stable_mir/src/mir/pretty.rs | 106 +++++++++++++++--- 4 files changed, 165 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 62a26bc089ad8..04ae134eaca6e 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -578,13 +578,11 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { } mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt { discr: discr.stable(tables), - targets: targets - .iter() - .map(|(value, target)| stable_mir::mir::SwitchTarget { - value, - target: target.as_usize(), - }) - .collect(), + targets: { + let (value_vec, target_vec) = + targets.iter().map(|(value, target)| (value, target.as_usize())).unzip(); + stable_mir::mir::SwitchTargets { value: value_vec, targets: target_vec } + }, otherwise: targets.otherwise().as_usize(), }, mir::TerminatorKind::UnwindResume => TerminatorKind::Resume, diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 94d17a2fa6794..2099c485c6f8f 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -16,7 +16,7 @@ //! //! The goal is to eventually be published on //! [crates.io](https://crates.io). - +#![feature(type_alias_impl_trait)] #[macro_use] extern crate scoped_tls; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 0966f9198a251..02a2868767659 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -3,8 +3,7 @@ use crate::ty::{ AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, }; use crate::{Error, Opaque, Span, Symbol}; -use std::io; - +use std::{io, slice}; /// The SMIR representation of a single function. #[derive(Clone, Debug)] pub struct Body { @@ -83,7 +82,8 @@ impl Body { Ok(()) }) .collect::>(); - writeln!(w, "{}", pretty_terminator(&block.terminator.kind))?; + pretty_terminator(&block.terminator.kind, w)?; + writeln!(w, "").unwrap(); writeln!(w, " }}").unwrap(); Ok(()) }) @@ -101,7 +101,7 @@ pub struct LocalDecl { pub mutability: Mutability, } -#[derive(Clone, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct BasicBlock { pub statements: Vec, pub terminator: Terminator, @@ -113,6 +113,14 @@ pub struct Terminator { pub span: Span, } +impl Terminator { + pub fn successors(&self) -> Successors<'_> { + self.kind.successors() + } +} + +pub type Successors<'a> = impl Iterator + 'a; + #[derive(Clone, Debug, Eq, PartialEq)] pub enum TerminatorKind { Goto { @@ -120,7 +128,7 @@ pub enum TerminatorKind { }, SwitchInt { discr: Operand, - targets: Vec, + targets: SwitchTargets, otherwise: usize, }, Resume, @@ -157,6 +165,58 @@ pub enum TerminatorKind { }, } +impl TerminatorKind { + pub fn successors(&self) -> Successors<'_> { + use self::TerminatorKind::*; + match *self { + Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } + | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. } + | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. } + | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => { + Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) + } + Goto { target: t } + | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } + | Call { target: Some(t), unwind: _, .. } + | Drop { target: t, unwind: _, .. } + | Assert { target: t, unwind: _, .. } + | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } + | InlineAsm { destination: Some(t), unwind: _, .. } => { + Some(t).into_iter().chain((&[]).into_iter().copied()) + } + + CoroutineDrop + | Return + | Resume + | Abort + | Unreachable + | Call { target: None, unwind: _, .. } + | InlineAsm { destination: None, unwind: _, .. } => { + None.into_iter().chain((&[]).into_iter().copied()) + } + SwitchInt { ref targets, .. } => { + None.into_iter().chain(targets.targets.iter().copied()) + } + } + } + + pub fn unwind(&self) -> Option<&UnwindAction> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::CoroutineDrop + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::SwitchInt { .. } => None, + TerminatorKind::Call { ref unwind, .. } + | TerminatorKind::Assert { ref unwind, .. } + | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct InlineAsmOperand { pub in_value: Option, @@ -603,9 +663,9 @@ pub struct Constant { } #[derive(Clone, Debug, Eq, PartialEq)] -pub struct SwitchTarget { - pub value: u128, - pub target: usize, +pub struct SwitchTargets { + pub value: Vec, + pub targets: Vec, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 6fa440887427f..ee2237394ca75 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -1,7 +1,9 @@ use crate::crate_def::CrateDef; -use crate::mir::{Operand, Rvalue, StatementKind}; +use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction}; use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy}; use crate::{with, Body, CrateItem, Mutability}; +use std::io::Write; +use std::{io, iter}; use super::{AssertMessage, BinOp, TerminatorKind}; @@ -72,21 +74,68 @@ pub fn pretty_statement(statement: &StatementKind) -> String { pretty } -pub fn pretty_terminator(terminator: &TerminatorKind) -> String { +pub fn pretty_terminator(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> { + write!(w, "{}", pretty_terminator_head(terminator))?; + let successor_count = terminator.successors().count(); + let labels = pretty_successor_labels(terminator); + + let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_))); + let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> { + write!(fmt, "unwind ")?; + match terminator.unwind() { + None | Some(UnwindAction::Cleanup(_)) => unreachable!(), + Some(UnwindAction::Continue) => write!(fmt, "continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"), + Some(UnwindAction::Terminate) => write!(fmt, "terminate"), + } + }; + + match (successor_count, show_unwind) { + (0, false) => Ok(()), + (0, true) => { + write!(w, " -> ")?; + fmt_unwind(w)?; + Ok(()) + } + (1, false) => { + write!(w, " -> {:?}", terminator.successors().next().unwrap())?; + Ok(()) + } + _ => { + write!(w, " -> [")?; + for (i, target) in terminator.successors().enumerate() { + if i > 0 { + write!(w, ", ")?; + } + write!(w, "{}: {:?}", labels[i], target)?; + } + if show_unwind { + write!(w, ", ")?; + fmt_unwind(w)?; + } + write!(w, "]") + } + }?; + + Ok(()) +} + +pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String { + use self::TerminatorKind::*; let mut pretty = String::new(); match terminator { - TerminatorKind::Goto { .. } => format!(" goto"), - TerminatorKind::SwitchInt { discr, .. } => { + Goto { .. } => format!(" goto"), + SwitchInt { discr, .. } => { format!(" switch({})", pretty_operand(discr)) } - TerminatorKind::Resume => format!(" resume"), - TerminatorKind::Abort => format!(" abort"), - TerminatorKind::Return => format!(" return"), - TerminatorKind::Unreachable => format!(" unreachable"), - TerminatorKind::Drop { place, .. } => format!(" drop({:?})", place.local), - TerminatorKind::Call { func, args, destination, .. } => { + Resume => format!(" resume"), + Abort => format!(" abort"), + Return => format!(" return"), + Unreachable => format!(" unreachable"), + Drop { place, .. } => format!(" drop(_{:?})", place.local), + Call { func, args, destination, .. } => { pretty.push_str(" "); - pretty.push_str(format!("{} = ", destination.local).as_str()); + pretty.push_str(format!("_{} = ", destination.local).as_str()); pretty.push_str(&pretty_operand(func)); pretty.push_str("("); args.iter().enumerate().for_each(|(i, arg)| { @@ -98,18 +147,45 @@ pub fn pretty_terminator(terminator: &TerminatorKind) -> String { pretty.push_str(")"); pretty } - TerminatorKind::Assert { cond, expected, msg, target: _, unwind: _ } => { + Assert { cond, expected, msg, target: _, unwind: _ } => { pretty.push_str(" assert("); if !expected { pretty.push_str("!"); } - pretty.push_str(&pretty_operand(cond)); + pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str()); pretty.push_str(&pretty_assert_message(msg)); pretty.push_str(")"); pretty } - TerminatorKind::CoroutineDrop => format!(" coroutine_drop"), - TerminatorKind::InlineAsm { .. } => todo!(), + CoroutineDrop => format!(" coroutine_drop"), + InlineAsm { .. } => todo!(), + } +} + +pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec { + use self::TerminatorKind::*; + match terminator { + Resume | Abort | Return | Unreachable | CoroutineDrop => vec![], + Goto { .. } => vec!["".to_string()], + SwitchInt { targets, .. } => targets + .value + .iter() + .map(|target| format!("{}", target)) + .chain(iter::once("otherwise".into())) + .collect(), + Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()], + Drop { unwind: _, .. } => vec!["return".into()], + Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Call { target: Some(_), unwind: _, .. } => vec!["return".into()], + Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()], + Call { target: None, unwind: _, .. } => vec![], + Assert { unwind: UnwindAction::Cleanup(_), .. } => { + vec!["success".into(), "unwind".into()] + } + Assert { unwind: _, .. } => vec!["success".into()], + InlineAsm { .. } => todo!(), } } From e65c060d78db59c5f21cb13f4ec322e407f0a642 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Wed, 3 May 2023 22:32:52 +0900 Subject: [PATCH 04/14] Detect Python-like slicing and suggest how to fix Fix #108215 --- compiler/rustc_ast/src/token.rs | 5 +++++ compiler/rustc_parse/src/parser/stmt.rs | 16 ++++++++++++++++ .../range-index-instead-of-colon.rs | 8 ++++++++ .../range-index-instead-of-colon.stderr | 18 ++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 tests/ui/suggestions/range-index-instead-of-colon.rs create mode 100644 tests/ui/suggestions/range-index-instead-of-colon.stderr 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_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5316dde609605..94d200188eafb 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -567,6 +567,22 @@ impl<'a> Parser<'a> { snapshot.recover_diff_marker(); } if self.token == token::Colon { + // 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.look_ahead(1, |token| token.is_integer_lit()) + { + // TODO(hkmatsumoto): Might be better to trigger + // this only when parsing an index expression. + err.span_suggestion_verbose( + self.token.span, + "you might have meant to make a slice with range index", + "..", + Applicability::MaybeIncorrect, + ); + } + // if next token is following a colon, it's likely a path // and we can suggest a path separator self.bump(); 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..a5e0098544db3 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -0,0 +1,8 @@ +// edition:2021 + +fn main() { + &[1, 2, 3][1:2]; + //~^ ERROR: expected one of + //~| HELP: you might have meant to make a slice with range index + //~| HELP: maybe write a path separator here +} \ No newline at end of file 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..72e400fba0ac8 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -0,0 +1,18 @@ +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 + | + = note: type ascription syntax has been removed, see issue #101728 +help: you might have meant to make a slice with range index + | +LL | &[1, 2, 3][1..2]; + | ~~ +help: maybe write a path separator here + | +LL | &[1, 2, 3][1::2]; + | ~~ + +error: aborting due to previous error + From 61c3e4d56ecc77899095590d9fd03ffc39e9849e Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Wed, 3 May 2023 22:54:22 +0900 Subject: [PATCH 05/14] Make tidy test happy --- compiler/rustc_parse/src/parser/stmt.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 94d200188eafb..71db5609edc2e 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -573,7 +573,7 @@ impl<'a> Parser<'a> { if self.prev_token.is_integer_lit() && self.look_ahead(1, |token| token.is_integer_lit()) { - // TODO(hkmatsumoto): Might be better to trigger + // FIXME(hkmatsumoto): Might be better to trigger // this only when parsing an index expression. err.span_suggestion_verbose( self.token.span, diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index a5e0098544db3..f183590d2c7a2 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -5,4 +5,4 @@ fn main() { //~^ ERROR: expected one of //~| HELP: you might have meant to make a slice with range index //~| HELP: maybe write a path separator here -} \ No newline at end of file +} From 730d299354f7ef09d8e30609110fc499e0e22d71 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Tue, 16 May 2023 14:53:05 +0900 Subject: [PATCH 06/14] Address review feedbacks Also addressed merge conflicts upon rebasing. --- compiler/rustc_parse/src/parser/stmt.rs | 33 ++++++++++--------- .../range-index-instead-of-colon.rs | 1 - .../range-index-instead-of-colon.stderr | 7 +--- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 71db5609edc2e..391a4777bd944 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -571,6 +571,7 @@ impl<'a> Parser<'a> { // 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 @@ -581,22 +582,22 @@ impl<'a> Parser<'a> { "..", Applicability::MaybeIncorrect, ); - } - - // 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 "); + } 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/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index f183590d2c7a2..0805102de7844 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -4,5 +4,4 @@ fn main() { &[1, 2, 3][1:2]; //~^ ERROR: expected one of //~| HELP: you might have meant to make a slice with range index - //~| HELP: maybe write a path separator here } diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr index 72e400fba0ac8..c7a12e9e4fb15 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.stderr +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -4,15 +4,10 @@ error: expected one of `.`, `?`, `]`, or an operator, found `:` LL | &[1, 2, 3][1:2]; | ^ expected one of `.`, `?`, `]`, or an operator | - = note: type ascription syntax has been removed, see issue #101728 help: you might have meant to make a slice with range index | LL | &[1, 2, 3][1..2]; | ~~ -help: maybe write a path separator here - | -LL | &[1, 2, 3][1::2]; - | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error From acec70de9b0b76cb5b077b030360fa217ccdcdec Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Mon, 27 Nov 2023 22:18:03 +0900 Subject: [PATCH 07/14] Change help message to make some sense in broader context --- compiler/rustc_parse/src/parser/stmt.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 391a4777bd944..620ba4a3cb363 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -578,7 +578,7 @@ impl<'a> Parser<'a> { // this only when parsing an index expression. err.span_suggestion_verbose( self.token.span, - "you might have meant to make a slice with range index", + "you might have meant a range expression", "..", Applicability::MaybeIncorrect, ); diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index 0805102de7844..3267527ecf2a7 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -3,5 +3,5 @@ fn main() { &[1, 2, 3][1:2]; //~^ ERROR: expected one of - //~| HELP: you might have meant to make a slice with range index + //~| 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 index c7a12e9e4fb15..df29356cc16b3 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.stderr +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `:` LL | &[1, 2, 3][1:2]; | ^ expected one of `.`, `?`, `]`, or an operator | -help: you might have meant to make a slice with range index +help: you might have meant a range expression | LL | &[1, 2, 3][1..2]; | ~~ From 7a88458363400cd9c2b827c2a3e28f5ba20392d5 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Thu, 23 Nov 2023 15:01:19 +0700 Subject: [PATCH 08/14] Added linker_arg(s) Linker trait methods for link-arg to be prefixed "-Wl," for cc-like linker args and not verbatim --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 70 ++++++++++--------- .../pass-linker-flags-flavor/Makefile | 8 +++ tests/run-make/pass-linker-flags-flavor/rs.rs | 1 + 4 files changed, 49 insertions(+), 34 deletions(-) create mode 100644 tests/run-make/pass-linker-flags-flavor/Makefile create mode 100644 tests/run-make/pass-linker-flags-flavor/rs.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ac13d61229e05..be895417bbebc 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder; use itertools::Itertools; use std::cell::OnceCell; use std::collections::BTreeSet; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{read, File, OpenOptions}; use std::io::{BufWriter, Write}; use std::ops::Deref; @@ -2527,7 +2527,7 @@ fn add_native_libs_from_crate( NativeLibKind::WasmImportModule => {} NativeLibKind::LinkArg => { if link_static { - cmd.arg(name); + cmd.linker_arg(OsStr::new(name), verbatim); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 4dd688c22345d..f65afd99e39c7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -196,6 +196,14 @@ pub trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} + fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) { + self.linker_args(&[arg], verbatim); + } + fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) { + args.into_iter().for_each(|a| { + self.cmd().arg(a); + }); + } } impl dyn Linker + '_ { @@ -223,38 +231,12 @@ pub struct GccLinker<'a> { } impl<'a> GccLinker<'a> { - /// Passes an argument directly to the linker. - /// - /// When the linker is not ld-like such as when using a compiler as a linker, the argument is - /// prepended by `-Wl,`. - fn linker_arg(&mut self, arg: impl AsRef) -> &mut Self { - self.linker_args(&[arg]); - self + fn linker_arg(&mut self, arg: impl AsRef) { + Linker::linker_arg(self, arg.as_ref(), false); } - - /// Passes a series of arguments directly to the linker. - /// - /// When the linker is ld-like, the arguments are simply appended to the command. When the - /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by - /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a - /// single argument is appended to the command to ensure that the order of the arguments is - /// preserved by the compiler. - fn linker_args(&mut self, args: &[impl AsRef]) -> &mut Self { - if self.is_ld { - args.into_iter().for_each(|a| { - self.cmd.arg(a); - }); - } else { - if !args.is_empty() { - let mut s = OsString::from("-Wl"); - for a in args { - s.push(","); - s.push(a); - } - self.cmd.arg(s); - } - } - self + fn linker_args(&mut self, args: &[impl AsRef]) { + let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect(); + Linker::linker_args(self, &args_vec, false); } fn takes_hints(&self) -> bool { @@ -361,6 +343,30 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { + /// Passes a series of arguments directly to the linker. + /// + /// When the linker is ld-like, the arguments are simply appended to the command. When the + /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by + /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a + /// single argument is appended to the command to ensure that the order of the arguments is + /// preserved by the compiler. + fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) { + if self.is_ld || verbatim { + args.into_iter().for_each(|a| { + self.cmd.arg(a); + }); + } else { + if !args.is_empty() { + let mut s = OsString::from("-Wl"); + for a in args { + s.push(","); + s.push(a); + } + self.cmd.arg(s); + } + } + } + fn cmd(&mut self) -> &mut Command { &mut self.cmd } @@ -531,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> { self.linker_arg("-force_load"); self.linker_arg(&lib); } else { - self.linker_arg("--whole-archive").cmd.arg(lib); + self.linker_args(&[OsString::from("--whole-archive"), lib.into()]); self.linker_arg("--no-whole-archive"); } } diff --git a/tests/run-make/pass-linker-flags-flavor/Makefile b/tests/run-make/pass-linker-flags-flavor/Makefile new file mode 100644 index 0000000000000..bd3d3ed882fbc --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/Makefile @@ -0,0 +1,8 @@ +# only-linux + +include ../tools.mk + +all: + $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=ld -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"' diff --git a/tests/run-make/pass-linker-flags-flavor/rs.rs b/tests/run-make/pass-linker-flags-flavor/rs.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/rs.rs @@ -0,0 +1 @@ +fn main() {} From 31d99836bff1dc3366a8cd370c019a789f193b88 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 27 Nov 2023 18:09:17 +0300 Subject: [PATCH 09/14] QueryContext: rename try_collect_active_jobs -> collect_active_jobs and change it's return type from Option to QueryMap As there currently always Some(...) inside --- compiler/rustc_interface/src/util.rs | 7 ++----- compiler/rustc_query_impl/src/plumbing.rs | 14 +++++++------- compiler/rustc_query_system/src/query/job.rs | 4 ++-- compiler/rustc_query_system/src/query/mod.rs | 2 +- compiler/rustc_query_system/src/query/plumbing.rs | 7 ++----- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index b3ab01a740a95..c9c7ffdd9371f 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -126,11 +126,8 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( .deadlock_handler(|| { // On deadlock, creates a new thread and forwards information in thread // locals to it. The new thread runs the deadlock handler. - let query_map = FromDyn::from(tls::with(|tcx| { - QueryCtxt::new(tcx) - .try_collect_active_jobs() - .expect("active jobs shouldn't be locked in deadlock handler") - })); + let query_map = + FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())); let registry = rayon_core::Registry::current(); thread::spawn(move || deadlock(query_map.into_inner(), ®istry)); }); diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 9faf63f00e27e..acd3d71e63683 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -80,14 +80,14 @@ impl QueryContext for QueryCtxt<'_> { tls::with_related_context(self.tcx, |icx| icx.query) } - fn try_collect_active_jobs(self) -> Option { + fn collect_active_jobs(self) -> QueryMap { let mut jobs = QueryMap::default(); for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() { collect(self.tcx, &mut jobs); } - Some(jobs) + jobs } // Interactions with on_disk_cache @@ -155,11 +155,11 @@ impl QueryContext for QueryCtxt<'_> { fn depth_limit_error(self, job: QueryJobId) { let mut span = None; let mut layout_of_depth = None; - if let Some(map) = self.try_collect_active_jobs() { - if let Some((info, depth)) = job.try_find_layout_root(map, dep_kinds::layout_of) { - span = Some(info.job.span); - layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); - } + if let Some((info, depth)) = + job.try_find_layout_root(self.collect_active_jobs(), dep_kinds::layout_of) + { + span = Some(info.job.span); + layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); } let suggested_limit = match self.recursion_limit() { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index b38d71733b591..2a55ec72c5f70 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -620,13 +620,13 @@ pub fn print_query_stack( // state if it was responsible for triggering the panic. let mut count_printed = 0; let mut count_total = 0; - let query_map = qcx.try_collect_active_jobs(); + let query_map = qcx.collect_active_jobs(); if let Some(ref mut file) = file { let _ = writeln!(file, "\n\nquery stack during panic:"); } while let Some(query) = current_query { - let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else { + let Some(query_info) = query_map.get(&query) else { break; }; if Some(count_printed) < num_frames || num_frames.is_none() { diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 05dee9f12dbdb..96a0c7a033aa1 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -106,7 +106,7 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn try_collect_active_jobs(self) -> Option; + fn collect_active_jobs(self) -> QueryMap; /// Load side effects associated to the node in the previous session. fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index ecbc7dc6b8f4e..2f9f094dae2e0 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -242,11 +242,8 @@ where Q: QueryConfig, Qcx: QueryContext, { - let error = try_execute.find_cycle_in_stack( - qcx.try_collect_active_jobs().unwrap(), - &qcx.current_query_job(), - span, - ); + let error = + try_execute.find_cycle_in_stack(qcx.collect_active_jobs(), &qcx.current_query_job(), span); (mk_cycle(query, qcx, error), None) } From 8221f9c837f46461d2dd6f29a4468b3a0ee4b508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 Nov 2023 21:22:42 +0000 Subject: [PATCH 10/14] Account for `!` arm in tail `match` expr On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful. ``` 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 get's coerced to `()` due to its surrounding expression LL | | } LL | | } | |_____- `match` arms have incompatible types ``` Fix #24157. --- compiler/rustc_hir_typeck/src/_match.rs | 36 ++++++++++++++++++- compiler/rustc_hir_typeck/src/coercion.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 7 ++-- .../src/fn_ctxt/suggestions.rs | 1 - .../match/match-tail-expr-never-type-error.rs | 16 +++++++++ .../match-tail-expr-never-type-error.stderr | 21 +++++++++++ 6 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 tests/ui/match/match-tail-expr-never-type-error.rs create mode 100644 tests/ui/match/match-tail-expr-never-type-error.stderr 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/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`. From 45fc842ed93d206d3923b869eeb1437cd62e0be8 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 27 Nov 2023 18:55:32 +0100 Subject: [PATCH 11/14] rustc_span: Use correct edit distance start length for suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the suggestions can be off-base for non-ASCII identifiers. For example suggesting that `Ok` is a name similar to `读文`. --- compiler/rustc_span/src/edit_distance.rs | 6 +++++- tests/ui/suggestions/non_ascii_ident.rs | 4 ++++ tests/ui/suggestions/non_ascii_ident.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/ui/suggestions/non_ascii_ident.rs create mode 100644 tests/ui/suggestions/non_ascii_ident.stderr 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/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`. From 15f9bab7ba9d242b9a9c30cab799cd23d0c248cb Mon Sep 17 00:00:00 2001 From: ouz-a Date: Mon, 27 Nov 2023 21:26:11 +0300 Subject: [PATCH 12/14] add otherwise into targets --- compiler/rustc_smir/src/rustc_smir/convert/mir.rs | 4 +++- compiler/stable_mir/src/mir/pretty.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 04ae134eaca6e..e9b835f90db24 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -579,8 +579,10 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt { discr: discr.stable(tables), targets: { - let (value_vec, target_vec) = + let (value_vec, mut target_vec): (Vec<_>, Vec<_>) = targets.iter().map(|(value, target)| (value, target.as_usize())).unzip(); + // We need to push otherwise as last element to ensure it's same as in MIR. + target_vec.push(targets.otherwise().as_usize()); stable_mir::mir::SwitchTargets { value: value_vec, targets: target_vec } }, otherwise: targets.otherwise().as_usize(), diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index ee2237394ca75..759c3b148dfef 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -107,7 +107,7 @@ pub fn pretty_terminator(terminator: &TerminatorKind, w: &mut W) - if i > 0 { write!(w, ", ")?; } - write!(w, "{}: {:?}", labels[i], target)?; + write!(w, "{}: bb{:?}", labels[i], target)?; } if show_unwind { write!(w, ", ")?; @@ -126,7 +126,7 @@ pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String { match terminator { Goto { .. } => format!(" goto"), SwitchInt { discr, .. } => { - format!(" switch({})", pretty_operand(discr)) + format!(" switchInt(_{})", pretty_operand(discr)) } Resume => format!(" resume"), Abort => format!(" abort"), From 87380cbc0c967f7ffb714c01e02c48fb6daf6eee Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 25 Nov 2023 15:45:44 -0500 Subject: [PATCH 13/14] Address unused tuple struct fields in the compiler --- compiler/rustc_borrowck/src/lib.rs | 3 ++- compiler/rustc_mir_transform/src/check_unsafety.rs | 6 +++--- compiler/rustc_resolve/src/def_collector.rs | 6 ++---- compiler/rustc_resolve/src/lib.rs | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7d6e15839c508..6e44f44dc18b0 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -42,6 +42,7 @@ use rustc_target::abi::FieldIdx; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; +use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; @@ -100,7 +101,7 @@ use renumber::RegionCtxt; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// Associate some local constants with the `'tcx` lifetime -struct TyCtxtConsts<'tcx>(TyCtxt<'tcx>); +struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); impl<'tcx> TyCtxtConsts<'tcx> { const DEREF_PROJECTION: &'tcx [PlaceElem<'tcx>; 1] = &[ProjectionElem::Deref]; } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 85447887cb0ec..c63b24b194fc2 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -385,7 +385,7 @@ pub(crate) fn provide(providers: &mut Providers) { enum Context { Safe, /// in an `unsafe fn` - UnsafeFn(HirId), + UnsafeFn, /// in a *used* `unsafe` block /// (i.e. a block without unused-unsafe warning) UnsafeBlock(HirId), @@ -407,7 +407,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { }; let unused_unsafe = match (self.context, used) { (_, false) => UnusedUnsafe::Unused, - (Context::Safe, true) | (Context::UnsafeFn(_), true) => { + (Context::Safe, true) | (Context::UnsafeFn, true) => { let previous_context = self.context; self.context = Context::UnsafeBlock(block.hir_id); intravisit::walk_block(self, block); @@ -454,7 +454,7 @@ fn check_unused_unsafe( let body = tcx.hir().body(body_id); let hir_id = tcx.local_def_id_to_hir_id(def_id); let context = match tcx.hir().fn_sig_by_hir_id(hir_id) { - Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn(hir_id), + Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn, _ => Context::Safe, }; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index b1ee7f438d296..c52450e11d642 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -223,7 +223,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // ``` // // In that case, the impl-trait is lowered as an additional generic parameter. - self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { + self.with_impl_trait(ImplTraitContext::Universal, |this| { visit::walk_generic_param(this, param) }); } @@ -310,9 +310,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { if p.is_placeholder { self.visit_macro_invoc(p.id) } else { - self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { - visit::walk_param(this, p) - }) + self.with_impl_trait(ImplTraitContext::Universal, |this| visit::walk_param(this, p)) } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 590bbfc3df1a1..d15e245868325 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -172,7 +172,7 @@ impl<'a> ParentScope<'a> { #[derive(Copy, Debug, Clone)] enum ImplTraitContext { Existential, - Universal(LocalDefId), + Universal, } #[derive(Debug)] From 765a713dff0c4778b4f13f88d597fc351f903030 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 25 Nov 2023 15:45:44 -0500 Subject: [PATCH 14/14] Address unused tuple struct fields in rustdoc --- src/librustdoc/clean/mod.rs | 7 ++----- src/librustdoc/clean/types.rs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) 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 {