1
Fork 0

Auto merge of #112681 - GuillaumeGomez:rollup-rwn4086, r=GuillaumeGomez

Rollup of 8 pull requests

Successful merges:

 - #112403 (Prevent `.eh_frame` from being emitted for `-C panic=abort`)
 - #112517 (`suspicious_double_ref_op`: don't lint on `.borrow()`)
 - #112529 (Extend `unused_must_use` to cover block exprs)
 - #112614 (tweak suggestion for argument-position `impl ?Sized`)
 - #112654 (normalize closure output in equate_inputs_and_outputs)
 - #112660 (Migrate GUI colors test to original CSS color format)
 - #112664 (Add support for test tmpdir to fuchsia test runner)
 - #112669 (Fix comment for ptr alignment checks in codegen)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-15 22:54:43 +00:00
commit 0252b4093f
55 changed files with 578 additions and 213 deletions

View file

@ -67,7 +67,7 @@ struct ArenaChunk<T = u8> {
unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> {
fn drop(&mut self) {
unsafe { Box::from_raw(self.storage.as_mut()) };
unsafe { drop(Box::from_raw(self.storage.as_mut())) }
}
}

View file

@ -124,21 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
let output_span = body.local_decls[RETURN_PLACE].source_info.span;
if let Err(terr) = self.eq_types(
normalized_output_ty,
mir_output_ty,
Locations::All(output_span),
ConstraintCategory::BoringNoLocation,
) {
span_mirbug!(
self,
Location::START,
"equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
normalized_output_ty,
mir_output_ty,
terr
);
};
self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
}
#[instrument(skip(self), level = "debug")]

View file

@ -616,7 +616,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
let required = self.codegen_operand(bx, required).immediate();
let found = self.codegen_operand(bx, found).immediate();
// It's `fn panic_bounds_check(index: usize, len: usize)`,
// It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`,
// and `#[track_caller]` adds an implicit third argument.
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
}

View file

@ -479,13 +479,11 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
.label = target type is set here
lint_suspicious_double_ref_op =
using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
*[should_not_happen] [{$op}]
[deref] dereferencing
[borrow] borrowing
[clone] cloning
} the inner type
lint_suspicious_double_ref_clone =
using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type
lint_suspicious_double_ref_deref =
using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
lint_trivial_untranslatable_diag = diagnostic with static strings only

View file

@ -1231,11 +1231,15 @@ pub struct NoopMethodCallDiag<'a> {
}
#[derive(LintDiagnostic)]
#[diag(lint_suspicious_double_ref_op)]
pub struct SuspiciousDoubleRefDiag<'a> {
pub call: Symbol,
#[diag(lint_suspicious_double_ref_deref)]
pub struct SuspiciousDoubleRefDerefDiag<'a> {
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
#[diag(lint_suspicious_double_ref_clone)]
pub struct SuspiciousDoubleRefCloneDiag<'a> {
pub ty: Ty<'a>,
pub op: &'static str,
}
// pass_by_value.rs
@ -1551,8 +1555,29 @@ pub struct UnusedOp<'a> {
pub op: &'a str,
#[label]
pub label: Span,
#[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")]
pub suggestion: Span,
#[subdiagnostic]
pub suggestion: UnusedOpSuggestion,
}
#[derive(Subdiagnostic)]
pub enum UnusedOpSuggestion {
#[suggestion(
lint_suggestion,
style = "verbose",
code = "let _ = ",
applicability = "maybe-incorrect"
)]
NormalExpr {
#[primary_span]
span: Span,
},
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
BlockTailExpr {
#[suggestion_part(code = "let _ = ")]
before_span: Span,
#[suggestion_part(code = ";")]
after_span: Span,
},
}
#[derive(LintDiagnostic)]
@ -1595,15 +1620,25 @@ pub struct UnusedDef<'a, 'b> {
}
#[derive(Subdiagnostic)]
#[suggestion(
lint_suggestion,
style = "verbose",
code = "let _ = ",
applicability = "maybe-incorrect"
)]
pub struct UnusedDefSuggestion {
#[primary_span]
pub span: Span,
pub enum UnusedDefSuggestion {
#[suggestion(
lint_suggestion,
style = "verbose",
code = "let _ = ",
applicability = "maybe-incorrect"
)]
NormalExpr {
#[primary_span]
span: Span,
},
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
BlockTailExpr {
#[suggestion_part(code = "let _ = ")]
before_span: Span,
#[suggestion_part(code = ";")]
after_span: Span,
},
}
// Needed because of def_path_str

View file

