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 6 pull requests #135277

Merged
merged 14 commits into from
Jan 9, 2025
Merged
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
14 changes: 13 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_ast::token::CommentKind;
use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
use rustc_ast::{
self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
};
pub use rustc_ast::{
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
Expand Down Expand Up @@ -2094,6 +2094,18 @@ impl Expr<'_> {
}
}

/// Check if expression is an integer literal that can be used
/// where `usize` is expected.
pub fn is_size_lit(&self) -> bool {
matches!(
self.kind,
ExprKind::Lit(Lit {
node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
..
})
)
}

/// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
/// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
/// silent, only signaling the ownership system. By doing this, suggestions that check the
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this ret
hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it
hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon

hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr}

hir_typeck_return_stmt_outside_of_fn_body =
{$statement_kind} statement outside of function body
.encl_body_label = the {$statement_kind} is part of this body...
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if expr_ty == expected {
return;
}

self.annotate_alternative_method_deref(err, expr, error);
self.explain_self_literal(err, expr, expected, expr_ty);

Expand All @@ -39,6 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
|| self.suggest_remove_last_method_call(err, expr, expected)
|| self.suggest_associated_const(err, expr, expected)
|| self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
|| self.suggest_option_to_bool(err, expr, expr_ty, expected)
|| self.suggest_compatible_variants(err, expr, expected, expr_ty)
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,16 @@ pub(crate) struct PassFnItemToVariadicFunction {
pub sugg_span: Span,
pub replace: String,
}

#[derive(Subdiagnostic)]
#[suggestion(
hir_typeck_replace_comma_with_semicolon,
applicability = "machine-applicable",
style = "verbose",
code = "; "
)]
pub(crate) struct ReplaceCommaWithSemicolon {
#[primary_span]
pub comma_span: Span,
pub descr: &'static str,
}
90 changes: 82 additions & 8 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1320,14 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let span = expr.span.shrink_to_hi();
let subdiag = if self.type_is_copy_modulo_regions(self.param_env, ty) {
errors::OptionResultRefMismatch::Copied { span, def_path }
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
self,
self.param_env,
ty,
clone_did,
)
{
} else if self.type_is_clone_modulo_regions(self.param_env, ty) {
errors::OptionResultRefMismatch::Cloned { span, def_path }
} else {
return false;
Expand Down Expand Up @@ -2182,6 +2175,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// Suggest replacing comma with semicolon in incorrect repeat expressions
/// like `["_", 10]` or `vec![String::new(), 10]`.
pub(crate) fn suggest_semicolon_in_repeat_expr(
&self,
err: &mut Diag<'_>,
expr: &hir::Expr<'_>,
expr_ty: Ty<'tcx>,
) -> bool {
// Check if `expr` is contained in array of two elements
if let hir::Node::Expr(array_expr) = self.tcx.parent_hir_node(expr.hir_id)
&& let hir::ExprKind::Array(elements) = array_expr.kind
&& let [first, second] = &elements[..]
&& second.hir_id == expr.hir_id
{
// Span between the two elements of the array
let comma_span = first.span.between(second.span);

// Check if `expr` is a constant value of type `usize`.
// This can only detect const variable declarations and
// calls to const functions.

// Checking this here instead of rustc_hir::hir because
// this check needs access to `self.tcx` but rustc_hir
// has no access to `TyCtxt`.
let expr_is_const_usize = expr_ty.is_usize()
&& match expr.kind {
ExprKind::Path(QPath::Resolved(
None,
Path { res: Res::Def(DefKind::Const, _), .. },
)) => true,
ExprKind::Call(
Expr {
kind:
ExprKind::Path(QPath::Resolved(
None,
Path { res: Res::Def(DefKind::Fn, fn_def_id), .. },
)),
..
},
_,
) => self.tcx.is_const_fn(*fn_def_id),
_ => false,
};

// Type of the first element is guaranteed to be checked
// when execution reaches here because `mismatched types`
// error occurs only when type of second element of array
// is not the same as type of first element.
let first_ty = self.typeck_results.borrow().expr_ty(first);

// `array_expr` is from a macro `vec!["a", 10]` if
// 1. array expression's span is imported from a macro
// 2. first element of array implements `Clone` trait
// 3. second element is an integer literal or is an expression of `usize` like type
if self.tcx.sess.source_map().is_imported(array_expr.span)
&& self.type_is_clone_modulo_regions(self.param_env, first_ty)
&& (expr.is_size_lit() || expr_ty.is_usize_like())
{
err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
comma_span,
descr: "a vector",
});
return true;
}

// `array_expr` is from an array `["a", 10]` if
// 1. first element of array implements `Copy` trait
// 2. second element is an integer literal or is a const value of type `usize`
if self.type_is_copy_modulo_regions(self.param_env, first_ty)
&& (expr.is_size_lit() || expr_is_const_usize)
{
err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
comma_span,
descr: "an array",
});
return true;
}
}
false
}

