Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #129254

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ pub struct LetExpr<'hir> {
pub pat: &'hir Pat<'hir>,
pub ty: Option<&'hir Ty<'hir>>,
pub init: &'hir Expr<'hir>,
/// `Recovered::Yes` when this let expressions is not in a syntanctically valid location.
/// `Recovered::Yes` when this let expressions is not in a syntactically valid location.
/// Used to prevent building MIR in such situations.
pub recovered: ast::Recovered,
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,9 @@ passes_macro_export_on_decl_macro =
passes_macro_use =
`#[{$name}]` only has an effect on `extern crate` and modules

passes_may_dangle =
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl

passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
passes_missing_const_err =
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
Expand Down Expand Up @@ -475,8 +478,8 @@ passes_multiple_start_functions =
.previous = previous `#[start]` function here

passes_must_not_suspend =
`must_not_suspend` attribute should be applied to a struct, enum, or trait
.label = is not a struct, enum, or trait
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
.label = is not a struct, enum, union, or trait

passes_must_use_async =
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
Expand Down
25 changes: 23 additions & 2 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
[sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr),
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
[sym::rustc_allow_incoherent_impl, ..] => {
self.check_allow_incoherent_impl(attr, span, target)
Expand Down Expand Up @@ -255,7 +256,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::cfg_attr
// need to be fixed
| sym::cfi_encoding // FIXME(cfi_encoding)
| sym::may_dangle // FIXME(dropck_eyepatch)
| sym::pointee // FIXME(derive_smart_pointer)
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
| sym::used // handled elsewhere to restrict to static items
Expand Down Expand Up @@ -1363,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

/// Checks if `#[must_not_suspend]` is applied to a function.
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Struct | Target::Enum | Target::Union | Target::Trait => {}
Expand All @@ -1373,6 +1373,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

/// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) {
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
&& matches!(
param.kind,
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
)
&& matches!(param.source, hir::GenericParamSource::Generics)
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
&& let hir::ItemKind::Impl(impl_) = item.kind
&& let Some(trait_) = impl_.of_trait
&& let Some(def_id) = trait_.trait_def_id()
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
{
return;
}

self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span });
}

/// Checks if `#[cold]` is applied to a non-function.
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,13 @@ pub struct NonExportedMacroInvalidAttrs {
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_may_dangle)]
pub struct InvalidMayDangle {
#[primary_span]
pub attr_span: Span,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_duplicate)]
pub struct UnusedDuplicate {
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
pub fn make_indirect(&mut self) {
match self.mode {
PassMode::Direct(_) | PassMode::Pair(_, _) => {
self.mode = Self::indirect_pass_mode(&self.layout);
self.make_indirect_force();
}
PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
// already indirect
Expand All @@ -652,6 +652,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
}
}

/// Same as make_indirect, but doesn't check the current `PassMode`.
pub fn make_indirect_force(&mut self) {
self.mode = Self::indirect_pass_mode(&self.layout);
}

/// Pass this argument indirectly, by placing it at a fixed stack offset.
/// This corresponds to the `byval` LLVM argument attribute.
/// This is only valid for sized arguments.
Expand Down Expand Up @@ -871,10 +876,10 @@ impl<'a, Ty> FnAbi<'a, Ty> {
}
"x86_64" => match abi {
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(cx, self),
_ => {
if cx.target_spec().is_like_windows {
x86_win64::compute_abi_info(self)
x86_win64::compute_abi_info(cx, self)
} else {
x86_64::compute_abi_info(cx, self)
}
Expand All @@ -898,7 +903,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
"csky" => csky::compute_abi_info(self),
"mips" | "mips32r6" => mips::compute_abi_info(cx, self),
"mips64" | "mips64r6" => mips64::compute_abi_info(cx, self),
"powerpc" => powerpc::compute_abi_info(self),
"powerpc" => powerpc::compute_abi_info(cx, self),
"powerpc64" => powerpc64::compute_abi_info(cx, self),
"s390x" => s390x::compute_abi_info(cx, self),
"msp430" => msp430::compute_abi_info(self),
Expand Down
20 changes: 14 additions & 6 deletions compiler/rustc_target/src/abi/call/powerpc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::abi::call::{ArgAbi, FnAbi};
use crate::spec::HasTargetSpec;

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if ret.layout.is_aggregate() {
Expand All @@ -8,23 +9,30 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
}
}

fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
fn classify_arg<Ty>(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) {
if arg.is_ignore() {
// powerpc-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
if cx.target_spec().os == "linux"
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
&& arg.layout.is_zst()
{
arg.make_indirect_force();
}
return;
}
if arg.layout.is_aggregate() {
arg.make_indirect();
} else {
arg.extend_integer_width_to(32);
}
}

pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
}

for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
continue;
}
classify_arg(arg);
classify_arg(cx, arg);
}
}
18 changes: 13 additions & 5 deletions compiler/rustc_target/src/abi/call/s390x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use crate::abi::call::{ArgAbi, FnAbi, Reg};
use crate::abi::{HasDataLayout, TyAbiInterface};
use crate::spec::HasTargetSpec;

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
Expand All @@ -15,12 +16,22 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if arg.is_ignore() {
// s390x-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
if cx.target_spec().os == "linux"
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
&& arg.layout.is_zst()
{
arg.make_indirect_force();
}
return;
}
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
arg.extend_integer_width_to(64);
return;
Expand All @@ -46,16 +57,13 @@ where
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
}