@ -1,5 +1,7 @@
use crate::context::LintContext;
use crate::lints::{NoopMethodCallDiag, SuspiciousDoubleRefDiag};
use crate::lints::{
NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag,
};
use crate::LateContext;
use crate::LateLintPass;
use rustc_hir::def::DefKind;
@ -76,22 +78,22 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
// traits and ignore any other method call.
let did = match cx.typeck_results().type_dependent_def(expr.hir_id) {
// Verify we are dealing with a method/associated function.
Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) {
// Check that we're dealing with a trait method for one of the traits we care about.
Some(trait_id)
if matches!(
cx.tcx.get_diagnostic_name(trait_id),
Some(sym::Borrow | sym::Clone | sym::Deref)
) =>
{
did
}
_ => return,
},
_ => return,
let Some((DefKind::AssocFn, did)) =
cx.typeck_results().type_dependent_def(expr.hir_id)
else {
return;
};
let Some(trait_id) = cx.tcx.trait_of_item(did) else { return };
if !matches!(
cx.tcx.get_diagnostic_name(trait_id),
Some(sym::Borrow | sym::Clone | sym::Deref)
) {
return;
};
let substs = cx
.tcx
.normalize_erasing_regions(cx.param_env, cx.typeck_results().node_substs(expr.hir_id));
@ -102,13 +104,6 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
// (Re)check that it implements the noop diagnostic.
let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
let op = match name {
sym::noop_method_borrow => "borrow",
sym::noop_method_clone => "clone",
sym::noop_method_deref => "deref",
_ => return,
};
let receiver_ty = cx.typeck_results().expr_ty(receiver);
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
let arg_adjustments = cx.typeck_results().expr_adjustments(receiver);
@ -129,11 +124,22 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
);
} else {
cx.emit_spanned_lint(
SUSPICIOUS_DOUBLE_REF_OP,
span,
SuspiciousDoubleRefDiag { call: call.ident.name, ty: expr_ty, op },
)
match name {
// If `type_of(x) == T` and `x.borrow()` is used to get `&T`,
// then that should be allowed
sym::noop_method_borrow => return,
sym::noop_method_clone => cx.emit_spanned_lint(
SUSPICIOUS_DOUBLE_REF_OP,
span,
SuspiciousDoubleRefCloneDiag { ty: expr_ty },
),
sym::noop_method_deref => cx.emit_spanned_lint(
SUSPICIOUS_DOUBLE_REF_OP,
span,
SuspiciousDoubleRefDerefDiag { ty: expr_ty },
),
_ => return,
}
}
}
}

View file

@ -1,7 +1,8 @@
use crate::lints::{
PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
UnusedResult,
};
use crate::Lint;
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -93,7 +94,15 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
impl<'tcx> LateLintPass<'tcx> for UnusedResults {
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
let hir::StmtKind::Semi(expr) = s.kind else { return; };
let hir::StmtKind::Semi(mut expr) = s.kind else { return; };
let mut expr_is_from_block = false;
while let hir::ExprKind::Block(blk, ..) = expr.kind
&& let hir::Block { expr: Some(e), .. } = blk
{
expr = e;
expr_is_from_block = true;
}
if let hir::ExprKind::Ret(..) = expr.kind {
return;
@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
expr.span,
"output of future returned by ",
"",
expr_is_from_block,
)
{
// We have a bare `foo().await;` on an opaque type from an async function that was
@ -125,13 +135,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
let type_lint_emitted_or_suppressed = match must_use_result {
Some(path) => {
emit_must_use_untranslated(cx, &path, "", "", 1, false);
emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
true
}
None => false,
};
let fn_warned = check_fn_must_use(cx, expr);
let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);
if !fn_warned && type_lint_emitted_or_suppressed {
// We don't warn about unused unit or uninhabited types.
@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
UnusedOp {
op: must_use_op,
label: expr.span,
suggestion: expr.span.shrink_to_lo(),
suggestion: if expr_is_from_block {
UnusedOpSuggestion::BlockTailExpr {
before_span: expr.span.shrink_to_lo(),
after_span: expr.span.shrink_to_hi(),
}
} else {
UnusedOpSuggestion::NormalExpr { span: expr.span.shrink_to_lo() }
},
},
);
op_warned = true;
@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
}
fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
fn check_fn_must_use(
cx: &LateContext<'_>,
expr: &hir::Expr<'_>,
expr_is_from_block: bool,
) -> bool {
let maybe_def_id = match expr.kind {
hir::ExprKind::Call(ref callee, _) => {
match callee.kind {
@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
_ => None,
};
if let Some(def_id) = maybe_def_id {
check_must_use_def(cx, def_id, expr.span, "return value of ", "")
check_must_use_def(
cx,
def_id,
expr.span,
"return value of ",
"",
expr_is_from_block,
)
} else {
false
}
@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
span: Span,
descr_pre_path: &str,
descr_post_path: &str,
expr_is_from_block: bool,
) -> bool {
is_def_must_use(cx, def_id, span)
.map(|must_use_path| {
@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post_path,
1,
false,
expr_is_from_block,
)
})
.is_some()
@ -373,6 +403,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post: &str,
plural_len: usize,
is_inner: bool,
expr_is_from_block: bool,
) {
let plural_suffix = pluralize!(plural_len);
@ -380,21 +411,51 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
MustUsePath::Suppressed => {}
MustUsePath::Boxed(path) => {
let descr_pre = &format!("{}boxed ", descr_pre);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
}
MustUsePath::Opaque(path) => {
let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
}
MustUsePath::TraitObject(path) => {
let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
}
MustUsePath::TupleElement(elems) => {
for (index, path) in elems {
let descr_post = &format!(" in tuple element {}", index);
emit_must_use_untranslated(
cx, path, descr_pre, descr_post, plural_len, true,
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
}
}
@ -407,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post,
plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
true,
expr_is_from_block,
);
}
MustUsePath::Closure(span) => {
@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx,
def_id: *def_id,
note: *reason,
suggestion: (!is_inner)
.then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }),
suggestion: (!is_inner).then_some(if expr_is_from_block {
UnusedDefSuggestion::BlockTailExpr {
before_span: span.shrink_to_lo(),
after_span: span.shrink_to_hi(),
}
} else {
UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() }
}),
},
);
}

