Skip to content

Commit

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

Rollup of 11 pull requests

Successful merges:

 - rust-lang#111505 (Made `INVALID_DOC_ATTRIBUTES` lint deny by default)
 - rust-lang#120305 (Delete line if suggestion would replace it with an empty line)
 - rust-lang#121153 (Suggest removing superfluous semicolon when statements used as expression)
 - rust-lang#121497 (`-Znext-solver=coherence`: suggest increasing recursion limit)
 - rust-lang#121634 (Clarify behavior of slice prefix/suffix operations in case of equality)
 - rust-lang#121706 (match lowering: Remove hacky branch in sort_candidate)
 - rust-lang#121730 (Add profiling support to AIX)
 - rust-lang#121750 (match lowering: Separate the `bool` case from other integers in `TestKind`)
 - rust-lang#121803 (Never say "`Trait` is implemented for `{type error}`")
 - rust-lang#121811 (Move sanitizer ui tests to sanitizer directory)
 - rust-lang#121824 (Implement missing ABI structures in StableMIR)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 2, 2024
2 parents e612d07 + 63e916e commit eaee1e9
Show file tree
Hide file tree
Showing 137 changed files with 1,165 additions and 708 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Expand Up @@ -1631,7 +1631,9 @@ impl<'a> Linker for AixLinker<'a> {

fn optimize(&mut self) {}

fn pgo_gen(&mut self) {}
fn pgo_gen(&mut self) {
self.cmd.arg("-bdbg:namedsects:ss");
}

fn control_flow_guard(&mut self) {}

Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_errors/src/json.rs
Expand Up @@ -428,14 +428,24 @@ impl DiagnosticSpan {
}

fn from_span_full(
span: Span,
mut span: Span,
is_primary: bool,
label: Option<String>,
suggestion: Option<(&String, Applicability)>,
mut backtrace: impl Iterator<Item = ExpnData>,
je: &JsonEmitter,
) -> DiagnosticSpan {
let start = je.sm.lookup_char_pos(span.lo());
// If this goes from the start of a line to the end and the replacement
// is an empty string, increase the length to include the newline so we don't
// leave an empty line
if start.col.0 == 0
&& suggestion.map_or(false, |(s, _)| s.is_empty())
&& let Ok(after) = je.sm.span_to_next_source(span)
&& after.starts_with('\n')
{
span = span.with_hi(span.hi() + rustc_span::BytePos(1));
}
let end = je.sm.lookup_char_pos(span.hi());
let backtrace_step = backtrace.next().map(|bt| {
let call_site = Self::from_span_full(bt.call_site, false, None, None, backtrace, je);
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Expand Up @@ -1744,7 +1744,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_unit(self.tcx),
);
}
if !self.consider_removing_semicolon(blk, expected_ty, err) {
if !self.err_ctxt().consider_removing_semicolon(
blk,
expected_ty,
err,
) {
self.err_ctxt().consider_returning_binding(
blk,
expected_ty,
Expand Down
41 changes: 1 addition & 40 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Expand Up @@ -22,7 +22,7 @@ use rustc_hir::{
Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
};
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_infer::traits::{self};
use rustc_middle::lint::in_external_macro;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::print::with_no_trimmed_paths;
Expand Down Expand Up @@ -1791,45 +1791,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// A common error is to add an extra semicolon:
///
/// ```compile_fail,E0308
/// fn foo() -> usize {
/// 22;
/// }
/// ```
///
/// This routine checks if the final statement in a block is an
/// expression with an explicit semicolon whose type is compatible
/// with `expected_ty`. If so, it suggests removing the semicolon.
pub(crate) fn consider_removing_semicolon(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diag<'_>,
) -> bool {
if let Some((span_semi, boxed)) = self.err_ctxt().could_remove_semicolon(blk, expected_ty) {
if let StatementAsExpression::NeedsBoxing = boxed {
err.span_suggestion_verbose(
span_semi,
"consider removing this semicolon and boxing the expression",
"",
Applicability::HasPlaceholders,
);
} else {
err.span_suggestion_short(
span_semi,
"remove this semicolon to return this value",
"",
Applicability::MachineApplicable,
);
}
true
} else {
false
}
}

pub(crate) fn is_field_suggestable(
&self,
field: &ty::FieldDef,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Expand Up @@ -1989,6 +1989,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
self.suggest_function_pointers(cause, span, &exp_found, diag);
self.suggest_turning_stmt_into_expr(cause, &exp_found, diag);
}
}

Expand Down
96 changes: 96 additions & 0 deletions compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -1,8 +1,13 @@
use crate::infer::error_reporting::hir::Path;
use hir::def::CtorKind;
use hir::intravisit::{walk_expr, walk_stmt, Visitor};
use hir::{Local, QPath};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::MatchSource;
use rustc_hir::Node;
use rustc_middle::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
StatementAsExpression,
Expand Down Expand Up @@ -293,6 +298,97 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}

pub(super) fn suggest_turning_stmt_into_expr(
&self,
cause: &ObligationCause<'tcx>,
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
diag: &mut Diag<'_>,
) {
let ty::error::ExpectedFound { expected, found } = exp_found;
if !found.peel_refs().is_unit() {
return;
}

let ObligationCauseCode::BlockTailExpression(hir_id, MatchSource::Normal) = cause.code()
else {
return;
};

let node = self.tcx.hir_node(*hir_id);
let mut blocks = vec![];
if let hir::Node::Block(block) = node
&& let Some(expr) = block.expr
&& let hir::ExprKind::Path(QPath::Resolved(_, Path { res, .. })) = expr.kind
&& let Res::Local(local) = res
&& let Node::Local(Local { init: Some(init), .. }) = self.tcx.parent_hir_node(*local)
{
fn collect_blocks<'hir>(expr: &hir::Expr<'hir>, blocks: &mut Vec<&hir::Block<'hir>>) {
match expr.kind {
// `blk1` and `blk2` must be have the same types, it will be reported before reaching here
hir::ExprKind::If(_, blk1, Some(blk2)) => {
collect_blocks(blk1, blocks);
collect_blocks(blk2, blocks);
}
hir::ExprKind::Match(_, arms, _) => {
// all arms must have same types
for arm in arms.iter() {
collect_blocks(arm.body, blocks);
}
}
hir::ExprKind::Block(blk, _) => {
blocks.push(blk);
}
_ => {}
}
}
collect_blocks(init, &mut blocks);
}

let expected_inner: Ty<'_> = expected.peel_refs();
for block in blocks.iter() {
self.consider_removing_semicolon(block, expected_inner, diag);
}
}

/// A common error is to add an extra semicolon:
///
/// ```compile_fail,E0308
/// fn foo() -> usize {
/// 22;
/// }
/// ```
///
/// This routine checks if the final statement in a block is an
/// expression with an explicit semicolon whose type is compatible
/// with `expected_ty`. If so, it suggests removing the semicolon.
pub fn consider_removing_semicolon(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
diag: &mut Diag<'_>,
) -> bool {
if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
if let StatementAsExpression::NeedsBoxing = boxed {
diag.span_suggestion_verbose(
span_semi,
"consider removing this semicolon and boxing the expression",
"",
Applicability::HasPlaceholders,
);
} else {
diag.span_suggestion_short(
span_semi,
"remove this semicolon to return this value",
"",
Applicability::MachineApplicable,
);
}
true
} else {
false
}
}

pub(super) fn suggest_function_pointers(
&self,
cause: &ObligationCause<'tcx>,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_infer/src/traits/mod.rs
Expand Up @@ -135,16 +135,18 @@ pub struct FulfillmentError<'tcx> {

#[derive(Clone)]
pub enum FulfillmentErrorCode<'tcx> {
/// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented.
/// Inherently impossible to fulfill; this trait is implemented if and only
/// if it is already implemented.
Cycle(Vec<PredicateObligation<'tcx>>),
SelectionError(SelectionError<'tcx>),
ProjectionError(MismatchedProjectionTypes<'tcx>),
SubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
ConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
Ambiguity {
/// Overflow reported from the new solver `-Znext-solver`, which will
/// be reported as an regular error as opposed to a fatal error.
overflow: bool,
/// Overflow is only `Some(suggest_recursion_limit)` when using the next generation
/// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by
/// emitting a fatal error instead.
overflow: Option<bool>,
},
}

Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_infer/src/traits/structural_impls.rs
Expand Up @@ -47,8 +47,10 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
ConstEquateError(ref a, ref b) => {
write!(f, "CodeConstEquateError({a:?}, {b:?})")
}
Ambiguity { overflow: false } => write!(f, "Ambiguity"),
Ambiguity { overflow: true } => write!(f, "Overflow"),
Ambiguity { overflow: None } => write!(f, "Ambiguity"),
Ambiguity { overflow: Some(suggest_increasing_limit) } => {
write!(f, "Overflow({suggest_increasing_limit})")
}
Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
}
}
Expand Down
11 changes: 1 addition & 10 deletions compiler/rustc_lint_defs/src/builtin.rs
Expand Up @@ -3586,18 +3586,9 @@ declare_lint! {
/// being validated. Usually these should be rejected as a hard error,
/// but this lint was introduced to avoid breaking any existing
/// crates which included them.
///
/// This is a [future-incompatible] lint to transition this to a hard
/// error in the future. See [issue #82730] for more details.
///
/// [issue #82730]: https://github.com/rust-lang/rust/issues/82730
pub INVALID_DOC_ATTRIBUTES,
Warn,
Deny,
"detects invalid `#[doc(...)]` attributes",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #82730 <https://github.com/rust-lang/rust/issues/82730>",
};
}

declare_lint! {
Expand Down
30 changes: 20 additions & 10 deletions compiler/rustc_middle/src/traits/solve.rs
Expand Up @@ -60,7 +60,6 @@ pub enum Certainty {

impl Certainty {
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
pub const OVERFLOW: Certainty = Certainty::Maybe(MaybeCause::Overflow);

/// Use this function to merge the certainty of multiple nested subgoals.
///
Expand All @@ -79,16 +78,13 @@ impl Certainty {
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
(Certainty::Yes, Certainty::Maybe(_)) => other,
(Certainty::Maybe(_), Certainty::Yes) => self,
(Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(MaybeCause::Ambiguity)) => {
Certainty::Maybe(MaybeCause::Ambiguity)
}
(Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(MaybeCause::Overflow))
| (Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Ambiguity))
| (Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Overflow)) => {
Certainty::Maybe(MaybeCause::Overflow)
}
(Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.unify_with(b)),
}
}

pub const fn overflow(suggest_increasing_limit: bool) -> Certainty {
Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit })
}
}

/// Why we failed to evaluate a goal.
Expand All @@ -99,7 +95,21 @@ pub enum MaybeCause {
/// or we hit a case where we just don't bother, e.g. `?x: Trait` goals.
Ambiguity,
/// We gave up due to an overflow, most often by hitting the recursion limit.
Overflow,
Overflow { suggest_increasing_limit: bool },
}

impl MaybeCause {
fn unify_with(self, other: MaybeCause) -> MaybeCause {
match (self, other) {
(MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity,
(MaybeCause::Ambiguity, MaybeCause::Overflow { .. }) => other,
(MaybeCause::Overflow { .. }, MaybeCause::Ambiguity) => self,
(
MaybeCause::Overflow { suggest_increasing_limit: a },
MaybeCause::Overflow { suggest_increasing_limit: b },
) => MaybeCause::Overflow { suggest_increasing_limit: a || b },
}
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
Expand Down
17 changes: 7 additions & 10 deletions compiler/rustc_mir_build/src/build/matches/mod.rs
Expand Up @@ -1097,21 +1097,18 @@ enum TestKind<'tcx> {
variants: BitSet<VariantIdx>,
},

/// Test what value an integer, `bool`, or `char` has.
/// Test what value an integer or `char` has.
SwitchInt {
/// The type of the value that we're testing.
switch_ty: Ty<'tcx>,
/// The (ordered) set of values that we test for.
///
/// For integers and `char`s we create a branch to each of the values in
/// `options`, as well as an "otherwise" branch for all other values, even
/// in the (rare) case that `options` is exhaustive.
///
/// For `bool` we always generate two edges, one for `true` and one for
/// `false`.
/// We create a branch to each of the values in `options`, as well as an "otherwise" branch
/// for all other values, even in the (rare) case that `options` is exhaustive.
options: FxIndexMap<Const<'tcx>, u128>,
},

/// Test what value a `bool` has.
If,

/// Test for equality with value, possibly after an unsizing coercion to
/// `ty`,
Eq {
Expand Down Expand Up @@ -1617,7 +1614,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// a test like SwitchInt, we may want to add cases based on the candidates that are
// available
match test.kind {
TestKind::SwitchInt { switch_ty: _, ref mut options } => {
TestKind::SwitchInt { ref mut options } => {
for candidate in candidates.iter() {
if !self.add_cases_to_switch(&match_place, candidate, options) {
break;
Expand Down

0 comments on commit eaee1e9

Please sign in to comment.