for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
continue;
}
classify_arg(cx, arg);
}
}
12 changes: 10 additions & 2 deletions compiler/rustc_target/src/abi/call/sparc64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::abi::call::{
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
};
use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
use crate::spec::HasTargetSpec;

#[derive(Clone, Debug)]
pub struct Sdata {
Expand Down Expand Up @@ -211,15 +212,22 @@ where
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !fn_abi.ret.is_ignore() {
classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32));
}

for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
continue;
// sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
if cx.target_spec().os == "linux"
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
&& arg.layout.is_zst()
{
arg.make_indirect_force();
}
return;
}
classify_arg(cx, arg, Size::from_bytes(16));
}
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_target/src/abi/call/x86_win64.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::abi::call::{ArgAbi, FnAbi, Reg};
use crate::abi::{Abi, Float, Primitive};
use crate::spec::HasTargetSpec;

// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing

pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
let fixup = |a: &mut ArgAbi<'_, Ty>| {
match a.layout.abi {
Abi::Uninhabited | Abi::Aggregate { sized: false } => {}
Expand Down Expand Up @@ -37,6 +38,13 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
}
for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
// x86_64-pc-windows-gnu doesn't ignore ZSTs.
if cx.target_spec().os == "windows"
&& cx.target_spec().env == "gnu"
&& arg.layout.is_zst()
{
arg.make_indirect_force();
}
continue;
}
fixup(arg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4610,6 +4610,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}

// For E0277 when use `?` operator, suggest adding
// a suitable return type in `FnSig`, and a default
// return value at the end of the function's body.
pub(super) fn suggest_add_result_as_return_type(
&self,
obligation: &PredicateObligation<'tcx>,
Expand All @@ -4620,19 +4623,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return;
}

// Only suggest for local function and associated method,
// because this suggest adding both return type in
// the `FnSig` and a default return value in the body, so it
// is not suitable for foreign function without a local body,
// and neighter for trait method which may be also implemented
// in other place, so shouldn't change it's FnSig.
fn choose_suggest_items<'tcx, 'hir>(
tcx: TyCtxt<'tcx>,
node: hir::Node<'hir>,
) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
match node {
hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => {
Some((sig.decl, body_id))
}
hir::Node::ImplItem(item)
if let hir::ImplItemKind::Fn(sig, body_id) = item.kind =>
{
let parent = tcx.parent_hir_node(item.hir_id());
if let hir::Node::Item(item) = parent
&& let hir::ItemKind::Impl(imp) = item.kind
&& imp.of_trait.is_none()
{
return Some((sig.decl, body_id));
}
None
}
_ => None,
}
}

let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
if let hir::Node::Item(item) = node
&& let hir::ItemKind::Fn(sig, _, body_id) = item.kind
&& let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output
if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node)
&& let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output
&& self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
&& trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
&& let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
&& self.tcx.is_diagnostic_item(sym::Result, def.did())
{
let body = self.tcx.hir().body(body_id);
let mut sugg_spans =
vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())];

let body = self.tcx.hir().body(body_id);
if let hir::ExprKind::Block(b, _) = body.value.kind
&& b.expr.is_none()
{
Expand Down
Loading
Loading