View file

@ -14,8 +14,8 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnostic
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::WherePredicate;
use rustc_span::Span;
use rustc_hir::{PredicateOrigin, WherePredicate};
use rustc_span::{BytePos, Span};
use rustc_type_ir::sty::TyKind::*;
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
@ -156,10 +156,11 @@ enum SuggestChangingConstraintsMessage<'a> {
RestrictBoundFurther,
RestrictType { ty: &'a str },
RestrictTypeFurther { ty: &'a str },
RemovingQSized,
RemoveMaybeUnsized,
ReplaceMaybeUnsizedWithSized,
}
fn suggest_removing_unsized_bound(
fn suggest_changing_unsized_bound(
generics: &hir::Generics<'_>,
suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
param: &hir::GenericParam<'_>,
@ -183,12 +184,25 @@ fn suggest_removing_unsized_bound(
if poly.trait_ref.trait_def_id() != def_id {
continue;
}
let sp = generics.span_for_bound_removal(where_pos, pos);
suggestions.push((
sp,
String::new(),
SuggestChangingConstraintsMessage::RemovingQSized,
));
if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 {
// For `impl ?Sized` with no other bounds, suggest `impl Sized` instead.
let bound_span = bound.span();
if bound_span.can_be_used_for_suggestions() {
let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1));
suggestions.push((
question_span,
String::new(),
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized,
));
}
} else {
let sp = generics.span_for_bound_removal(where_pos, pos);
suggestions.push((
sp,
String::new(),
SuggestChangingConstraintsMessage::RemoveMaybeUnsized,
));
}
}
}
}
@ -238,14 +252,11 @@ pub fn suggest_constraining_type_params<'a>(
{
let mut sized_constraints =
constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
if let Some((constraint, def_id)) = sized_constraints.next() {
if let Some((_, def_id)) = sized_constraints.next() {
applicability = Applicability::MaybeIncorrect;
err.span_label(
param.span,
format!("this type parameter needs to be `{}`", constraint),
);
suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
err.span_label(param.span, "this type parameter needs to be `Sized`");
suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id);
}
}
@ -395,9 +406,12 @@ pub fn suggest_constraining_type_params<'a>(
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
Cow::from(format!("consider further restricting type parameter `{}`", ty))
}
SuggestChangingConstraintsMessage::RemovingQSized => {
SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
}
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
Cow::from("consider replacing `?Sized` with `Sized`")
}
};
err.span_suggestion_verbose(span, msg, suggestion, applicability);

View file

@ -9,6 +9,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut};
use rustc_session::Session;
use rustc_target::spec::PanicStrategy;
pub struct CheckAlignment;
@ -236,7 +237,11 @@ fn insert_alignment_check<'tcx>(
required: Operand::Copy(alignment),
found: Operand::Copy(addr),
}),
unwind: UnwindAction::Terminate,
unwind: if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
UnwindAction::Terminate
} else {
UnwindAction::Unreachable
},
},
});
}