/// If the expected type is an enum (Issue #55250) with any variants whose
/// sole field is of the found type, suggest such variants. (Issue #42764)
pub(crate) fn suggest_compatible_variants(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `arg` is
/// typically obtained via the second field of [`TyKind::Adt`].
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).instantiate(tcx, arg)
pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).instantiate(tcx, args)
}

/// Computes the `Ident` of this variant by looking up the `Span`
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::infer::canonical::Canonical;
use crate::ty::InferTy::*;
use crate::ty::{
self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor,
Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
};

// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
Expand Down Expand Up @@ -1017,6 +1017,18 @@ impl<'tcx> Ty<'tcx> {
}
}

/// Check if type is an `usize`.
#[inline]
pub fn is_usize(self) -> bool {
matches!(self.kind(), Uint(UintTy::Usize))
}

/// Check if type is an `usize` or an integral type variable.
#[inline]
pub fn is_usize_like(self) -> bool {
matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
}

#[inline]
pub fn is_never(self) -> bool {
matches!(self.kind(), Never)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
}
}

// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
// the old solver, for as long as that exists.
pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
cx: I,
self_ty: I::Ty,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1812,9 +1812,11 @@ supported_targets! {
("aarch64-unknown-illumos", aarch64_unknown_illumos),

("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
("i686-pc-windows-gnu", i686_pc_windows_gnu),
("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
("i686-win7-windows-gnu", i686_win7_windows_gnu),

("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
Expand Down
35 changes: 35 additions & 0 deletions compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};

pub(crate) fn target() -> Target {
let mut base = base::windows_gnu::opts();
base.vendor = "win7".into();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
base.frame_pointer = FramePointer::Always; // Required for backtraces
base.linker = Some("i686-w64-mingw32-gcc".into());

// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
"-m",
"i386pe",
"--large-address-aware",
]);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,--large-address-aware"]);

Target {
llvm_target: "i686-pc-windows-gnu".into(),
metadata: crate::spec::TargetMetadata {
description: Some("32-bit MinGW (Windows 7+)".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(true),
},
pointer_width: 32,
data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
.into(),
arch: "x86".into(),
options: base,
}
}
32 changes: 32 additions & 0 deletions compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};

pub(crate) fn target() -> Target {
let mut base = base::windows_gnu::opts();
base.vendor = "win7".into();
base.cpu = "x86-64".into();
base.plt_by_default = false;
// Use high-entropy 64 bit address space for ASLR
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
"-m",
"i386pep",
"--high-entropy-va",
]);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
base.max_atomic_width = Some(64);
base.linker = Some("x86_64-w64-mingw32-gcc".into());

Target {
llvm_target: "x86_64-pc-windows-gnu".into(),
metadata: crate::spec::TargetMetadata {
description: Some("64-bit MinGW (Windows 7+)".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(true),
},
pointer_width: 64,
data_layout:
"e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
arch: "x86_64".into(),
options: base,
}
}
6 changes: 6 additions & 0 deletions compiler/rustc_trait_selection/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ impl<'tcx> InferCtxt<'tcx> {
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
}

fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
let ty = self.resolve_vars_if_possible(ty);
let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, None);
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id)
}

fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
Expand Down
Loading
Loading