Auto merge of #98447 - JohnTitor:rollup-pponoo3, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #91264 (Add macro support in jump to definition feature) - #96955 (Remove (transitive) reliance on sorting by DefId in pretty-printer) - #97633 (Session object: Set OS/ABI) - #98039 (Fix `panic` message for `BTreeSet`'s `range` API and document `panic` cases) - #98214 (rustc_target: Remove some redundant target properties) - #98280 (Improve suggestion for calling fn-like expr on type mismatch) - #98394 (Fixup missing renames from `#[main]` to `#[rustc_main]`) - #98411 (Update tendril) - #98419 (Remove excess rib while resolving closures) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7036449c77
42 changed files with 603 additions and 259 deletions
|
@ -2,7 +2,7 @@
|
|||
pub enum EntryPointType {
|
||||
None,
|
||||
MainNamed,
|
||||
MainAttr,
|
||||
RustcMainAttr,
|
||||
Start,
|
||||
OtherMain, // Not an entry point, but some other function named main
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin
|
|||
if sess.contains_name(&item.attrs, sym::start) {
|
||||
EntryPointType::Start
|
||||
} else if sess.contains_name(&item.attrs, sym::rustc_main) {
|
||||
EntryPointType::MainAttr
|
||||
EntryPointType::RustcMainAttr
|
||||
} else if item.ident.name == sym::main {
|
||||
if depth == 0 {
|
||||
// This is a top-level function so can be 'main'
|
||||
|
@ -177,12 +177,12 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
|||
let item = noop_flat_map_item(i, self).expect_one("noop did something");
|
||||
self.depth -= 1;
|
||||
|
||||
// Remove any #[main] or #[start] from the AST so it doesn't
|
||||
// Remove any #[rustc_main] or #[start] from the AST so it doesn't
|
||||
// clash with the one we're going to add, but mark it as
|
||||
// #[allow(dead_code)] to avoid printing warnings.
|
||||
let item = match entry_point_type(self.sess, &item, self.depth) {
|
||||
EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item
|
||||
.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
|
||||
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
|
||||
item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
|
||||
let allow_ident = Ident::new(sym::allow, self.def_site);
|
||||
let dc_nested =
|
||||
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
|
||||
|
@ -197,7 +197,8 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
|||
.collect();
|
||||
|
||||
ast::Item { id, ident, attrs, kind, vis, span, tokens }
|
||||
}),
|
||||
})
|
||||
}
|
||||
EntryPointType::None | EntryPointType::OtherMain => item,
|
||||
};
|
||||
|
||||
|
|
|
@ -906,7 +906,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
return eh_catch_typeinfo;
|
||||
}
|
||||
let tcx = self.tcx;
|
||||
assert!(self.sess().target.is_like_emscripten);
|
||||
assert!(self.sess().target.os == "emscripten");
|
||||
let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
|
||||
Some(def_id) => self.get_static(def_id),
|
||||
_ => {
|
||||
|
|
|
@ -441,7 +441,7 @@ fn try_intrinsic<'ll>(
|
|||
bx.store(bx.const_i32(0), dest, ret_align);
|
||||
} else if wants_msvc_seh(bx.sess()) {
|
||||
codegen_msvc_try(bx, try_func, data, catch_func, dest);
|
||||
} else if bx.sess().target.is_like_emscripten {
|
||||
} else if bx.sess().target.os == "emscripten" {
|
||||
codegen_emcc_try(bx, try_func, data, catch_func, dest);
|
||||
} else {
|
||||
codegen_gnu_try(bx, try_func, data, catch_func, dest);
|
||||
|
|
|
@ -42,6 +42,6 @@ rustc_target = { path = "../rustc_target" }
|
|||
rustc_session = { path = "../rustc_session" }
|
||||
|
||||
[dependencies.object]
|
||||
version = "0.28.4"
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
|
||||
|
|
|
@ -2031,7 +2031,7 @@ fn add_order_independent_options(
|
|||
|
||||
add_link_script(cmd, sess, tmpdir, crate_type);
|
||||
|
||||
if sess.target.is_like_fuchsia && crate_type == CrateType::Executable {
|
||||
if sess.target.os == "fuchsia" && crate_type == CrateType::Executable {
|
||||
let prefix = if sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
|
||||
"asan/"
|
||||
} else {
|
||||
|
@ -2051,7 +2051,7 @@ fn add_order_independent_options(
|
|||
cmd.no_crt_objects();
|
||||
}
|
||||
|
||||
if sess.target.is_like_emscripten {
|
||||
if sess.target.os == "emscripten" {
|
||||
cmd.arg("-s");
|
||||
cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
|
||||
"DISABLE_EXCEPTION_CATCHING=1"
|
||||
|
|
|
@ -130,7 +130,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||
};
|
||||
|
||||
let mut file = write::Object::new(binary_format, architecture, endianness);
|
||||
match architecture {
|
||||
let e_flags = match architecture {
|
||||
Architecture::Mips => {
|
||||
let arch = match sess.target.options.cpu.as_ref() {
|
||||
"mips1" => elf::EF_MIPS_ARCH_1,
|
||||
|
@ -149,7 +149,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||
if sess.target.options.cpu.contains("r6") {
|
||||
e_flags |= elf::EF_MIPS_NAN2008;
|
||||
}
|
||||
file.flags = FileFlags::Elf { e_flags };
|
||||
e_flags
|
||||
}
|
||||
Architecture::Mips64 => {
|
||||
// copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
|
||||
|
@ -160,17 +160,26 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||
} else {
|
||||
elf::EF_MIPS_ARCH_64R2
|
||||
};
|
||||
file.flags = FileFlags::Elf { e_flags };
|
||||
e_flags
|
||||
}
|
||||
Architecture::Riscv64 if sess.target.options.features.contains("+d") => {
|
||||
// copied from `riscv64-linux-gnu-gcc foo.c -c`, note though
|
||||
// that the `+d` target feature represents whether the double
|
||||
// float abi is enabled.
|
||||
let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE;
|
||||
file.flags = FileFlags::Elf { e_flags };
|
||||
e_flags
|
||||
}
|
||||
_ => {}
|
||||
_ => 0,
|
||||
};
|
||||
// adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
|
||||
let os_abi = match sess.target.options.os.as_ref() {
|
||||
"hermit" => elf::ELFOSABI_STANDALONE,
|
||||
"freebsd" => elf::ELFOSABI_FREEBSD,
|
||||
"solaris" => elf::ELFOSABI_SOLARIS,
|
||||
_ => elf::ELFOSABI_NONE,
|
||||
};
|
||||
let abi_version = 0;
|
||||
file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
|
||||
Some(file)
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,10 @@ impl CStore {
|
|||
CrateNum::new(self.metas.len() - 1)
|
||||
}
|
||||
|
||||
pub fn has_crate_data(&self, cnum: CrateNum) -> bool {
|
||||
self.metas[cnum].is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
|
||||
let cdata = self.metas[cnum]
|
||||
.as_ref()
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::ty::{
|
|||
TypeSuperFoldable,
|
||||
};
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
|
||||
|
@ -779,8 +779,8 @@ pub trait PrettyPrinter<'tcx>:
|
|||
// by looking up the projections associated with the def_id.
|
||||
let bounds = self.tcx().bound_explicit_item_bounds(def_id);
|
||||
|
||||
let mut traits = BTreeMap::new();
|
||||
let mut fn_traits = BTreeMap::new();
|
||||
let mut traits = FxIndexMap::default();
|
||||
let mut fn_traits = FxIndexMap::default();
|
||||
let mut is_sized = false;
|
||||
|
||||
for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
|
||||
|
@ -856,7 +856,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
p!(")");
|
||||
if let Term::Ty(ty) = return_ty.skip_binder() {
|
||||
if !ty.is_unit() {
|
||||
p!("-> ", print(return_ty));
|
||||
p!(" -> ", print(return_ty));
|
||||
}
|
||||
}
|
||||
p!(write("{}", if paren_needed { ")" } else { "" }));
|
||||
|
@ -970,11 +970,11 @@ pub trait PrettyPrinter<'tcx>:
|
|||
&mut self,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
|
||||
traits: &mut BTreeMap<
|
||||
traits: &mut FxIndexMap<
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
BTreeMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
|
||||
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
|
||||
>,
|
||||
fn_traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
|
||||
fn_traits: &mut FxIndexMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
|
||||
) {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
|
||||
|
@ -1110,19 +1110,18 @@ pub trait PrettyPrinter<'tcx>:
|
|||
// Builtin bounds.
|
||||
// FIXME(eddyb) avoid printing twice (needed to ensure
|
||||
// that the auto traits are sorted *and* printed via cx).
|
||||
let mut auto_traits: Vec<_> =
|
||||
predicates.auto_traits().map(|did| (self.tcx().def_path_str(did), did)).collect();
|
||||
let mut auto_traits: Vec<_> = predicates.auto_traits().collect();
|
||||
|
||||
// The auto traits come ordered by `DefPathHash`. While
|
||||
// `DefPathHash` is *stable* in the sense that it depends on
|
||||
// neither the host nor the phase of the moon, it depends
|
||||
// "pseudorandomly" on the compiler version and the target.
|
||||
//
|
||||
// To avoid that causing instabilities in compiletest
|
||||
// To avoid causing instabilities in compiletest
|
||||
// output, sort the auto-traits alphabetically.
|
||||
auto_traits.sort();
|
||||
auto_traits.sort_by_cached_key(|did| self.tcx().def_path_str(*did));
|
||||
|
||||
for (_, def_id) in auto_traits {
|
||||
for def_id in auto_traits {
|
||||
if !first {
|
||||
p!(" + ");
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
|
|||
if ctxt.tcx.sess.contains_name(attrs, sym::start) {
|
||||
EntryPointType::Start
|
||||
} else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) {
|
||||
EntryPointType::MainAttr
|
||||
EntryPointType::RustcMainAttr
|
||||
} else {
|
||||
if let Some(name) = ctxt.tcx.opt_item_name(id.def_id.to_def_id())
|
||||
&& name == sym::main {
|
||||
|
@ -95,7 +95,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
|
|||
EntryPointType::OtherMain => {
|
||||
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
|
||||
}
|
||||
EntryPointType::MainAttr => {
|
||||
EntryPointType::RustcMainAttr => {
|
||||
if ctxt.attr_main_fn.is_none() {
|
||||
ctxt.attr_main_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
|
||||
} else {
|
||||
|
@ -103,13 +103,13 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
|
|||
ctxt.tcx.sess,
|
||||
ctxt.tcx.def_span(id.def_id.to_def_id()),
|
||||
E0137,
|
||||
"multiple functions with a `#[main]` attribute"
|
||||
"multiple functions with a `#[rustc_main]` attribute"
|
||||
)
|
||||
.span_label(
|
||||
ctxt.tcx.def_span(id.def_id.to_def_id()),
|
||||
"additional `#[main]` function",
|
||||
"additional `#[rustc_main]` function",
|
||||
)
|
||||
.span_label(ctxt.attr_main_fn.unwrap().1, "first `#[main]` function")
|
||||
.span_label(ctxt.attr_main_fn.unwrap().1, "first `#[rustc_main]` function")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
|
|||
if items.eh_personality().is_none() {
|
||||
items.missing.push(LangItem::EhPersonality);
|
||||
}
|
||||
if tcx.sess.target.is_like_emscripten && items.eh_catch_typeinfo().is_none() {
|
||||
if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() {
|
||||
items.missing.push(LangItem::EhCatchTypeinfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -3514,7 +3514,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
})
|
||||
});
|
||||
}
|
||||
ExprKind::Async(..) | ExprKind::Closure(..) => {
|
||||
// For closures, ClosureOrAsyncRibKind is added in visit_fn
|
||||
ExprKind::Closure(..) => visit::walk_expr(self, expr),
|
||||
ExprKind::Async(..) => {
|
||||
self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr));
|
||||
}
|
||||
ExprKind::Repeat(ref elem, ref ct) => {
|
||||
|
|
|
@ -74,7 +74,7 @@ impl AArch64InlineAsmRegClass {
|
|||
}
|
||||
|
||||
pub fn target_reserves_x18(target: &Target) -> bool {
|
||||
target.os == "android" || target.is_like_fuchsia || target.is_like_osx || target.is_like_windows
|
||||
target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows
|
||||
}
|
||||
|
||||
fn reserved_x18(
|
||||
|
|
|
@ -28,7 +28,6 @@ pub fn opts() -> TargetOptions {
|
|||
dynamic_linking: true,
|
||||
executables: true,
|
||||
families: cvs!["unix"],
|
||||
is_like_fuchsia: true,
|
||||
pre_link_args,
|
||||
pre_link_objects: crt_objects::new(&[
|
||||
(LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]),
|
||||
|
|
|
@ -1273,12 +1273,6 @@ pub struct TargetOptions {
|
|||
/// - uses SEH-based unwinding,
|
||||
/// - supports control flow guard mechanism.
|
||||
pub is_like_msvc: bool,
|
||||
/// Whether the target toolchain is like Emscripten's. Only useful for compiling with
|
||||
/// Emscripten toolchain.
|
||||
/// Defaults to false.
|
||||
pub is_like_emscripten: bool,
|
||||
/// Whether the target toolchain is like Fuchsia's.
|
||||
pub is_like_fuchsia: bool,
|
||||
/// Whether a target toolchain is like WASM.
|
||||
pub is_like_wasm: bool,
|
||||
/// Version of DWARF to use if not using the default.
|
||||
|
@ -1505,9 +1499,7 @@ impl Default for TargetOptions {
|
|||
is_like_osx: false,
|
||||
is_like_solaris: false,
|
||||
is_like_windows: false,
|
||||
is_like_emscripten: false,
|
||||
is_like_msvc: false,
|
||||
is_like_fuchsia: false,
|
||||
is_like_wasm: false,
|
||||
dwarf_version: None,
|
||||
linker_is_gnu: true,
|
||||
|
@ -2112,8 +2104,6 @@ impl Target {
|
|||
key!(is_like_solaris, bool);
|
||||
key!(is_like_windows, bool);
|
||||
key!(is_like_msvc, bool);
|
||||
key!(is_like_emscripten, bool);
|
||||
key!(is_like_fuchsia, bool);
|
||||
key!(is_like_wasm, bool);
|
||||
key!(dwarf_version, Option<u32>);
|
||||
key!(linker_is_gnu, bool);
|
||||
|
@ -2358,8 +2348,6 @@ impl ToJson for Target {
|
|||
target_option_val!(is_like_solaris);
|
||||
target_option_val!(is_like_windows);
|
||||
target_option_val!(is_like_msvc);
|
||||
target_option_val!(is_like_emscripten);
|
||||
target_option_val!(is_like_fuchsia);
|
||||
target_option_val!(is_like_wasm);
|
||||
target_option_val!(dwarf_version);
|
||||
target_option_val!(linker_is_gnu);
|
||||
|
|
|
@ -8,7 +8,12 @@ pub(super) fn test_target(target: Target) {
|
|||
|
||||
impl Target {
|
||||
fn check_consistency(&self) {
|
||||
assert_eq!(self.is_like_osx, self.vendor == "apple");
|
||||
assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos");
|
||||
assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi");
|
||||
assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
|
||||
assert!(self.is_like_windows || !self.is_like_msvc);
|
||||
|
||||
// Check that LLD with the given flavor is treated identically to the linker it emulates.
|
||||
// If your target really needs to deviate from the rules below, except it and document the
|
||||
// reasons.
|
||||
|
|
|
@ -26,7 +26,6 @@ pub fn target() -> Target {
|
|||
// functionality, and a .wasm file.
|
||||
exe_suffix: ".js".into(),
|
||||
linker: None,
|
||||
is_like_emscripten: true,
|
||||
panic_strategy: PanicStrategy::Unwind,
|
||||
no_default_libraries: false,
|
||||
post_link_args,
|
||||
|
|
|
@ -8,15 +8,14 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::{CtorOf, DefKind};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
Expr, ExprKind, GenericBound, ItemKind, Node, Path, QPath, Stmt, StmtKind, TyKind,
|
||||
WherePredicate,
|
||||
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_infer::infer::{self, TyCtxtInferExt};
|
||||
use rustc_infer::traits;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty};
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
|
||||
|
@ -78,124 +77,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let hir = self.tcx.hir();
|
||||
let (def_id, sig) = match *found.kind() {
|
||||
ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)),
|
||||
ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig()),
|
||||
let (def_id, output, inputs) = match *found.kind() {
|
||||
ty::FnDef(def_id, _) => {
|
||||
let fn_sig = found.fn_sig(self.tcx);
|
||||
(def_id, fn_sig.output(), fn_sig.inputs().skip_binder().len())
|
||||
}
|
||||
ty::Closure(def_id, substs) => {
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
(def_id, fn_sig.output(), fn_sig.inputs().skip_binder().len() - 1)
|
||||
}
|
||||
ty::Opaque(def_id, substs) => {
|
||||
let sig = self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
|
||||
if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder()
|
||||
&& Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
|
||||
// args tuple will always be substs[1]
|
||||
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
|
||||
{
|
||||
Some((
|
||||
pred.kind().rebind(proj.term.ty().unwrap()),
|
||||
args.len(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some((output, inputs)) = sig {
|
||||
(def_id, output, inputs)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let sig = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, sig);
|
||||
let sig = self.normalize_associated_types_in(expr.span, sig);
|
||||
if self.can_coerce(sig.output(), expected) {
|
||||
let (mut sugg_call, applicability) = if sig.inputs().is_empty() {
|
||||
(String::new(), Applicability::MachineApplicable)
|
||||
} else {
|
||||
("...".to_string(), Applicability::HasPlaceholders)
|
||||
let output = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, output);
|
||||
let output = self.normalize_associated_types_in(expr.span, output);
|
||||
if !output.is_ty_var() && self.can_coerce(output, expected) {
|
||||
let (sugg_call, mut applicability) = match inputs {
|
||||
0 => ("".to_string(), Applicability::MachineApplicable),
|
||||
1..=4 => (
|
||||
(0..inputs).map(|_| "_").collect::<Vec<_>>().join(", "),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
_ => ("...".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
let mut msg = "call this function";
|
||||
match hir.get_if_local(def_id) {
|
||||
Some(
|
||||
Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. })
|
||||
| Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(_, body_id), ..
|
||||
})
|
||||
| Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)),
|
||||
..
|
||||
}),
|
||||
) => {
|
||||
let body = hir.body(*body_id);
|
||||
sugg_call = body
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| match ¶m.pat.kind {
|
||||
hir::PatKind::Binding(_, _, ident, None)
|
||||
if ident.name != kw::SelfLower =>
|
||||
{
|
||||
ident.to_string()
|
||||
}
|
||||
_ => "_".to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
let msg = match self.tcx.def_kind(def_id) {
|
||||
DefKind::Fn => "call this function",
|
||||
DefKind::Closure | DefKind::OpaqueTy => "call this closure",
|
||||
DefKind::Ctor(CtorOf::Struct, _) => "instantiate this tuple struct",
|
||||
DefKind::Ctor(CtorOf::Variant, _) => "instantiate this tuple variant",
|
||||
_ => "call this function",
|
||||
};
|
||||
|
||||
let sugg = match expr.kind {
|
||||
hir::ExprKind::Call(..)
|
||||
| hir::ExprKind::Path(..)
|
||||
| hir::ExprKind::Index(..)
|
||||
| hir::ExprKind::Lit(..) => {
|
||||
vec![(expr.span.shrink_to_hi(), format!("({sugg_call})"))]
|
||||
}
|
||||
Some(Node::Expr(hir::Expr {
|
||||
kind: ExprKind::Closure { body: body_id, .. },
|
||||
span: full_closure_span,
|
||||
..
|
||||
})) => {
|
||||
if *full_closure_span == expr.span {
|
||||
return false;
|
||||
}
|
||||
msg = "call this closure";
|
||||
let body = hir.body(*body_id);
|
||||
sugg_call = body
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| match ¶m.pat.kind {
|
||||
hir::PatKind::Binding(_, _, ident, None)
|
||||
if ident.name != kw::SelfLower =>
|
||||
{
|
||||
ident.to_string()
|
||||
}
|
||||
_ => "_".to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
hir::ExprKind::Closure { .. } => {
|
||||
// Might be `{ expr } || { bool }`
|
||||
applicability = Applicability::MaybeIncorrect;
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "(".to_string()),
|
||||
(expr.span.shrink_to_hi(), format!(")({sugg_call})")),
|
||||
]
|
||||
}
|
||||
Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
|
||||
sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
|
||||
match def_id.as_local().map(|def_id| self.tcx.def_kind(def_id)) {
|
||||
Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
|
||||
msg = "instantiate this tuple variant";
|
||||
}
|
||||
Some(DefKind::Ctor(CtorOf::Struct, _)) => {
|
||||
msg = "instantiate this tuple struct";
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "(".to_string()),
|
||||
(expr.span.shrink_to_hi(), format!(")({sugg_call})")),
|
||||
]
|
||||
}
|
||||
Some(Node::ForeignItem(hir::ForeignItem {
|
||||
kind: hir::ForeignItemKind::Fn(_, idents, _),
|
||||
..
|
||||
})) => {
|
||||
sugg_call = idents
|
||||
.iter()
|
||||
.map(|ident| {
|
||||
if ident.name != kw::SelfLower {
|
||||
ident.to_string()
|
||||
} else {
|
||||
"_".to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
Some(Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)),
|
||||
..
|
||||
})) => {
|
||||
sugg_call = idents
|
||||
.iter()
|
||||
.map(|ident| {
|
||||
if ident.name != kw::SelfLower {
|
||||
ident.to_string()
|
||||
} else {
|
||||
"_".to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
&format!("use parentheses to {}", msg),
|
||||
format!("({})", sugg_call),
|
||||
};
|
||||
|
||||
err.multipart_suggestion_verbose(
|
||||
format!("use parentheses to {msg}"),
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue