Auto merge of #96087 - Dylan-DPC:rollup-k6yzk55, r=Dylan-DPC

Rollup of 11 pull requests

Successful merges:

 - #94457 (Stabilize `derive_default_enum`)
 - #94461 (Create (unstable) 2024 edition)
 - #94849 (Check var scope if it exist)
 - #95194 (remove find_use_placement)
 - #95749 (only downgrade selection Error -> Ambiguous if type error is in predicate)
 - #96026 (couple of clippy::complexity fixes)
 - #96027 (remove function parameters only used in recursion)
 - #96034 ([test] Add test cases of untested functions for BTreeSet )
 - #96040 (Use u32 instead of i32 for futexes.)
 - #96062 (docs: Update tests chapter for Termination stabilization)
 - #96065 (Refactor: Use `format-args-capture` and remove unnecessary nested blocks in rustc_typeck)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-04-15 18:51:40 +00:00
commit 3f391b8455
94 changed files with 1029 additions and 1073 deletions

View file

@ -722,7 +722,7 @@ impl NonterminalKind {
Edition::Edition2015 | Edition::Edition2018 => {
NonterminalKind::PatParam { inferred: true }
}
Edition::Edition2021 => NonterminalKind::PatWithOr,
Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
},
sym::pat_param => NonterminalKind::PatParam { inferred: false },
sym::expr => NonterminalKind::Expr,

View file

@ -52,7 +52,9 @@ pub(super) fn index_hir<'hir>(
};
match item {
OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID),
OwnerNode::Crate(citem) => {
collector.visit_mod(&citem, citem.spans.inner_span, hir::CRATE_HIR_ID)
}
OwnerNode::Item(item) => collector.visit_item(item),
OwnerNode::TraitItem(item) => collector.visit_trait_item(item),
OwnerNode::ImplItem(item) => collector.visit_impl_item(item),

View file

@ -124,7 +124,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
self.with_lctx(CRATE_NODE_ID, |lctx| {
let module = lctx.lower_mod(&c.items, c.spans.inner_span);
let module = lctx.lower_mod(&c.items, &c.spans);
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
hir::OwnerNode::Crate(lctx.arena.alloc(module))
})
@ -186,9 +186,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
}
impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> {
hir::Mod {
inner: self.lower_span(inner),
spans: hir::ModSpans {
inner_span: self.lower_span(spans.inner_span),
inject_use_span: self.lower_span(spans.inject_use_span),
},
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
}
}
@ -308,8 +311,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}
ItemKind::Mod(_, ref mod_kind) => match mod_kind {
ModKind::Loaded(items, _, ModSpans { inner_span, inject_use_span: _ }) => {
hir::ItemKind::Mod(self.lower_mod(items, *inner_span))
ModKind::Loaded(items, _, spans) => {
hir::ItemKind::Mod(self.lower_mod(items, spans))
}
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
},

View file

@ -46,18 +46,7 @@ pub fn expand_deriving_default(
StaticStruct(_, fields) => {
default_struct_substructure(cx, trait_span, substr, fields)
}
StaticEnum(enum_def, _) => {
if !cx.sess.features_untracked().derive_default_enum {
rustc_session::parse::feature_err(
cx.parse_sess(),
sym::derive_default_enum,
span,
"deriving `Default` on enums is experimental",
)
.emit();
}
default_enum_substructure(cx, trait_span, enum_def)
}
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
_ => cx.span_bug(trait_span, "method in `derive(Default)`"),
}
})),

View file

@ -70,6 +70,7 @@ pub fn inject(
Edition2015 => sym::rust_2015,
Edition2018 => sym::rust_2018,
Edition2021 => sym::rust_2021,
Edition2024 => sym::rust_2024,
}])
.map(|&symbol| Ident::new(symbol, span))
.collect();

View file

@ -832,7 +832,7 @@ impl Diagnostic {
name: impl Into<Cow<'static, str>>,
arg: DiagnosticArgValue<'static>,
) -> &mut Self {
self.args.push((name.into(), arg.into()));
self.args.push((name.into(), arg));
self
}

View file

@ -270,7 +270,7 @@ fn check_binders(
MISSING_FRAGMENT_SPECIFIER,
span,
node_id,
&format!("missing fragment specifier"),
"missing fragment specifier",
);
}
if !macros.is_empty() {

View file

@ -77,7 +77,6 @@ use crate::mbe::{KleeneOp, TokenTree};
use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token};
use rustc_parse::parser::{NtOrTt, Parser};
use rustc_session::parse::ParseSess;
use rustc_span::symbol::MacroRulesNormalizedIdent;
use rustc_span::Span;
@ -128,9 +127,8 @@ pub(super) enum MatcherLoc {
Eof,
}
pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<MatcherLoc> {
pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
fn inner(
sess: &ParseSess,
tts: &[TokenTree],
locs: &mut Vec<MatcherLoc>,
next_metavar: &mut usize,
@ -147,7 +145,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<Match
locs.push(MatcherLoc::Delimited);
locs.push(MatcherLoc::Token { token: open_token });
inner(sess, &delimited.tts, locs, next_metavar, seq_depth);
inner(&delimited.tts, locs, next_metavar, seq_depth);
locs.push(MatcherLoc::Token { token: close_token });
}
TokenTree::Sequence(_, seq) => {
@ -162,7 +160,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<Match
let op = seq.kleene.op;
let idx_first = locs.len();
let idx_seq = idx_first - 1;
inner(sess, &seq.tts, locs, next_metavar, seq_depth + 1);
inner(&seq.tts, locs, next_metavar, seq_depth + 1);
if let Some(separator) = &seq.separator {
locs.push(MatcherLoc::SequenceSep { separator: separator.clone() });
@ -197,7 +195,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<Match
let mut locs = vec![];
let mut next_metavar = 0;
inner(sess, matcher, &mut locs, &mut next_metavar, /* seq_depth */ 0);
inner(matcher, &mut locs, &mut next_metavar, /* seq_depth */ 0);
// A final entry is needed for eof.
locs.push(MatcherLoc::Eof);

View file

@ -435,7 +435,7 @@ pub fn compile_declarative_macro(
),
];
// Convert it into `MatcherLoc` form.
let argument_gram = mbe::macro_parser::compute_locs(&sess.parse_sess, &argument_gram);
let argument_gram = mbe::macro_parser::compute_locs(&argument_gram);
let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS);
let mut tt_parser =
@ -478,7 +478,7 @@ pub fn compile_declarative_macro(
)
.pop()
.unwrap();
valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def, &tt);
valid &= check_lhs_nt_follows(&sess.parse_sess, &def, &tt);
return tt;
}
sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
@ -540,7 +540,7 @@ pub fn compile_declarative_macro(
// Ignore the delimiters around the matcher.
match lhs {
mbe::TokenTree::Delimited(_, delimited) => {
mbe::macro_parser::compute_locs(&sess.parse_sess, &delimited.tts)
mbe::macro_parser::compute_locs(&delimited.tts)
}
_ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"),
}
@ -563,16 +563,11 @@ pub fn compile_declarative_macro(
}))
}
fn check_lhs_nt_follows(
sess: &ParseSess,
features: &Features,
def: &ast::Item,
lhs: &mbe::TokenTree,
) -> bool {
fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
// lhs is going to be like TokenTree::Delimited(...), where the
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
if let mbe::TokenTree::Delimited(_, delimited) = lhs {
check_matcher(sess, features, def, &delimited.tts)
check_matcher(sess, def, &delimited.tts)
} else {
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
sess.span_diagnostic.span_err(lhs.span(), msg);
@ -632,16 +627,11 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
false
}
fn check_matcher(
sess: &ParseSess,
features: &Features,
def: &ast::Item,
matcher: &[mbe::TokenTree],
) -> bool {
fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
let first_sets = FirstSets::new(matcher);
let empty_suffix = TokenSet::empty();
let err = sess.span_diagnostic.err_count();
check_matcher_core(sess, features, def, &first_sets, matcher, &empty_suffix);
check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix);
err == sess.span_diagnostic.err_count()
}
@ -955,7 +945,6 @@ impl<'tt> TokenSet<'tt> {
// see `FirstSets::new`.
fn check_matcher_core<'tt>(
sess: &ParseSess,
features: &Features,
def: &ast::Item,
first_sets: &FirstSets<'tt>,
matcher: &'tt [mbe::TokenTree],
@ -1008,7 +997,7 @@ fn check_matcher_core<'tt>(
token::CloseDelim(d.delim),
span.close,
));
check_matcher_core(sess, features, def, first_sets, &d.tts, &my_suffix);
check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix);
// don't track non NT tokens
last.replace_with_irrelevant();
@ -1040,8 +1029,7 @@ fn check_matcher_core<'tt>(
// At this point, `suffix_first` is built, and
// `my_suffix` is some TokenSet that we can use
// for checking the interior of `seq_rep`.
let next =
check_matcher_core(sess, features, def, first_sets, &seq_rep.tts, my_suffix);
let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix);
if next.maybe_empty {
last.add_all(&next);
} else {
@ -1114,7 +1102,7 @@ fn check_matcher_core<'tt>(
err.span_label(sp, format!("not allowed after `{}` fragments", kind));
if kind == NonterminalKind::PatWithOr
&& sess.edition == Edition::Edition2021
&& sess.edition.rust_2021()
&& next_token.is_token(&BinOp(token::BinOpToken::Or))
{
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(

View file

@ -126,6 +126,8 @@ declare_features! (
(accepted, default_type_params, "1.0.0", None, None),
/// Allows `#[deprecated]` attribute.
(accepted, deprecated, "1.9.0", Some(29935), None),
/// Allows `#[derive(Default)]` and `#[default]` on enums.
(accepted, derive_default_enum, "1.62.0", Some(86985), None),
/// Allows the use of destructuring assignments.
(accepted, destructuring_assignment, "1.59.0", Some(71126), None),
/// Allows `#[doc(alias = "...")]`.

View file

@ -368,8 +368,6 @@ declare_features! (
(active, deprecated_safe, "1.61.0", Some(94978), None),
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
(active, deprecated_suggestion, "1.61.0", Some(94785), None),
/// Allows `#[derive(Default)]` and `#[default]` on enums.
(active, derive_default_enum, "1.56.0", Some(86985), None),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
(active, doc_auto_cfg, "1.58.0", Some(43781), None),
/// Allows `#[doc(cfg(...))]`.

View file

@ -11,7 +11,7 @@
//! even if it is stabilized or removed, *do not remove it*. Instead, move the
//! symbol to the `accepted` or `removed` modules respectively.
#![feature(derive_default_enum)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(once_cell)]
mod accepted;

View file

@ -2557,11 +2557,17 @@ impl FnRetTy<'_> {
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct Mod<'hir> {
pub spans: ModSpans,
pub item_ids: &'hir [ItemId],
}
#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable)]
pub struct ModSpans {
/// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token
/// to the last token in the external file.
pub inner: Span,
pub item_ids: &'hir [ItemId],
pub inner_span: Span,
pub inject_use_span: Span,
}
#[derive(Debug, HashStable_Generic)]
@ -3059,8 +3065,8 @@ impl<'hir> OwnerNode<'hir> {
OwnerNode::Item(Item { span, .. })
| OwnerNode::ForeignItem(ForeignItem { span, .. })
| OwnerNode::ImplItem(ImplItem { span, .. })
| OwnerNode::TraitItem(TraitItem { span, .. })
| OwnerNode::Crate(Mod { inner: span, .. }) => *span,
| OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
}
}

View file

@ -63,9 +63,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// common state. Used in coherence.
pub fn fork(&self) -> Self {
Self {
tcx: self.tcx.clone(),
defining_use_anchor: self.defining_use_anchor.clone(),
in_progress_typeck_results: self.in_progress_typeck_results.clone(),
tcx: self.tcx,
defining_use_anchor: self.defining_use_anchor,
in_progress_typeck_results: self.in_progress_typeck_results,
inner: self.inner.clone(),
skip_leak_check: self.skip_leak_check.clone(),
lexical_region_resolutions: self.lexical_region_resolutions.clone(),

View file

@ -17,7 +17,7 @@
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(derive_default_enum)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(extend_one)]
#![feature(label_break_value)]
#![feature(let_chains)]

View file

@ -44,7 +44,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
#[proc_macro]
#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)]
pub fn newtype_index(input: TokenStream) -> TokenStream {
newtype::newtype(input).into()
newtype::newtype(input)
}
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);

View file

@ -584,7 +584,7 @@ impl<'hir> Map<'hir> {
Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
(m, span, hir_id)
}
Some(OwnerNode::Crate(item)) => (item, item.inner, hir_id),
Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id),
node => panic!("not a module: {:?}", node),
}
}
@ -1012,7 +1012,7 @@ impl<'hir> Map<'hir> {
Node::Infer(i) => i.span,
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
Node::Local(local) => local.span,
Node::Crate(item) => item.inner,
Node::Crate(item) => item.spans.inner_span,
};
Some(span)
}

View file

@ -30,7 +30,7 @@
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(core_intrinsics)]
#![feature(derive_default_enum)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(discriminant_kind)]
#![feature(exhaustive_patterns)]
#![feature(get_mut_unchecked)]

View file

@ -362,12 +362,9 @@ impl ScopeTree {
self.parent_map.get(&id).cloned().map(|(p, _)| p)
}
/// Returns the lifetime of the local variable `var_id`
pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope {
self.var_map
.get(&var_id)
.cloned()
.unwrap_or_else(|| bug!("no enclosing scope for id {:?}", var_id))
/// Returns the lifetime of the local variable `var_id`, if any.
pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Option<Scope> {
self.var_map.get(&var_id).cloned()
}
/// Returns the scope when the temp created by `expr_id` will be cleaned up.

View file

@ -191,7 +191,7 @@ impl<'tcx> Ty<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest<'tcx> {
tcx.type_uninhabited_from(param_env.and(self)).clone()
tcx.type_uninhabited_from(param_env.and(self))
}
}

View file

@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
};
Constant { span, user_ty: None, literal: literal.into() }
Constant { span, user_ty: None, literal }
}
ExprKind::NonHirLiteral { lit, user_ty } => {
let user_ty = user_ty.map(|user_ty| {

View file

@ -423,11 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
thir::InlineAsmOperand::Const { value, span } => {
mir::InlineAsmOperand::Const {
value: Box::new(Constant {
span,
user_ty: None,
literal: value.into(),
}),
value: Box::new(Constant { span, user_ty: None, literal: value }),
}
}
thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn {

View file

@ -701,8 +701,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let local_id = self.var_local_id(var, for_guard);
let source_info = self.source_info(span);
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) });
let region_scope = self.region_scope_tree.var_scope(var.local_id);
if schedule_drop {
// Altough there is almost always scope for given variable in corner cases
// like #92893 we might get variable with no scope.
if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) && schedule_drop{
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
}
Place::from(local_id)
@ -710,8 +711,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
let local_id = self.var_local_id(var, for_guard);
let region_scope = self.region_scope_tree.var_scope(var.local_id);
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) {
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
}
}
/// Visit all of the primary bindings in a patterns, that is, visit the

View file

@ -441,7 +441,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Need to experiment.
user_ty: None,
literal: method.into(),
literal: method,
})),
args: vec![val, expect],
destination: Some((eq_result, eq_block)),

View file

@ -539,13 +539,13 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
UnusedUnsafe::InUnsafeBlock(id) => {
db.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
format!("because it's nested under this `unsafe` block"),
"because it's nested under this `unsafe` block",
);
}
UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => {
db.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
format!("because it's nested under this `unsafe` fn"),
"because it's nested under this `unsafe` fn",
)
.note(
"this `unsafe` block does contain unsafe operations, \

View file

@ -234,13 +234,13 @@ impl<'a> StringReader<'a> {
rustc_lexer::TokenKind::InvalidIdent
// Do not recover an identifier with emoji if the codepoint is a confusable
// with a recoverable substitution token, like ``.
if UNICODE_ARRAY
if !UNICODE_ARRAY
.iter()
.find(|&&(c, _, _)| {
.any(|&(c, _, _)| {
let sym = self.str_from(start);
sym.chars().count() == 1 && c == sym.chars().next().unwrap()
})
.is_none() =>
=>
{
let sym = nfc_normalize(self.str_from(start));
let span = self.mk_sp(start, self.pos);

View file

@ -158,7 +158,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
#[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands.
fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) {
fn check_for_self_assign_helper<'tcx>(
tcx: TyCtxt<'tcx>,
typeck_results: &'tcx ty::TypeckResults<'tcx>,
lhs: &'tcx hir::Expr<'tcx>,
rhs: &'tcx hir::Expr<'tcx>,
@ -177,7 +176,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
(hir::ExprKind::Field(lhs_l, ident_l), hir::ExprKind::Field(lhs_r, ident_r)) => {
if ident_l == ident_r {
return check_for_self_assign_helper(tcx, typeck_results, lhs_l, lhs_r);
return check_for_self_assign_helper(typeck_results, lhs_l, lhs_r);
}
return false;
}
@ -188,7 +187,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
if let hir::ExprKind::Assign(lhs, rhs, _) = assign.kind {
if check_for_self_assign_helper(self.tcx, self.typeck_results(), lhs, rhs)
if check_for_self_assign_helper(self.typeck_results(), lhs, rhs)
&& !assign.span.from_expansion()
{
let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));

View file

@ -133,9 +133,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
// `Deprecation` is just two pointers, no need to intern it
let depr_entry = DeprecationEntry::local(depr.clone(), def_id);
let depr_entry = DeprecationEntry::local(*depr, def_id);
self.index.depr_map.insert(def_id, depr_entry);
} else if let Some(parent_depr) = self.parent_depr.clone() {
} else if let Some(parent_depr) = self.parent_depr {
if inherit_deprecation.yes() {
is_deprecated = true;
info!("tagging child {:?} as deprecated from parent", def_id);

View file

@ -1095,11 +1095,11 @@ impl<'tcx> DumpVisitor<'tcx> {
let sm = self.tcx.sess.source_map();
let krate_mod = self.tcx.hir().root_module();
let filename = sm.span_to_filename(krate_mod.inner);
let filename = sm.span_to_filename(krate_mod.spans.inner_span);
let data_id = id_from_hir_id(id, &self.save_ctxt);
let children =
krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect();
let span = self.span_from_span(krate_mod.inner);
let span = self.span_from_span(krate_mod.spans.inner_span);
let attrs = self.tcx.hir().attrs(id);
self.dumper.dump_def(

View file

@ -282,7 +282,7 @@ impl<'tcx> SaveContext<'tcx> {
let qualname = format!("::{}", self.tcx.def_path_str(def_id));
let sm = self.tcx.sess.source_map();
let filename = sm.span_to_filename(m.inner);
let filename = sm.span_to_filename(m.spans.inner_span);
filter!(self.span_utils, item.ident.span);

View file

@ -1,7 +1,7 @@
#![feature(crate_visibility_modifier)]
#![feature(derive_default_enum)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(never_type)]

View file

@ -238,7 +238,7 @@ impl Session {
}
diag.emit();
// If we should err, make sure we did.
if must_err && !self.has_errors().is_some() {
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
self.err(
"`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
@ -991,6 +991,11 @@ impl Session {
self.opts.edition >= Edition::Edition2021
}
/// Are we allowed to use features from the Rust 2024 edition?
pub fn rust_2024(&self) -> bool {
self.opts.edition >= Edition::Edition2024
}
pub fn edition(&self) -> Edition {
self.opts.edition
}

View file

@ -22,13 +22,15 @@ pub enum Edition {
Edition2018,
/// The 2021 edition
Edition2021,
/// The 2024 edition
Edition2024,
}
// Must be in order from oldest to newest.
pub const ALL_EDITIONS: &[Edition] =
&[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];
&[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021, Edition::Edition2024];
pub const EDITION_NAME_LIST: &str = "2015|2018|2021";
pub const EDITION_NAME_LIST: &str = "2015|2018|2021|2024";
pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
@ -40,6 +42,7 @@ impl fmt::Display for Edition {
Edition::Edition2015 => "2015",
Edition::Edition2018 => "2018",
Edition::Edition2021 => "2021",
Edition::Edition2024 => "2024",
};
write!(f, "{}", s)
}
@ -51,6 +54,7 @@ impl Edition {
Edition::Edition2015 => "rust_2015_compatibility",
Edition::Edition2018 => "rust_2018_compatibility",
Edition::Edition2021 => "rust_2021_compatibility",
Edition::Edition2024 => "rust_2024_compatibility",
}
}
@ -59,6 +63,7 @@ impl Edition {
Edition::Edition2015 => sym::rust_2015_preview,
Edition::Edition2018 => sym::rust_2018_preview,
Edition::Edition2021 => sym::rust_2021_preview,
Edition::Edition2024 => sym::rust_2024_preview,
}
}
@ -67,8 +72,28 @@ impl Edition {
Edition::Edition2015 => true,
Edition::Edition2018 => true,
Edition::Edition2021 => true,
Edition::Edition2024 => false,
}
}
pub fn rust_2015(&self) -> bool {
*self == Edition::Edition2015
}
/// Are we allowed to use features from the Rust 2018 edition?
pub fn rust_2018(&self) -> bool {
*self >= Edition::Edition2018
}
/// Are we allowed to use features from the Rust 2021 edition?
pub fn rust_2021(&self) -> bool {
*self >= Edition::Edition2021
}
/// Are we allowed to use features from the Rust 2024 edition?
pub fn rust_2024(&self) -> bool {
*self >= Edition::Edition2024
}
}
impl FromStr for Edition {
@ -78,6 +103,7 @@ impl FromStr for Edition {
"2015" => Ok(Edition::Edition2015),
"2018" => Ok(Edition::Edition2018),
"2021" => Ok(Edition::Edition2021),
"2024" => Ok(Edition::Edition2024),
_ => Err(()),
}
}

View file

@ -684,6 +684,11 @@ impl Span {
self.edition() >= edition::Edition::Edition2021
}
#[inline]
pub fn rust_2024(self) -> bool {
self.edition() >= edition::Edition::Edition2024
}
/// Returns the source callee.
///
/// Returns `None` if the supplied span has no expansion trace,

View file

@ -1149,6 +1149,8 @@ symbols! {
rust_2018_preview,
rust_2021,
rust_2021_preview,
rust_2024,
rust_2024_preview,
rust_begin_unwind,
rust_eh_catch_typeinfo,
rust_eh_personality,

View file

@ -113,11 +113,11 @@ where
data = arg_scalar(cx, &scalar, offset, data);
}
abi::Abi::Aggregate { .. } => {
for i in 0..layout.fields.count().clone() {
for i in 0..layout.fields.count() {
if offset < layout.fields.offset(i) {
offset = layout.fields.offset(i);
}
data = parse_structure(cx, layout.field(cx, i).clone(), data.clone(), offset);
data = parse_structure(cx, layout.field(cx, i), data.clone(), offset);
}
}
_ => {
@ -161,7 +161,7 @@ where
let mut data = parse_structure(
cx,
arg.layout.clone(),
arg.layout,
Sdata {
prefix: [None; 8],
prefix_index: 0,

View file

@ -16,7 +16,7 @@
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)]
#![feature(derive_default_enum)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(drain_filter)]
#![feature(hash_drain_filter)]
#![feature(label_break_value)]

View file

@ -258,7 +258,7 @@ impl<'tcx> OnUnimplementedDirective {
enclosing_scope = Some(enclosing_scope_.clone());
}
append_const_msg = command.append_const_msg.clone();
append_const_msg = command.append_const_msg;
}
OnUnimplementedNote {

View file

@ -231,8 +231,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
// emitting additional spurious errors, since we're guaranteed
// to have emitted at least one.
if stack.obligation.references_error() {
debug!("no results for error type, treating as ambiguous");
if stack.obligation.predicate.references_error() {
debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous");
return Ok(None);
}
return Err(Unimplemented);

View file

@ -260,10 +260,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut |err| {
if let Some((span, msg)) = &ret_reason {
err.span_label(*span, msg.as_str());
} else if let ExprKind::Block(block, _) = &then_expr.kind {
if let Some(expr) = &block.expr {
err.span_label(expr.span, "found here".to_string());
}
} else if let ExprKind::Block(block, _) = &then_expr.kind
&& let Some(expr) = &block.expr
{
err.span_label(expr.span, "found here".to_string());
}
err.note("`if` expressions without `else` evaluate to `()`");
err.help("consider adding an `else` block that evaluates to the expected type");
@ -293,7 +293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
let span = fn_decl.output.span();
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
Some((span, format!("expected `{}` because of this return type", snippet)))
Some((span, format!("expected `{snippet}` because of this return type")))
});
}
}

View file

@ -43,7 +43,7 @@ pub fn check_legal_trait_for_method_call(
let (sp, suggestion) = receiver
.and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok())
.filter(|snippet| !snippet.is_empty())
.map(|snippet| (expr_span, format!("drop({})", snippet)))
.map(|snippet| (expr_span, format!("drop({snippet})")))
.unwrap_or_else(|| (span, "drop".to_string()));
err.span_suggestion(
@ -315,17 +315,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::Tup(exp),
hir::ExprKind::Call(_, args),
) = (parent_node, &callee_expr.kind, &call_expr.kind)
&& args.len() == exp.len()
{
if args.len() == exp.len() {
let start = callee_expr.span.shrink_to_hi();
err.span_suggestion(
start,
"consider separating array elements with a comma",
",".to_string(),
Applicability::MaybeIncorrect,
);
return true;
}
let start = callee_expr.span.shrink_to_hi();
err.span_suggestion(
start,
"consider separating array elements with a comma",
",".to_string(),
Applicability::MaybeIncorrect,
);
return true;
}
false
}
@ -373,15 +372,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ref t => {
let mut unit_variant = None;
let mut removal_span = call_expr.span;
if let ty::Adt(adt_def, ..) = t {
if adt_def.is_enum() {
if let hir::ExprKind::Call(expr, _) = call_expr.kind {
removal_span =
expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
}
}
if let ty::Adt(adt_def, ..) = t
&& adt_def.is_enum()
&& let hir::ExprKind::Call(expr, _) = call_expr.kind
{
removal_span =
expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
}
let callee_ty = self.resolve_vars_if_possible(callee_ty);
@ -392,8 +390,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
E0618,
"expected function, found {}",
match unit_variant {
Some(ref path) => format!("enum variant `{}`", path),
None => format!("`{}`", callee_ty),
Some(ref path) => format!("enum variant `{path}`"),
None => format!("`{callee_ty}`"),
}
);
@ -408,8 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
removal_span,
&format!(
"`{}` is a unit variant, you need to write it without the parentheses",
path
"`{path}` is a unit variant, you need to write it without the parentheses",
),
String::new(),
Applicability::MachineApplicable,
@ -452,14 +449,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string();
let label = match (unit_variant, inner_callee_path) {
(Some(path), _) => Some(format!("`{}` defined here", path)),
(Some(path), _) => Some(format!("`{path}` defined here")),
(_, Some(hir::QPath::Resolved(_, path))) => self
.tcx
.sess
.source_map()
.span_to_snippet(path.span)
.ok()
.map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)),
.map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
_ => {
match def {
// Emit a different diagnostic for local variables, as they are not
@ -475,7 +472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.def_path_str(def_id),
))
}
_ => Some(format!("`{}` defined here", callee_ty)),
_ => Some(format!("`{callee_ty}` defined here")),
}
}
};

View file

@ -322,7 +322,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_suggestion(
self.span,
"compare with zero instead",
format!("{} != 0", snippet),
format!("{snippet} != 0"),
Applicability::MachineApplicable,
);
}
@ -373,8 +373,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let mut sugg = None;
let mut sugg_mutref = false;
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
if fcx
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
@ -386,27 +386,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
None,
)
.is_ok()
{
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
}
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
if expr_mutbl == Mutability::Not
&& mutbl == Mutability::Mut
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
expr_reg,
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg_mutref = true;
}
{
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
&& expr_mutbl == Mutability::Not
&& mutbl == Mutability::Mut
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
expr_reg,
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg_mutref = true;
}
if !sugg_mutref
@ -423,8 +421,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
{
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() {
if fcx
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
@ -436,9 +434,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
None,
)
.is_ok()
{
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
{
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
if sugg_mutref {
err.span_label(self.span, "invalid cast");
@ -483,28 +480,28 @@ impl<'a, 'tcx> CastCheck<'tcx> {
) {
let mut label = true;
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
// Erase regions to avoid panic in `prove_value` when calling
// `type_implements_trait`.
let ty = fcx.tcx.erase_regions(ty);
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let expr_ty = fcx.tcx.erase_regions(expr_ty);
let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
if fcx
.infcx
.type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
err.span_suggestion(
self.span,
"consider using the `From` trait instead",
format!("{}::from({})", self.cast_ty, snippet),
Applicability::MaybeIncorrect,
);
}
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
&& let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From)
{
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
// Erase regions to avoid panic in `prove_value` when calling
// `type_implements_trait`.
let ty = fcx.tcx.erase_regions(ty);
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let expr_ty = fcx.tcx.erase_regions(expr_ty);
let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
if fcx
.infcx
.type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
err.span_suggestion(
self.span,
"consider using the `From` trait instead",
format!("{}::from({})", self.cast_ty, snippet),
Applicability::MaybeIncorrect,
);
}
}
let msg = "an `as` expression can only be used to convert between primitive \
@ -627,10 +624,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
}
} else {
let msg = &format!(
"consider using an implicit coercion to `&{}{}` instead",
mtstr, tstr
);
let msg =
&format!("consider using an implicit coercion to `&{mtstr}{tstr}` instead");
err.span_help(self.span, msg);
}
}
@ -640,14 +635,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_suggestion(
self.cast_span,
"you can cast to a `Box` instead",
format!("Box<{}>", s),
format!("Box<{s}>"),
Applicability::MachineApplicable,
);
}
Err(_) => {
err.span_help(
self.cast_span,
&format!("you might have meant `Box<{}>`", tstr),
&format!("you might have meant `Box<{tstr}>`"),
);
}
}
@ -678,8 +673,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
))
.help(&format!(
"cast can be replaced by coercion; this might \
require {}a temporary variable",
type_asc_or
require {type_asc_or}a temporary variable"
))
.emit();
});
@ -969,21 +963,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
if let ty::Adt(d, _) = self.expr_ty.kind() {
if d.has_dtor(fcx.tcx) {
fcx.tcx.struct_span_lint_hir(
lint::builtin::CENUM_IMPL_DROP_CAST,
self.expr.hir_id,
self.span,
|err| {
err.build(&format!(
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
self.expr_ty, self.cast_ty
))
.emit();
},
);
}
if let ty::Adt(d, _) = self.expr_ty.kind()
&& d.has_dtor(fcx.tcx)
{
fcx.tcx.struct_span_lint_hir(
lint::builtin::CENUM_IMPL_DROP_CAST,
self.expr.hir_id,
self.span,
|err| {
err.build(&format!(
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
self.expr_ty, self.cast_ty
))
.emit();
},
);
}
}
@ -1007,7 +1001,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_suggestion(
self.span,
msg,
format!("({}).addr(){}", snippet, scalar_cast),
format!("({snippet}).addr(){scalar_cast}"),
Applicability::MaybeIncorrect
);
} else {
@ -1038,7 +1032,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_suggestion(
self.span,
msg,
format!("(...).with_addr({})", snippet),
format!("(...).with_addr({snippet})"),
Applicability::HasPlaceholders,
);
} else {

View file

@ -43,8 +43,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
tcx.sess,
span,
E0570,
"`{}` is not a supported ABI for the current target",
abi
"`{abi}` is not a supported ABI for the current target",
)
.emit();
}
@ -249,84 +248,84 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.demand_suptype(span, declared_ret_ty, actual_return_ty);
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
if panic_impl_did == hir.local_def_id(fn_id).to_def_id() {
if let Some(panic_info_did) = tcx.lang_items().panic_info() {
if *declared_ret_ty.kind() != ty::Never {
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_panic_info = match *inputs[0].kind() {
ty::Ref(region, ty, mutbl) => match *ty.kind() {
ty::Adt(ref adt, _) => {
adt.did() == panic_info_did
&& mutbl == hir::Mutability::Not
&& !region.is_static()
}
_ => false,
},
_ => false,
};
if !arg_is_panic_info {
sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
}
if let Node::Item(item) = hir.get(fn_id)
&& let ItemKind::Fn(_, ref generics, _) = item.kind
&& !generics.params.is_empty()
{
sess.span_err(span, "should have no type parameters");
}
} else {
let span = sess.source_map().guess_head_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
sess.err("language item required, but not found: `panic_info`");
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
&& panic_impl_did == hir.local_def_id(fn_id).to_def_id()
{
if let Some(panic_info_did) = tcx.lang_items().panic_info() {
if *declared_ret_ty.kind() != ty::Never {
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_panic_info = match *inputs[0].kind() {
ty::Ref(region, ty, mutbl) => match *ty.kind() {
ty::Adt(ref adt, _) => {
adt.did() == panic_info_did
&& mutbl == hir::Mutability::Not
&& !region.is_static()
}
_ => false,
},
_ => false,
};
if !arg_is_panic_info {
sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
}
if let Node::Item(item) = hir.get(fn_id)
&& let ItemKind::Fn(_, ref generics, _) = item.kind
&& !generics.params.is_empty()
{
sess.span_err(span, "should have no type parameters");
}
} else {
let span = sess.source_map().guess_head_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
sess.err("language item required, but not found: `panic_info`");
}
}
// Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
if let Some(alloc_error_handler_did) = tcx.lang_items().oom() {
if alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() {
if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
if *declared_ret_ty.kind() != ty::Never {
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_alloc_layout = match inputs[0].kind() {
ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
_ => false,
};
if !arg_is_alloc_layout {
sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
}
if let Node::Item(item) = hir.get(fn_id)
&& let ItemKind::Fn(_, ref generics, _) = item.kind
&& !generics.params.is_empty()
{
sess.span_err(
span,
"`#[alloc_error_handler]` function should have no type parameters",
);
}
} else {
let span = sess.source_map().guess_head_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
sess.err("language item required, but not found: `alloc_layout`");
if let Some(alloc_error_handler_did) = tcx.lang_items().oom()
&& alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id()
{
if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
if *declared_ret_ty.kind() != ty::Never {
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_alloc_layout = match inputs[0].kind() {
ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
_ => false,
};
if !arg_is_alloc_layout {
sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
}
if let Node::Item(item) = hir.get(fn_id)
&& let ItemKind::Fn(_, ref generics, _) = item.kind
&& !generics.params.is_empty()
{
sess.span_err(
span,
"`#[alloc_error_handler]` function should have no type parameters",
);
}
} else {
let span = sess.source_map().guess_head_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
sess.err("language item required, but not found: `alloc_layout`");
}
}
@ -670,7 +669,7 @@ fn check_opaque_meets_bounds<'tcx>(
Err(ty_err) => {
tcx.sess.delay_span_bug(
span,
&format!("could not unify `{}` with revealed type:\n{}", hidden_type, ty_err,),
&format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
);
}
}
@ -817,10 +816,9 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
tcx.sess,
item.span,
E0044,
"foreign items may not have {} parameters",
kinds,
"foreign items may not have {kinds} parameters",
)
.span_label(item.span, &format!("can't have {} parameters", kinds))
.span_label(item.span, &format!("can't have {kinds} parameters"))
.help(
// FIXME: once we start storing spans for type arguments, turn this
// into a suggestion.
@ -1065,68 +1063,67 @@ pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalD
pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
let t = tcx.type_of(def_id);
if let ty::Adt(def, substs) = t.kind() {
if def.is_struct() {
let fields = &def.non_enum_variant().fields;
if fields.is_empty() {
if let ty::Adt(def, substs) = t.kind()
&& def.is_struct()
{
let fields = &def.non_enum_variant().fields;
if fields.is_empty() {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
let e = fields[0].ty(tcx, substs);
if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
.emit();
return;
}
let len = if let ty::Array(_ty, c) = e.kind() {
c.try_eval_usize(tcx, tcx.param_env(def.did()))
} else {
Some(fields.len() as u64)
};
if let Some(len) = len {
if len == 0 {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
let e = fields[0].ty(tcx, substs);
if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
.emit();
} else if len > MAX_SIMD_LANES {
struct_span_err!(
tcx.sess,
sp,
E0075,
"SIMD vector cannot have more than {MAX_SIMD_LANES} elements",
)
.emit();
return;
}
}
let len = if let ty::Array(_ty, c) = e.kind() {
c.try_eval_usize(tcx, tcx.param_env(def.did()))
} else {
Some(fields.len() as u64)
};
if let Some(len) = len {
if len == 0 {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
} else if len > MAX_SIMD_LANES {
struct_span_err!(
tcx.sess,
sp,
E0075,
"SIMD vector cannot have more than {} elements",
MAX_SIMD_LANES,
)
.emit();
return;
}
}
// Check that we use types valid for use in the lanes of a SIMD "vector register"
// These are scalar types which directly match a "machine" type
// Yes: Integers, floats, "thin" pointers
// No: char, "fat" pointers, compound types
match e.kind() {
ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
ty::Array(t, _clen)
if matches!(
t.kind(),
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)
) =>
{ /* struct([f32; 4]) is ok */ }
_ => {
struct_span_err!(
tcx.sess,
sp,
E0077,
"SIMD vector element type should be a \
primitive scalar (integer/float/pointer) type"
)
.emit();
return;
}
// Check that we use types valid for use in the lanes of a SIMD "vector register"
// These are scalar types which directly match a "machine" type
// Yes: Integers, floats, "thin" pointers
// No: char, "fat" pointers, compound types
match e.kind() {
ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
ty::Array(t, _clen)
if matches!(
t.kind(),
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)
) =>
{ /* struct([f32; 4]) is ok */ }
_ => {
struct_span_err!(
tcx.sess,
sp,
E0077,
"SIMD vector element type should be a \
primitive scalar (integer/float/pointer) type"
)
.emit();
return;
}
}
}
@ -1189,7 +1186,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
ident
)
} else {
format!("...which contains a field of type `{}`", ident)
format!("...which contains a field of type `{ident}`")
},
);
first = false;
@ -1215,13 +1212,12 @@ pub(super) fn check_packed_inner(
stack.push(def_id);
for field in &def.non_enum_variant().fields {
if let ty::Adt(def, _) = field.ty(tcx, substs).kind() {
if !stack.contains(&def.did()) {
if let Some(mut defs) = check_packed_inner(tcx, def.did(), stack) {
defs.push((def.did(), field.ident(tcx).span));
return Some(defs);
}
}
if let ty::Adt(def, _) = field.ty(tcx, substs).kind()
&& !stack.contains(&def.did())
&& let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
{
defs.push((def.did(), field.ident(tcx).span));
return Some(defs);
}
}
stack.pop();
@ -1370,8 +1366,8 @@ fn check_enum<'tcx>(
"discriminant value `{}` already exists",
discr.val,
)
.span_label(i_span, format!("first use of {}", display_discr_i))
.span_label(span, format!("enum already has {}", display_discr))
.span_label(i_span, format!("first use of {display_discr_i}"))
.span_label(span, format!("enum already has {display_discr}"))
.emit();
}
disr_vals.push(discr);
@ -1393,7 +1389,7 @@ fn display_discriminant_value<'tcx>(
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
&& evaluated != *lit_value
{
return format!("`{}` (overflowed from `{}`)", evaluated, lit_value);
return format!("`{evaluated}` (overflowed from `{lit_value}`)");
}
}
format!("`{}`", evaluated)
@ -1422,28 +1418,28 @@ pub(super) fn check_type_params_are_used<'tcx>(
}
for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if let ty::Param(param) = leaf_ty.kind() {
debug!("found use of ty param {:?}", param);
params_used.insert(param.index);
}
if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
&& let ty::Param(param) = leaf_ty.kind()
{
debug!("found use of ty param {:?}", param);
params_used.insert(param.index);
}
}
for param in &generics.params {
if !params_used.contains(param.index) {
if let ty::GenericParamDefKind::Type { .. } = param.kind {
let span = tcx.def_span(param.def_id);
struct_span_err!(
tcx.sess,
span,
E0091,
"type parameter `{}` is unused",
param.name,
)
.span_label(span, "unused type parameter")
.emit();
}
if !params_used.contains(param.index)
&& let ty::GenericParamDefKind::Type { .. } = param.kind
{
let span = tcx.def_span(param.def_id);
struct_span_err!(
tcx.sess,
span,
E0091,
"type parameter `{}` is unused",
param.name,
)
.span_label(span, "unused type parameter")
.emit();
}
}
}
@ -1534,10 +1530,10 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
for def_id in visitor.0 {
let ty_span = tcx.def_span(def_id);
if !seen.contains(&ty_span) {
err.span_label(ty_span, &format!("returning this opaque type `{}`", ty));
err.span_label(ty_span, &format!("returning this opaque type `{ty}`"));
seen.insert(ty_span);
}
err.span_label(sp, &format!("returning here with type `{}`", ty));
err.span_label(sp, &format!("returning here with type `{ty}`"));
}
}
}

View file

@ -632,11 +632,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) =
(self_ty.kind(), unsize_ty.kind())
&& data_a.principal_def_id() != data_b.principal_def_id()
{
if data_a.principal_def_id() != data_b.principal_def_id() {
debug!("coerce_unsized: found trait upcasting coercion");
has_trait_upcasting_coercion = true;
}
debug!("coerce_unsized: found trait upcasting coercion");
has_trait_upcasting_coercion = true;
}
if let ty::Tuple(..) = unsize_ty.kind() {
debug!("coerce_unsized: found unsized tuple coercion");
@ -732,13 +731,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
{
if let ty::FnPtr(fn_ty_b) = b.kind() {
if let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
if let ty::FnPtr(fn_ty_b) = b.kind()
&& let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
(fn_ty_a.unsafety(), fn_ty_b.unsafety())
{
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
return self.unify_and(unsafe_a, b, to_unsafe);
}
{
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
return self.unify_and(unsafe_a, b, to_unsafe);
}
self.unify_and(a, b, normal)
}
@ -783,12 +781,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
if let ty::FnDef(def_id, _) = *a.kind() {
if b_sig.unsafety() == hir::Unsafety::Normal
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
{
return Err(TypeError::TargetFeatureCast(def_id));
}
if let ty::FnDef(def_id, _) = *a.kind()
&& b_sig.unsafety() == hir::Unsafety::Normal
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
{
return Err(TypeError::TargetFeatureCast(def_id));
}
let InferOk { value: a_sig, obligations: o1 } =
@ -1540,11 +1537,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fcx.tcx.hir().get_if_cause(expr.hir_id),
expected.is_unit(),
pointing_at_return_type,
) {
)
// If the block is from an external macro or try (`?`) desugaring, then
// do not suggest adding a semicolon, because there's nowhere to put it.
// See issues #81943 and #87051.
if matches!(
&& matches!(
cond_expr.span.desugaring_kind(),
None | Some(DesugaringKind::WhileLoop)
) && !in_external_macro(fcx.tcx.sess, cond_expr.span)
@ -1552,11 +1549,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
cond_expr.kind,
hir::ExprKind::Match(.., hir::MatchSource::TryDesugar)
)
{
err.span_label(cond_expr.span, "expected this to be `()`");
if expr.can_have_side_effects() {
fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
}
{
err.span_label(cond_expr.span, "expected this to be `()`");
if expr.can_have_side_effects() {
fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
}
}
fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
@ -1636,28 +1632,27 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
// Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
let mut is_object_safe = false;
if let hir::FnRetTy::Return(ty) = fn_output {
if let hir::FnRetTy::Return(ty) = fn_output
// Get the return type.
if let hir::TyKind::OpaqueDef(..) = ty.kind {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind() {
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
fcx.tcx.hir().expect_item(def_id.expect_local()).kind
{
// Are of this `impl Trait`'s traits object safe?
is_object_safe = bounds.iter().all(|bound| {
bound
.trait_ref()
.and_then(|t| t.trait_def_id())
.map_or(false, |def_id| {
fcx.tcx.object_safety_violations(def_id).is_empty()
})
&& let hir::TyKind::OpaqueDef(..) = ty.kind
{
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind()
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
&& let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
fcx.tcx.hir().expect_item(def_id.expect_local()).kind
{
// Are of this `impl Trait`'s traits object safe?
is_object_safe = bounds.iter().all(|bound| {
bound
.trait_ref()
.and_then(|t| t.trait_def_id())
.map_or(false, |def_id| {
fcx.tcx.object_safety_violations(def_id).is_empty()
})
}
}
})
}
};
if has_impl {
@ -1703,7 +1698,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
&& let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty)
&& let ty::Dynamic(..) = ty.kind()
{
return true;
return true;
}
false
}

View file

@ -315,7 +315,7 @@ fn compare_predicate_entailment<'tcx>(
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => {
"&mut self".to_owned()
}
_ => format!("self: {}", ty),
_ => format!("self: {ty}"),
};
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
@ -526,7 +526,7 @@ fn compare_self_type<'tcx>(
ExplicitSelf::ByValue => "self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
_ => format!("self: {}", self_arg_ty),
_ => format!("self: {self_arg_ty}"),
}
})
};
@ -544,9 +544,9 @@ fn compare_self_type<'tcx>(
trait_m.name,
self_descr
);
err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
err.span_label(span, format!("trait method declared without `{}`", self_descr));
err.span_label(span, format!("trait method declared without `{self_descr}`"));
} else {
err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
}
@ -564,9 +564,9 @@ fn compare_self_type<'tcx>(
trait_m.name,
self_descr
);
err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr));
err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
err.span_label(span, format!("`{}` used in trait", self_descr));
err.span_label(span, format!("`{self_descr}` used in trait"));
} else {
err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
}
@ -668,7 +668,7 @@ fn compare_number_of_generics<'tcx>(
err.span_label(*span, "");
}
} else {
suffix = Some(format!(", expected {}", trait_count));
suffix = Some(format!(", expected {trait_count}"));
}
if let Some(span) = span {
@ -873,12 +873,10 @@ fn compare_synthetic_generics<'tcx>(
intravisit::walk_ty(self, ty);
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) =
ty.kind
&& let Res::Def(DefKind::TyParam, def_id) = path.res
&& def_id == self.1
{
if let Res::Def(DefKind::TyParam, def_id) = path.res {
if def_id == self.1 {
self.0 = Some(ty.span);
}
}
self.0 = Some(ty.span);
}
}
}
@ -908,7 +906,7 @@ fn compare_synthetic_generics<'tcx>(
// delete generic parameters
(impl_m.generics.span, String::new()),
// replace param usage with `impl Trait`
(span, format!("impl {}", bounds)),
(span, format!("impl {bounds}")),
],
Applicability::MaybeIncorrect,
);
@ -972,7 +970,7 @@ fn compare_const_param_types<'tcx>(
&format!(
"the const parameter{} has type `{}`, but the declaration \
in trait `{}` has type `{}`",
&impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)),
&impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{ident}`")),
impl_ty,
tcx.def_path_str(trait_m.def_id),
trait_ty

View file

@ -241,13 +241,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We are pointing at the binding's type or initializer value, but it's pattern
// is in a different line, so we point at both.
err.span_label(secondary_span, "expected due to the type of this binding");
err.span_label(primary_span, &format!("expected due to this{}", post_message));
err.span_label(primary_span, &format!("expected due to this{post_message}"));
} else if post_message == "" {
// We are pointing at either the assignment lhs or the binding def pattern.
err.span_label(primary_span, "expected due to the type of this binding");
} else {
// We are pointing at the binding's type or initializer value.
err.span_label(primary_span, &format!("expected due to this{}", post_message));
err.span_label(primary_span, &format!("expected due to this{post_message}"));
}
if !lhs.is_syntactic_place_expr() {
@ -321,7 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"try adding an expression at the end of the block",
return_suggestions
.into_iter()
.map(|r| format!("{}\n{}{}", semicolon, indent, r)),
.map(|r| format!("{semicolon}\n{indent}{r}")),
Applicability::MaybeIncorrect,
);
}
@ -344,10 +344,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let variant_path =
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
// FIXME #56861: DRYer prelude filtering
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
if let Some((_, path)) = path.split_once("::") {
return Some(path.to_string());
}
if let Some(path) = variant_path.strip_prefix("std::prelude::")
&& let Some((_, path)) = path.split_once("::")
{
return Some(path.to_string());
}
Some(variant_path)
} else {
@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect();
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!("{}: ", ident),
Some(ident) => format!("{ident}: "),
None => String::new(),
};
@ -366,9 +366,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
[variant] => {
// Just a single matching variant.
err.multipart_suggestion_verbose(
&format!("try wrapping the expression in `{}`", variant),
&format!("try wrapping the expression in `{variant}`"),
vec![
(expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)),
(expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
(expr.span.shrink_to_hi(), ")".to_string()),
],
Applicability::MaybeIncorrect,
@ -383,7 +383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
compatible_variants.into_iter().map(|variant| {
vec![
(expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)),
(expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
(expr.span.shrink_to_hi(), ")".to_string()),
]
}),
@ -680,7 +680,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ if is_range_literal(expr) => true,
_ => false,
};
let sugg_expr = if needs_parens { format!("({})", src) } else { src };
let sugg_expr = if needs_parens { format!("({src})") } else { src };
if let Some(sugg) = self.can_use_as_ref(expr) {
return Some((
@ -693,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!("{}: ", ident),
Some(ident) => format!("{ident}: "),
None => String::new(),
};
@ -727,14 +727,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Mutability::Mut => (
sp,
"consider mutably borrowing here".to_string(),
format!("{}&mut {}", prefix, sugg_expr),
format!("{prefix}&mut {sugg_expr}"),
Applicability::MachineApplicable,
false,
),
hir::Mutability::Not => (
sp,
"consider borrowing here".to_string(),
format!("{}&{}", prefix, sugg_expr),
format!("{prefix}&{sugg_expr}"),
Applicability::MachineApplicable,
false,
),
@ -758,29 +758,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(call_span) =
iter::successors(Some(expr.span), |s| s.parent_callsite())
.find(|&s| sp.contains(s))
&& sm.span_to_snippet(call_span).is_ok()
{
if sm.span_to_snippet(call_span).is_ok() {
return Some((
sp.with_hi(call_span.lo()),
"consider removing the borrow".to_string(),
String::new(),
Applicability::MachineApplicable,
true,
));
}
}
return None;
}
if sp.contains(expr.span) {
if sm.span_to_snippet(expr.span).is_ok() {
return Some((
sp.with_hi(expr.span.lo()),
sp.with_hi(call_span.lo()),
"consider removing the borrow".to_string(),
String::new(),
Applicability::MachineApplicable,
true,
));
}
return None;
}
if sp.contains(expr.span)
&& sm.span_to_snippet(expr.span).is_ok()
{
return Some((
sp.with_hi(expr.span.lo()),
"consider removing the borrow".to_string(),
String::new(),
Applicability::MachineApplicable,
true,
));
}
}
(
@ -788,66 +787,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&ty::RawPtr(TypeAndMut { ty: ty_b, mutbl: mutbl_b }),
&ty::Ref(_, ty_a, mutbl_a),
) => {
if let Some(steps) = self.deref_steps(ty_a, ty_b) {
if let Some(steps) = self.deref_steps(ty_a, ty_b)
// Only suggest valid if dereferencing needed.
if steps > 0 {
// The pointer type implements `Copy` trait so the suggestion is always valid.
if let Ok(src) = sm.span_to_snippet(sp) {
let derefs = "*".repeat(steps);
if let Some((span, src, applicability)) = match mutbl_b {
&& steps > 0
// The pointer type implements `Copy` trait so the suggestion is always valid.
&& let Ok(src) = sm.span_to_snippet(sp)
{
let derefs = "*".repeat(steps);
if let Some((span, src, applicability)) = match mutbl_b {
hir::Mutability::Mut => {
let new_prefix = "&mut ".to_owned() + &derefs;
match mutbl_a {
hir::Mutability::Mut => {
let new_prefix = "&mut ".to_owned() + &derefs;
match mutbl_a {
hir::Mutability::Mut => {
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(5);
let sp = sp.with_lo(pos).with_hi(pos);
(sp, derefs, Applicability::MachineApplicable)
})
}
hir::Mutability::Not => {
replace_prefix(&src, "&", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(1);
let sp = sp.with_lo(pos).with_hi(pos);
(
sp,
format!("mut {}", derefs),
Applicability::Unspecified,
)
})
}
}
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(5);
let sp = sp.with_lo(pos).with_hi(pos);
(sp, derefs, Applicability::MachineApplicable)
})
}
hir::Mutability::Not => {
let new_prefix = "&".to_owned() + &derefs;
match mutbl_a {
hir::Mutability::Mut => {
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
let lo = sp.lo() + BytePos(1);
let hi = sp.lo() + BytePos(5);
let sp = sp.with_lo(lo).with_hi(hi);
(sp, derefs, Applicability::MachineApplicable)
})
}
hir::Mutability::Not => {
replace_prefix(&src, "&", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(1);
let sp = sp.with_lo(pos).with_hi(pos);
(sp, derefs, Applicability::MachineApplicable)
})
}
}
replace_prefix(&src, "&", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(1);
let sp = sp.with_lo(pos).with_hi(pos);
(
sp,
format!("mut {derefs}"),
Applicability::Unspecified,
)
})
}
} {
return Some((
span,
"consider dereferencing".to_string(),
src,
applicability,
true,
));
}
}
hir::Mutability::Not => {
let new_prefix = "&".to_owned() + &derefs;
match mutbl_a {
hir::Mutability::Mut => {
replace_prefix(&src, "&mut ", &new_prefix).map(|_| {
let lo = sp.lo() + BytePos(1);
let hi = sp.lo() + BytePos(5);
let sp = sp.with_lo(lo).with_hi(hi);
(sp, derefs, Applicability::MachineApplicable)
})
}
hir::Mutability::Not => {
replace_prefix(&src, "&", &new_prefix).map(|_| {
let pos = sp.lo() + BytePos(1);
let sp = sp.with_lo(pos).with_hi(pos);
(sp, derefs, Applicability::MachineApplicable)
})
}
}
}
} {
return Some((
span,
"consider dereferencing".to_string(),
src,
applicability,
true,
));
}
}
}
@ -908,7 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Suggest removing `&` if we have removed any, otherwise suggest just
// dereferencing the remaining number of steps.
let message = if remove.is_empty() {
format!("consider {}", deref_kind)
format!("consider {deref_kind}")
} else {
format!(
"consider removing the `{}` and {} instead",
@ -918,7 +916,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!("{}: ", ident),
Some(ident) => format!("{ident}: "),
None => String::new(),
};
@ -994,35 +992,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
if let hir::ExprKind::Call(path, args) = &expr.kind {
if let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) =
if let hir::ExprKind::Call(path, args) = &expr.kind
&& let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) =
(&path.kind, args.len())
{
// `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697).
if let (hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)), sym::from) =
(&base_ty.kind, path_segment.ident.name)
{
if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() {
match ident.name {
sym::i128
| sym::i64
| sym::i32
| sym::i16
| sym::i8
| sym::u128
| sym::u64
| sym::u32
| sym::u16
| sym::u8
| sym::isize
| sym::usize
if base_ty_path.segments.len() == 1 =>
{
return false;
}
_ => {}
}
// `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697).
&& let (hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)), sym::from) =
(&base_ty.kind, path_segment.ident.name)
{
if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() {
match ident.name {
sym::i128
| sym::i64
| sym::i32
| sym::i16
| sym::i8
| sym::u128
| sym::u64
| sym::u32
| sym::u16
| sym::u8
| sym::isize
| sym::usize
if base_ty_path.segments.len() == 1 =>
{
return false;
}
_ => {}
}
}
}
@ -1042,8 +1037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty,
);
let lit_msg = format!(
"change the type of the numeric literal from `{}` to `{}`",
checked_ty, expected_ty,
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
);
let close_paren = if expr.precedence().order() < PREC_POSTFIX {
@ -1054,10 +1048,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let mut cast_suggestion = sugg.clone();
cast_suggestion
.push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty)));
cast_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren} as {expected_ty}")));
let mut into_suggestion = sugg.clone();
into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren)));
into_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren}.into()")));
let mut suffix_suggestion = sugg.clone();
suffix_suggestion.push((
if matches!(
@ -1074,7 +1067,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
if expr.precedence().order() < PREC_POSTFIX {
// Readd `)`
format!("{})", expected_ty)
format!("{expected_ty})")
} else {
expected_ty.to_string()
},
@ -1108,20 +1101,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(lhs_expr_and_src, exp_to_found_is_fallible)
{
let msg = format!(
"you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
lhs_src, expected_ty, checked_ty, src
"you can convert `{lhs_src}` from `{expected_ty}` to `{checked_ty}`, matching the type of `{src}`",
);
let suggestion = vec![
(lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)),
(lhs_expr.span.shrink_to_lo(), format!("{checked_ty}::from(")),
(lhs_expr.span.shrink_to_hi(), ")".to_string()),
];
(msg, suggestion)
} else {
let msg = format!("{} and panic if the converted value doesn't fit", msg);
let msg = format!("{msg} and panic if the converted value doesn't fit");
let mut suggestion = sugg.clone();
suggestion.push((
expr.span.shrink_to_hi(),
format!("{}.try_into().unwrap()", close_paren),
format!("{close_paren}.try_into().unwrap()"),
));
(msg, suggestion)
};
@ -1151,7 +1143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We now know that converting either the lhs or rhs is fallible. Before we
// suggest a fallible conversion, check if the value can never fit in the
// expected type.
let msg = format!("`{}` cannot fit into type `{}`", src, expected_ty);
let msg = format!("`{src}` cannot fit into type `{expected_ty}`");
err.note(&msg);
return;
} else if in_const_context {
@ -1229,7 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if can_cast {
// Missing try_into implementation for `f64` to `f32`
err.multipart_suggestion_verbose(
&format!("{}, producing the closest possible value", cast_msg),
&format!("{cast_msg}, producing the closest possible value"),
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
);
@ -1246,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if can_cast {
// Missing try_into implementation for `{float}` to `{integer}`
err.multipart_suggestion_verbose(
&format!("{}, rounding the float towards zero", msg),
&format!("{msg}, rounding the float towards zero"),
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
);
@ -1258,8 +1250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if exp.bit_width() > found.bit_width().unwrap_or(256) {
err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer",
msg,
"{msg}, producing the floating point representation of the integer",
),
into_suggestion,
Applicability::MachineApplicable,
@ -1274,9 +1265,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Missing try_into implementation for `{integer}` to `{float}`
err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer, \
"{cast_msg}, producing the floating point representation of the integer, \
rounded if necessary",
cast_msg,
),
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
@ -1321,7 +1311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&ty::Char,
) => {
err.multipart_suggestion_verbose(
&format!("{}, since a `char` always occupies 4 bytes", cast_msg,),
&format!("{cast_msg}, since a `char` always occupies 4 bytes"),
cast_suggestion,
Applicability::MachineApplicable,
);
@ -1333,22 +1323,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Report the type inferred by the return statement.
fn report_closure_inferred_return_type(&self, err: &mut Diagnostic, expected: Ty<'tcx>) {
if let Some(sp) = self.ret_coercion_span.get() {
if let Some(sp) = self.ret_coercion_span.get()
// If the closure has an explicit return type annotation, or if
// the closure's return type has been inferred from outside
// requirements (such as an Fn* trait bound), then a type error
// may occur at the first return expression we see in the closure
// (if it conflicts with the declared return type). Skip adding a
// note in this case, since it would be incorrect.
if !self.return_type_pre_known {
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
self.resolve_vars_if_possible(expected)
),
);
}
&& !self.return_type_pre_known
{
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
self.resolve_vars_if_possible(expected)
),
);
}
}
}

View file

@ -57,7 +57,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
let span = tcx.def_span(drop_impl_did);
let reported = tcx.sess.delay_span_bug(
span,
&format!("should have been rejected by coherence check: {}", dtor_self_type),
&format!("should have been rejected by coherence check: {dtor_self_type}"),
);
Err(reported)
}
@ -104,8 +104,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
item_span,
&format!(
"use the same sequence of generic type, lifetime and const parameters \
as the {} definition",
self_descr,
as the {self_descr} definition",
),
)
.emit();
@ -262,9 +261,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx.sess,
predicate_sp,
E0367,
"`Drop` impl requires `{}` but the {} it is implemented for does not",
predicate,
self_descr,
"`Drop` impl requires `{predicate}` but the {self_descr} it is implemented for does not",
)
.span_note(item_span, "the implementor must specify the same requirement")
.emit();

View file

@ -181,13 +181,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// make this code only run with -Zverbose because it is probably slow
if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
if !lint_str.contains('\n') {
debug!("expr text: {}", lint_str);
debug!("expr text: {lint_str}");
} else {
let mut lines = lint_str.lines();
if let Some(line0) = lines.next() {
let remaining_lines = lines.count();
debug!("expr text: {}", line0);
debug!("expr text: ...(and {} more lines)", remaining_lines);
debug!("expr text: {line0}");
debug!("expr text: ...(and {remaining_lines} more lines)");
}
}
}
@ -375,8 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.span,
oprnd_t,
E0614,
"type `{}` cannot be dereferenced",
oprnd_t,
"type `{oprnd_t}` cannot be dereferenced",
);
let sp = tcx.sess.source_map().start_point(expr.span);
if let Some(sp) =
@ -652,7 +651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion(
expr.span,
"give it a value of the expected type",
format!("break{} {}", label, val),
format!("break{label} {val}"),
Applicability::HasPlaceholders,
);
}
@ -780,7 +779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
db.span_label(
span,
format!("expected `{}` because of this return type", snippet),
format!("expected `{snippet}` because of this return type"),
);
}
},
@ -1611,15 +1610,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut truncated_fields_error = String::new();
let remaining_fields_names = match &displayable_field_names[..] {
[field1] => format!("`{}`", field1),
[field1, field2] => format!("`{}` and `{}`", field1, field2),
[field1, field2, field3] => format!("`{}`, `{}` and `{}`", field1, field2, field3),
[field1, field2] => format!("`{field1}` and `{field2}`"),
[field1, field2, field3] => format!("`{field1}`, `{field2}` and `{field3}`"),
_ => {
truncated_fields_error =
format!(" and {} other field{}", len - 3, pluralize!(len - 3));
displayable_field_names
.iter()
.take(3)
.map(|n| format!("`{}`", n))
.map(|n| format!("`{n}`"))
.collect::<Vec<_>>()
.join(", ")
}
@ -1635,10 +1634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
truncated_fields_error,
adt_ty
);
err.span_label(
span,
format!("missing {}{}", remaining_fields_names, truncated_fields_error),
);
err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));
// If the last field is a range literal, but it isn't supposed to be, then they probably
// meant to use functional update syntax.
@ -1693,8 +1689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.sess.span_err(
span,
&format!(
"cannot construct `{}` with struct literal syntax due to inaccessible fields",
adt_ty,
"cannot construct `{adt_ty}` with struct literal syntax due to inaccessible fields",
),
);
}
@ -1807,7 +1802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.span_label(
field.ident.span,
format!("`{}` does not have this field", ty),
format!("`{ty}` does not have this field"),
);
}
let available_field_names =
@ -1973,8 +1968,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field.span,
expr_t,
E0610,
"`{}` is a primitive type and therefore doesn't have fields",
expr_t
"`{expr_t}` is a primitive type and therefore doesn't have fields",
)
.emit();
}
@ -2018,7 +2012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
if add_label {
err.span_label(field_ident.span, &format!("field not found in `{}`", ty));
err.span_label(field_ident.span, &format!("field not found in `{ty}`"));
}
}
@ -2077,10 +2071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx().sess,
field.span,
E0616,
"field `{}` of {} `{}` is private",
field,
kind_name,
struct_path
"field `{field}` of {kind_name} `{struct_path}` is private",
);
err.span_label(field.span, "private field");
// Also check if an accessible method exists, which is often what is meant.
@ -2088,7 +2079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
self.suggest_method_call(
&mut err,
&format!("a method `{}` also exists, call it with parentheses", field),
&format!("a method `{field}` also exists, call it with parentheses"),
field,
expr_t,
expr,
@ -2104,9 +2095,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field.span,
expr_t,
E0615,
"attempted to take value of method `{}` on type `{}`",
field,
expr_t
"attempted to take value of method `{field}` on type `{expr_t}`",
);
err.span_label(field.span, "method, not a field");
let expr_is_call =
@ -2150,27 +2139,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
let mut found = false;
if let ty::RawPtr(ty_and_mut) = expr_t.kind() {
if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() {
if adt_def.variants().len() == 1
&& adt_def
.variants()
.iter()
.next()
.unwrap()
.fields
.iter()
.any(|f| f.ident(self.tcx) == field)
{
if let Some(dot_loc) = expr_snippet.rfind('.') {
found = true;
err.span_suggestion(
expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)),
"to access the field, dereference first",
format!("(*{})", &expr_snippet[0..dot_loc]),
Applicability::MaybeIncorrect,
);
}
if let ty::RawPtr(ty_and_mut) = expr_t.kind()
&& let ty::Adt(adt_def, _) = ty_and_mut.ty.kind()
{
if adt_def.variants().len() == 1
&& adt_def
.variants()
.iter()
.next()
.unwrap()
.fields
.iter()
.any(|f| f.ident(self.tcx) == field)
{
if let Some(dot_loc) = expr_snippet.rfind('.') {
found = true;
err.span_suggestion(
expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)),
"to access the field, dereference first",
format!("(*{})", &expr_snippet[0..dot_loc]),
Applicability::MaybeIncorrect,
);
}
}
}
@ -2197,7 +2186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let param_span = self.tcx.hir().span(param_hir_id);
let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local());
err.span_label(param_span, &format!("type parameter '{}' declared here", param_name));
err.span_label(param_span, &format!("type parameter '{param_name}' declared here"));
}
fn suggest_fields_on_recordish(
@ -2239,17 +2228,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
if let (Some(len), Ok(user_index)) =
(len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
{
if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
let help = "instead of using tuple indexing, use array indexing";
let suggestion = format!("{}[{}]", base, field);
let applicability = if len < user_index {
Applicability::MachineApplicable
} else {
Applicability::MaybeIncorrect
};
err.span_suggestion(expr.span, help, suggestion, applicability);
}
let help = "instead of using tuple indexing, use array indexing";
let suggestion = format!("{base}[{field}]");
let applicability = if len < user_index {
Applicability::MachineApplicable
} else {
Applicability::MaybeIncorrect
};
err.span_suggestion(expr.span, help, suggestion, applicability);
}
}
@ -2261,8 +2249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident,
) {
if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
let suggestion = format!("(*{}).{}", base, field);
let msg = format!("`{base}` is a raw pointer; try dereferencing it");
let suggestion = format!("(*{base}).{field}");
err.span_suggestion(expr.span, &msg, suggestion, Applicability::MaybeIncorrect);
}
}
@ -2281,9 +2269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field.span,
expr_t,
E0609,
"no field `{}` on type `{}`",
field,
expr_t
"no field `{field}` on type `{expr_t}`",
);
// try to add a suggestion in case the field is a nested field of a field of the Adt
@ -2307,7 +2293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
field.span.shrink_to_lo(),
"one of the expressions' fields has a field of the same name",
format!("{}.", field_path_str),
format!("{field_path_str}."),
Applicability::MaybeIncorrect,
);
}
@ -2419,8 +2405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.span,
base_t,
E0608,
"cannot index into a value of type `{}`",
base_t
"cannot index into a value of type `{base_t}`",
);
// Try to give some advice about indexing tuples.
if let ty::Tuple(..) = base_t.kind() {
@ -2434,7 +2419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion(
expr.span,
"to access tuple elements, use",
format!("{}.{}", snip, i),
format!("{snip}.{i}"),
Applicability::MachineApplicable,
);
needs_note = false;

View file

@ -415,8 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();
.flat_map(|id| tcx.hir().body(id).params)
;
for param in params {
spans.push_span_label(param.span, String::new());

View file

@ -646,7 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// now get all predicates in the same types as the where bounds, so we can chain them
let predicates_from_where =
where_predicates.iter().flatten().map(|bounds| bounds.iter()).flatten();
where_predicates.iter().flatten().flat_map(|bounds| bounds.iter());
// extract all bounds from the source code using their spans
let all_matching_bounds_strs = expected_generic_param

View file

@ -319,7 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
self.expr_count += 1;
if let PatKind::Binding(..) = pat.kind {
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
self.record(ty, pat.hir_id, Some(scope), None, pat.span, false);
}
@ -567,7 +567,7 @@ pub fn check_must_not_suspend_ty<'tcx>(
_ => None,
};
for (i, ty) in fields.iter().enumerate() {
let descr_post = &format!(" in tuple element {}", i);
let descr_post = &format!(" in tuple element {i}");
let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span);
if check_must_not_suspend_ty(
fcx,

View file

@ -484,14 +484,14 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
}
Err(_) => {
let msg =
format!("unrecognized platform-specific intrinsic function: `{}`", name);
format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, &msg).emit();
return;
}
}
}
_ => {
let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name);
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, &msg).emit();
return;
}

View file

@ -8,7 +8,7 @@ use rustc_errors::{
MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -1473,12 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn suggest_use_candidates(
&self,
err: &mut Diagnostic,
mut msg: String,
candidates: Vec<DefId>,
) {
fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
let parent_map = self.tcx.visible_parent_map(());
// Separate out candidates that must be imported with a glob, because they are named `_`
@ -1502,80 +1497,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
let module_did = self.tcx.parent_module(self.body_id);
let (span, found_use) = find_use_placement(self.tcx, module_did);
if let Some(span) = span {
let path_strings = candidates.iter().map(|trait_did| {
// Produce an additional newline to separate the new use statement
// from the directly following item.
let additional_newline = if found_use { "" } else { "\n" };
format!(
"use {};\n{}",
with_crate_prefix!(self.tcx.def_path_str(*trait_did)),
additional_newline
)
});
let (module, _, _) = self.tcx.hir().get_module(module_did);
let span = module.spans.inject_use_span;
let glob_path_strings = globs.iter().map(|trait_did| {
let parent_did = parent_map.get(trait_did).unwrap();
let path_strings = candidates.iter().map(|trait_did| {
format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
});
// Produce an additional newline to separate the new use statement
// from the directly following item.
let additional_newline = if found_use { "" } else { "\n" };
format!(
"use {}::*; // trait {}\n{}",
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
additional_newline
)
});
let glob_path_strings = globs.iter().map(|trait_did| {
let parent_did = parent_map.get(trait_did).unwrap();
format!(
"use {}::*; // trait {}\n",
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
)
});
err.span_suggestions(
span,
&msg,
path_strings.chain(glob_path_strings),
Applicability::MaybeIncorrect,
);
} else {
let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 };
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
if candidates.len() + globs.len() > 1 {
msg.push_str(&format!(
"\ncandidate #{}: `use {};`",
i + 1,
with_crate_prefix!(self.tcx.def_path_str(*trait_did))
));
} else {
msg.push_str(&format!(
"\n`use {};`",
with_crate_prefix!(self.tcx.def_path_str(*trait_did))
));
}
}
for (i, trait_did) in
globs.iter().take(limit.saturating_sub(candidates.len())).enumerate()
{
let parent_did = parent_map.get(trait_did).unwrap();
if candidates.len() + globs.len() > 1 {
msg.push_str(&format!(
"\ncandidate #{}: `use {}::*; // trait {}`",
candidates.len() + i + 1,
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
));
} else {
msg.push_str(&format!(
"\n`use {}::*; // trait {}`",
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
));
}
}
if candidates.len() > limit {
msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit));
}
err.note(&msg);
}
err.span_suggestions(
span,
&msg,
path_strings.chain(glob_path_strings),
Applicability::MaybeIncorrect,
);
}
fn suggest_valid_traits(
@ -2106,53 +2049,6 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
}
fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {
// FIXME(#94854): this code uses an out-of-date method for inferring a span
// to suggest. It would be better to thread the ModSpans from the AST into
// the HIR, and then use that to drive the suggestion here.
let mut span = None;
let mut found_use = false;
let (module, _, _) = tcx.hir().get_module(target_module);
// Find a `use` statement.
for &item_id in module.item_ids {
let item = tcx.hir().item(item_id);
match item.kind {
hir::ItemKind::Use(..) => {
// Don't suggest placing a `use` before the prelude
// import or other generated ones.
if !item.span.from_expansion() {
span = Some(item.span.shrink_to_lo());
found_use = true;
break;
}
}
// Don't place `use` before `extern crate`...
hir::ItemKind::ExternCrate(_) => {}
// ...but do place them before the first other item.
_ => {
if span.map_or(true, |span| item.span < span) {
if !item.span.from_expansion() {
span = Some(item.span.shrink_to_lo());
// Don't insert between attributes and an item.
let attrs = tcx.hir().attrs(item.hir_id());
// Find the first attribute on the item.
// FIXME: This is broken for active attributes.
for attr in attrs {
if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) {
span = Some(attr.span.shrink_to_lo());
}
}
}
}
}
}
}
(span, found_use)
}
fn print_disambiguation_help<'tcx>(
item_name: Ident,
args: Option<&'tcx [hir::Expr<'tcx>]>,

View file

@ -553,13 +553,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
// the consumer's responsibility to ensure all bytes that have been read
// have defined values.
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) {
if alloc.inner().relocations().len() != 0 {
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \
extra levels of indirection such as references";
tcx.sess.span_err(span, msg);
}
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
&& alloc.inner().relocations().len() != 0
{
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \
extra levels of indirection such as references";
tcx.sess.span_err(span, msg);
}
}
@ -587,7 +587,7 @@ fn report_forbidden_specialization(
));
}
Err(cname) => {
err.note(&format!("parent implementation is in crate `{}`", cname));
err.note(&format!("parent implementation is in crate `{cname}`"));
}
}
@ -610,10 +610,9 @@ fn missing_items_err(
tcx.sess,
impl_span,
E0046,
"not all trait items implemented, missing: `{}`",
missing_items_msg
"not all trait items implemented, missing: `{missing_items_msg}`",
);
err.span_label(impl_span, format!("missing `{}` in implementation", missing_items_msg));
err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation"));
// `Span` before impl block closing brace.
let hi = full_impl_span.hi() - BytePos(1);
@ -628,7 +627,7 @@ fn missing_items_err(
for trait_item in missing_items {
let snippet = suggestion_signature(trait_item, tcx);
let code = format!("{}{}\n{}", padding, snippet, padding);
let msg = format!("implement the missing item: `{}`", snippet);
let msg = format!("implement the missing item: `{snippet}`");
let appl = Applicability::HasPlaceholders;
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
err.span_label(span, format!("`{}` from trait", trait_item.name));
@ -653,10 +652,9 @@ fn missing_items_must_implement_one_of_err(
tcx.sess,
impl_span,
E0046,
"not all trait items implemented, missing one of: `{}`",
missing_items_msg
"not all trait items implemented, missing one of: `{missing_items_msg}`",
);
err.span_label(impl_span, format!("missing one of `{}` in implementation", missing_items_msg));
err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation"));
if let Some(annotation_span) = annotation_span {
err.span_note(annotation_span, "required because of this annotation");
@ -749,9 +747,10 @@ fn fn_sig_suggestion<'tcx>(
Some(match ty.kind() {
ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
ty::Ref(reg, ref_ty, mutability) if i == 0 => {
let reg = match &format!("{}", reg)[..] {
"'_" | "" => String::new(),
reg => format!("{} ", reg),
let reg = format!("{reg} ");
let reg = match &reg[..] {
"'_ " | " " => "",
reg => reg,
};
if assoc.fn_has_self_parameter {
match ref_ty.kind() {
@ -759,17 +758,17 @@ fn fn_sig_suggestion<'tcx>(
format!("&{}{}self", reg, mutability.prefix_str())
}
_ => format!("self: {}", ty),
_ => format!("self: {ty}"),
}
} else {
format!("_: {}", ty)
format!("_: {ty}")
}
}
_ => {
if assoc.fn_has_self_parameter && i == 0 {
format!("self: {}", ty)
format!("self: {ty}")
} else {
format!("_: {}", ty)
format!("_: {ty}")
}
}
})
@ -779,7 +778,7 @@ fn fn_sig_suggestion<'tcx>(
.collect::<Vec<String>>()
.join(", ");
let output = sig.output();
let output = if !output.is_unit() { format!(" -> {}", output) } else { String::new() };
let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
let unsafety = sig.unsafety.prefix_str();
let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
@ -789,10 +788,7 @@ fn fn_sig_suggestion<'tcx>(
// lifetimes between the `impl` and the `trait`, but this should be good enough to
// fill in a significant portion of the missing code, and other subsequent
// suggestions can help the user fix the code.
format!(
"{}fn {}{}({}){}{} {{ todo!() }}",
unsafety, ident, generics, args, output, where_clauses
)
format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
}
/// Return placeholder code for the given associated item.
@ -830,7 +826,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d
.map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
.collect();
let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
err.span_label(sp, &msg);
if let [start @ .., end] = &*variant_spans {
for variant_span in start {
@ -850,7 +846,7 @@ fn bad_non_zero_sized_fields<'tcx>(
field_spans: impl Iterator<Item = Span>,
sp: Span,
) {
let msg = format!("needs at most one non-zero-sized field, but has {}", field_count);
let msg = format!("needs at most one non-zero-sized field, but has {field_count}");
let mut err = struct_span_err!(
tcx.sess,
sp,
@ -877,7 +873,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
tcx.sess
.source_map()
.span_to_snippet(span)
.map_or_else(|_| String::new(), |s| format!(" `{}`", s)),
.map_or_else(|_| String::new(), |s| format!(" `{s}`",)),
)
.emit();
}

View file

@ -405,16 +405,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut pat_ty = ty;
if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
let expected = self.structurally_resolved_type(span, expected);
if let ty::Ref(_, inner_ty, _) = expected.kind() {
if matches!(inner_ty.kind(), ty::Slice(_)) {
let tcx = self.tcx;
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
self.typeck_results
.borrow_mut()
.treat_byte_string_as_slice
.insert(lt.hir_id.local_id);
pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8));
}
if let ty::Ref(_, inner_ty, _) = expected.kind()
&& matches!(inner_ty.kind(), ty::Slice(_))
{
let tcx = self.tcx;
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
self.typeck_results
.borrow_mut()
.treat_byte_string_as_slice
.insert(lt.hir_id.local_id);
pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8));
}
}
@ -481,14 +481,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Unify each side with `expected`.
// Subtyping doesn't matter here, as the value is some kind of scalar.
let demand_eqtype = |x: &mut _, y| {
if let Some((ref mut fail, x_ty, x_span)) = *x {
if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) {
if let Some((_, y_ty, y_span)) = y {
self.endpoint_has_type(&mut err, y_span, y_ty);
}
err.emit();
*fail = true;
};
if let Some((ref mut fail, x_ty, x_span)) = *x
&& let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
{
if let Some((_, y_ty, y_span)) = y {
self.endpoint_has_type(&mut err, y_span, y_ty);
}
err.emit();
*fail = true;
}
};
demand_eqtype(&mut lhs, rhs);
@ -630,7 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
let hir = self.tcx.hir();
let var_ty = self.resolve_vars_with_obligations(var_ty);
let msg = format!("first introduced with type `{}` here", var_ty);
let msg = format!("first introduced with type `{var_ty}` here");
err.span_label(hir.span(var_id), msg);
let in_match = hir.parent_iter(var_id).any(|(_, n)| {
matches!(
@ -665,8 +665,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
err.span_suggestion(
*span,
&format!("did you mean `{}`", snippet),
format!(" &{}", expected),
&format!("did you mean `{snippet}`"),
format!(" &{expected}"),
Applicability::MachineApplicable,
);
}
@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"type `{}` cannot be dereferenced",
type_str
);
err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
}
@ -918,7 +918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path_str
);
let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}");
match res {
Res::Def(DefKind::Fn | DefKind::AssocFn, _) => {
err.span_label(pat.span, "`fn` calls are not allowed in patterns");
@ -1396,8 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.sess,
pat.span,
E0769,
"tuple variant `{}` written as struct variant",
path
"tuple variant `{path}` written as struct variant",
);
err.span_suggestion_verbose(
qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
@ -1422,8 +1421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sess,
pat.span,
E0638,
"`..` required with {} marked as non-exhaustive",
descr
"`..` required with {descr} marked as non-exhaustive",
);
err.span_suggestion_verbose(
sp_comma,
@ -1442,8 +1440,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"field `{}` bound multiple times in the pattern",
ident
)
.span_label(span, format!("multiple uses of `{}` in pattern", ident))
.span_label(other_field, format!("first use of `{}`", ident))
.span_label(span, format!("multiple uses of `{ident}` in pattern"))
.span_label(other_field, format!("first use of `{ident}`"))
.emit();
}

View file

@ -74,9 +74,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.resolve_vars_if_possible(ty);
let mut err = self.tcx.sess.struct_span_err(
span,
&format!("negative integers cannot be used to index on a `{}`", ty),
&format!("negative integers cannot be used to index on a `{ty}`"),
);
err.span_label(span, &format!("cannot use a negative integer for indexing on `{}`", ty));
err.span_label(span, &format!("cannot use a negative integer for indexing on `{ty}`"));
if let (hir::ExprKind::Path(..), Ok(snippet)) =
(&base_expr.kind, self.tcx.sess.source_map().span_to_snippet(base_expr.span))
{
@ -84,10 +84,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
span.shrink_to_lo(),
&format!(
"to access an element starting from the end of the `{}`, compute the index",
ty,
"to access an element starting from the end of the `{ty}`, compute the index",
),
format!("{}.len() ", snippet),
format!("{snippet}.len() "),
Applicability::MachineApplicable,
);
}
@ -314,32 +313,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id);
if let Some(mut adjustments) = previous_adjustments {
for adjustment in &mut adjustments {
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind {
if let Some(ok) = self.try_mutable_overloaded_place_op(
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind
&& let Some(ok) = self.try_mutable_overloaded_place_op(
expr.span,
source,
&[],
PlaceOp::Deref,
) {
let method = self.register_infer_ok_obligations(ok);
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
*deref = OverloadedDeref { region, mutbl, span: deref.span };
}
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
// This helps avoid accidental drops.
if inside_union
&& source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
{
let mut err = self.tcx.sess.struct_span_err(
expr.span,
"not automatically applying `DerefMut` on `ManuallyDrop` union field",
);
err.help(
"writing to this reference calls the destructor for the old value",
);
err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
err.emit();
}
)
{
let method = self.register_infer_ok_obligations(ok);
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
*deref = OverloadedDeref { region, mutbl, span: deref.span };
}
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
// This helps avoid accidental drops.
if inside_union
&& source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
{
let mut err = self.tcx.sess.struct_span_err(
expr.span,
"not automatically applying `DerefMut` on `ManuallyDrop` union field",
);
err.help(
"writing to this reference calls the destructor for the old value",
);
err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
err.emit();
}
}
source = adjustment.target;

View file

@ -317,13 +317,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.body_id = body_id.hir_id;
self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
let fn_sig = {
match self.typeck_results.borrow().liberated_fn_sigs().get(id) {
Some(f) => *f,
None => {
bug!("No fn-sig entry for id={:?}", id);
}
}
let Some(fn_sig) = self.typeck_results.borrow().liberated_fn_sigs().get(id) else {
bug!("No fn-sig entry for id={:?}", id);
};
// Collect the types from which we create inferred bounds.
@ -642,12 +637,9 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
ignore_err!(self.with_mc(|mc| {
mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id, .. }| {
// `ref x` pattern
if let PatKind::Binding(..) = kind {
if let Some(ty::BindByReference(mutbl)) =
mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span)
{
self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt);
}
if let PatKind::Binding(..) = kind
&& let Some(ty::BindByReference(mutbl)) = mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span) {
self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt);
}
})
}));

View file

@ -862,7 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diagnostics_builder.span_suggestion(
closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(),
&diagnostic_msg,
format!("\n{}{};", indent, migration_string),
format!("\n{indent}{migration_string};"),
Applicability::MachineApplicable,
);
} else if line1.starts_with('{') {
@ -873,7 +873,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diagnostics_builder.span_suggestion(
closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(),
&diagnostic_msg,
format!(" {};", migration_string),
format!(" {migration_string};"),
Applicability::MachineApplicable,
);
} else {
@ -882,7 +882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diagnostics_builder.multipart_suggestion(
&diagnostic_msg,
vec![
(closure_body_span.shrink_to_lo(), format!("{{ {}; ", migration_string)),
(closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")),
(closure_body_span.shrink_to_hi(), " }".to_string()),
],
Applicability::MachineApplicable
@ -1527,7 +1527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.sess.struct_span_err(closure_span, "First Pass analysis includes:");
for (place, capture_info) in capture_information {
let capture_str = construct_capture_info_string(self.tcx, place, capture_info);
let output_str = format!("Capturing {}", capture_str);
let output_str = format!("Capturing {capture_str}");
let span =
capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
@ -1552,7 +1552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let capture_str =
construct_capture_info_string(self.tcx, place, capture_info);
let output_str = format!("Min Capture {}", capture_str);
let output_str = format!("Min Capture {capture_str}");
if capture.info.path_expr_id != capture.info.capture_kind_expr_id {
let path_span = capture_info
@ -1969,7 +1969,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
projections_str.push_str(proj.as_str());
}
format!("{}[{}]", variable_name, projections_str)
format!("{variable_name}[{projections_str}]")
}
fn construct_capture_kind_reason_string<'tcx>(
@ -1984,13 +1984,13 @@ fn construct_capture_kind_reason_string<'tcx>(
ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
};
format!("{} captured as {} here", place_str, capture_kind_str)
format!("{place_str} captured as {capture_kind_str} here")
}
fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
let place_str = construct_place_string(tcx, place);
format!("{} used here", place_str)
format!("{place_str} used here")
}
fn construct_capture_info_string<'tcx>(
@ -2004,7 +2004,7 @@ fn construct_capture_info_string<'tcx>(
ty::UpvarCapture::ByValue => "ByValue".into(),
ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
};
format!("{} -> {}", place_str, capture_kind_str)
format!("{place_str} -> {capture_kind_str}")
}
fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
@ -2035,16 +2035,16 @@ fn migration_suggestion_for_2229(
.collect::<Vec<_>>();
let migration_ref_concat =
need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
need_migrations_variables.iter().map(|v| format!("&{v}")).collect::<Vec<_>>().join(", ");
let migration_string = if 1 == need_migrations.len() {
format!("let _ = {}", migration_ref_concat)
format!("let _ = {migration_ref_concat}")
} else {
format!("let _ = ({})", migration_ref_concat)
format!("let _ = ({migration_ref_concat})")
};
let migrated_variables_concat =
need_migrations_variables.iter().map(|v| format!("`{}`", v)).collect::<Vec<_>>().join(", ");
need_migrations_variables.iter().map(|v| format!("`{v}`")).collect::<Vec<_>>().join(", ");
(migration_string, migrated_variables_concat)
}

View file

@ -230,8 +230,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
.struct_span_err(
self_ty.span,
&format!(
"first argument of `call` in `{}` lang item must be a reference",
fn_lang_item_name
"first argument of `call` in `{fn_lang_item_name}` lang item must be a reference",
),
)
.emit();
@ -241,8 +240,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
.struct_span_err(
*span,
&format!(
"`call` function in `{}` lang item takes exactly two arguments",
fn_lang_item_name
"`call` function in `{fn_lang_item_name}` lang item takes exactly two arguments",
),
)
.emit();
@ -252,8 +250,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
.struct_span_err(
trait_item.span,
&format!(
"`call` trait item in `{}` lang item must be a function",
fn_lang_item_name
"`call` trait item in `{fn_lang_item_name}` lang item must be a function",
),
)
.emit();
@ -432,7 +429,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
);
err.span_suggestion(
gat_item_hir.generics.where_clause.tail_span_for_suggestion(),
&format!("add the required where clause{}", plural),
&format!("add the required where clause{plural}"),
suggestion,
Applicability::MachineApplicable,
);
@ -523,7 +520,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
// In our example, requires that `Self: 'a`
if ty_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *ty, *region_a) {
debug!(?ty_idx, ?region_a_idx);
debug!("required clause: {} must outlive {}", ty, region_a);
debug!("required clause: {ty} must outlive {region_a}");
// Translate into the generic parameters of the GAT. In
// our example, the type was `Self`, which will also be
// `Self` in the GAT.
@ -560,7 +557,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
}
if region_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *region_a, *region_b) {
debug!(?region_a_idx, ?region_b_idx);
debug!("required clause: {} must outlive {}", region_a, region_b);
debug!("required clause: {region_a} must outlive {region_b}");
// Translate into the generic parameters of the GAT.
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
let region_a_param =
@ -869,7 +866,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
)
.span_label(
hir_ty.span,
format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
)
.emit();
}
@ -884,7 +881,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
ty::RawPtr(_) => Some("raw pointers"),
_ => {
is_ptr = false;
err_ty_str = format!("`{}`", ty);
err_ty_str = format!("`{ty}`");
Some(err_ty_str.as_str())
}
};
@ -894,16 +891,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
tcx.sess.span_err(
hir_ty.span,
&format!(
"using {} as const generic parameters is forbidden",
unsupported_type
"using {unsupported_type} as const generic parameters is forbidden",
),
);
} else {
let mut err = tcx.sess.struct_span_err(
hir_ty.span,
&format!(
"{} is forbidden as the type of a const generic parameter",
unsupported_type
"{unsupported_type} is forbidden as the type of a const generic parameter",
),
);
err.note("the only supported types are integers, `bool` and `char`");
@ -1567,9 +1562,8 @@ fn check_method_receiver<'fcx, 'tcx>(
sym::arbitrary_self_types,
span,
&format!(
"`{}` cannot be used as the type of `self` without \
"`{receiver_ty}` cannot be used as the type of `self` without \
the `arbitrary_self_types` feature",
receiver_ty,
),
)
.help(HELP_FOR_SELF_TYPE)
@ -1587,8 +1581,7 @@ fn e0307<'tcx>(fcx: &FnCtxt<'_, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
fcx.tcx.sess.diagnostic(),
span,
E0307,
"invalid `self` parameter type: {}",
receiver_ty,
"invalid `self` parameter type: {receiver_ty}"
)
.note("type of `self` must be `Self` or a type that dereferences to it")
.help(HELP_FOR_SELF_TYPE)
@ -1793,7 +1786,7 @@ fn report_bivariance(
tcx.def_path_str(def_id),
)
} else {
format!("consider removing `{}` or referring to it in a field", param_name)
format!("consider removing `{param_name}` or referring to it in a field")
};
err.help(&msg);
@ -1993,8 +1986,7 @@ fn error_392(
span: Span,
param_name: Symbol,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut err =
struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name);
let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{param_name}` is never used");
err.span_label(span, "unused parameter");
err
}

View file

@ -319,6 +319,42 @@ fn test_is_subset() {
assert_eq!(is_subset(&[99, 100], &large), false);
}
#[test]
fn test_is_superset() {
fn is_superset(a: &[i32], b: &[i32]) -> bool {
let set_a = BTreeSet::from_iter(a.iter());
let set_b = BTreeSet::from_iter(b.iter());
set_a.is_superset(&set_b)
}
assert_eq!(is_superset(&[], &[]), true);
assert_eq!(is_superset(&[], &[1, 2]), false);
assert_eq!(is_superset(&[0], &[1, 2]), false);
assert_eq!(is_superset(&[1], &[1, 2]), false);
assert_eq!(is_superset(&[4], &[1, 2]), false);
assert_eq!(is_superset(&[1, 4], &[1, 2]), false);
assert_eq!(is_superset(&[1, 2], &[1, 2]), true);
assert_eq!(is_superset(&[1, 2, 3], &[1, 3]), true);
assert_eq!(is_superset(&[1, 2, 3], &[]), true);
assert_eq!(is_superset(&[-1, 1, 2, 3], &[-1, 3]), true);
if cfg!(miri) {
// Miri is too slow
return;
}
let large = Vec::from_iter(0..100);
assert_eq!(is_superset(&[], &large), false);
assert_eq!(is_superset(&large, &[]), true);
assert_eq!(is_superset(&large, &[1]), true);
assert_eq!(is_superset(&large, &[50, 99]), true);
assert_eq!(is_superset(&large, &[100]), false);
assert_eq!(is_superset(&large, &[0, 99]), true);
assert_eq!(is_superset(&[-1], &large), false);
assert_eq!(is_superset(&[0], &large), false);
assert_eq!(is_superset(&[99, 100], &large), false);
}
#[test]
fn test_retain() {
let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
@ -391,6 +427,26 @@ fn test_clear() {
x.clear();
assert!(x.is_empty());
}
#[test]
fn test_remove() {
let mut x = BTreeSet::new();
assert!(x.is_empty());
x.insert(1);
x.insert(2);
x.insert(3);
x.insert(4);
assert_eq!(x.remove(&2), true);
assert_eq!(x.remove(&0), false);
assert_eq!(x.remove(&5), false);
assert_eq!(x.remove(&1), true);
assert_eq!(x.remove(&2), false);
assert_eq!(x.remove(&3), true);
assert_eq!(x.remove(&4), true);
assert_eq!(x.remove(&4), false);
assert!(x.is_empty());
}
#[test]
fn test_zip() {

View file

@ -52,6 +52,23 @@
/// This trait can be used with `#[derive]` if all of the type's fields implement
/// `Default`. When `derive`d, it will use the default value for each field's type.
///
/// ### `enum`s
///
/// When using `#[derive(Default)]` on an `enum`, you need to choose which unit variant will be
/// default. You do this by placing the `#[default]` attribute on the variant.
///
/// ```
/// #[derive(Default)]
/// enum Kind {
/// #[default]
/// A,
/// B,
/// C,
/// }
/// ```
///
/// You cannot use the `#[default]` attribute on non-unit or non-exhaustive variants.
///
/// ## How can I implement `Default`?
///
/// Provide an implementation for the `default()` method that returns the value of

View file

@ -167,7 +167,7 @@
#![feature(const_precise_live_drops)]
#![feature(const_refs_to_cell)]
#![feature(decl_macro)]
#![feature(derive_default_enum)]
#![cfg_attr(bootstrap, feature(derive_default_enum))]
#![feature(deprecated_suggestion)]
#![feature(doc_cfg)]
#![feature(doc_notable_trait)]

View file

@ -45,3 +45,13 @@ pub mod rust_2021 {
#[doc(no_inline)]
pub use crate::convert::{TryFrom, TryInto};
}
/// The 2024 edition of the core prelude.
///
/// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2024", issue = "none")]
pub mod rust_2024 {
#[unstable(feature = "prelude_2024", issue = "none")]
#[doc(no_inline)]
pub use super::rust_2021::*;
}

View file

@ -279,6 +279,7 @@
#![feature(panic_info_message)]
#![feature(panic_internals)]
#![feature(portable_simd)]
#![feature(prelude_2024)]
#![feature(ptr_as_uninit)]
#![feature(raw_os_nonzero)]
#![feature(slice_internals)]

View file

@ -132,3 +132,17 @@ pub mod rust_2021 {
#[doc(no_inline)]
pub use core::prelude::rust_2021::*;
}
/// The 2024 version of the prelude of The Rust Standard Library.
///
/// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2024", issue = "none")]
pub mod rust_2024 {
#[unstable(feature = "prelude_2024", issue = "none")]
#[doc(no_inline)]
pub use super::v1::*;
#[unstable(feature = "prelude_2024", issue = "none")]
#[doc(no_inline)]
pub use core::prelude::rust_2024::*;
}

View file

@ -4,7 +4,7 @@
all(target_os = "emscripten", target_feature = "atomics")
))]
use crate::sync::atomic::AtomicI32;
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
/// Wait for a futex_wake operation to wake us.
@ -13,7 +13,7 @@ use crate::time::Duration;
///
/// Returns false on timeout, and true in all other cases.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -> bool {
pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
use super::time::Timespec;
use crate::ptr::null;
use crate::sync::atomic::Ordering::Relaxed;
@ -35,7 +35,7 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -
let r = unsafe {
libc::syscall(
libc::SYS_futex,
futex as *const AtomicI32,
futex as *const AtomicU32,
libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG,
expected,
timespec.as_ref().map_or(null(), |t| &t.t as *const libc::timespec),
@ -53,10 +53,10 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -
}
#[cfg(target_os = "emscripten")]
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
extern "C" {
fn emscripten_futex_wait(
addr: *const AtomicI32,
addr: *const AtomicU32,
val: libc::c_uint,
max_wait_ms: libc::c_double,
) -> libc::c_int;
@ -64,10 +64,8 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
unsafe {
emscripten_futex_wait(
futex as *const AtomicI32,
// `val` is declared unsigned to match the Emscripten headers, but since it's used as
// an opaque value, we can ignore the meaning of signed vs. unsigned and cast here.
expected as libc::c_uint,
futex,
expected,
timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0),
);
}
@ -78,11 +76,11 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
/// Returns true if this actually woke up such a thread,
/// or false if no thread was waiting on this futex.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wake(futex: &AtomicI32) -> bool {
pub fn futex_wake(futex: &AtomicU32) -> bool {
unsafe {
libc::syscall(
libc::SYS_futex,
futex as *const AtomicI32,
futex as *const AtomicU32,
libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
1,
) > 0
@ -91,11 +89,11 @@ pub fn futex_wake(futex: &AtomicI32) -> bool {
/// Wake up all threads that are waiting on futex_wait on this futex.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wake_all(futex: &AtomicI32) {
pub fn futex_wake_all(futex: &AtomicU32) {
unsafe {
libc::syscall(
libc::SYS_futex,
futex as *const AtomicI32,
futex as *const AtomicU32,
libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
i32::MAX,
);
@ -103,10 +101,10 @@ pub fn futex_wake_all(futex: &AtomicI32) {
}
#[cfg(target_os = "emscripten")]
pub fn futex_wake(futex: &AtomicI32) -> bool {
pub fn futex_wake(futex: &AtomicU32) -> bool {
extern "C" {
fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int;
fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
}
unsafe { emscripten_futex_wake(futex as *const AtomicI32, 1) > 0 }
unsafe { emscripten_futex_wake(futex, 1) > 0 }
}

View file

@ -1,6 +1,6 @@
use crate::cell::UnsafeCell;
use crate::sync::atomic::{
AtomicI32, AtomicUsize,
AtomicU32, AtomicUsize,
Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
@ -13,13 +13,13 @@ pub struct Mutex {
/// 0: unlocked
/// 1: locked, no other threads waiting
/// 2: locked, and other threads waiting (contended)
futex: AtomicI32,
futex: AtomicU32,
}
impl Mutex {
#[inline]
pub const fn new() -> Self {
Self { futex: AtomicI32::new(0) }
Self { futex: AtomicU32::new(0) }
}
#[inline]
@ -71,7 +71,7 @@ impl Mutex {
}
}
fn spin(&self) -> i32 {
fn spin(&self) -> u32 {
let mut spin = 100;
loop {
// We only use `load` (and not `swap` or `compare_exchange`)
@ -110,13 +110,13 @@ pub struct Condvar {
// The value of this atomic is simply incremented on every notification.
// This is used by `.wait()` to not miss any notifications after
// unlocking the mutex and before waiting for notifications.
futex: AtomicI32,
futex: AtomicU32,
}
impl Condvar {
#[inline]
pub const fn new() -> Self {
Self { futex: AtomicI32::new(0) }
Self { futex: AtomicU32::new(0) }
}
#[inline]

View file

@ -1,5 +1,5 @@
use crate::sync::atomic::{
AtomicI32,
AtomicU32,
Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
@ -14,36 +14,36 @@ pub struct RwLock {
// 0x3FFF_FFFF: Write locked
// Bit 30: Readers are waiting on this futex.
// Bit 31: Writers are waiting on the writer_notify futex.
state: AtomicI32,
state: AtomicU32,
// The 'condition variable' to notify writers through.
// Incremented on every signal.
writer_notify: AtomicI32,
writer_notify: AtomicU32,
}
const READ_LOCKED: i32 = 1;
const MASK: i32 = (1 << 30) - 1;
const WRITE_LOCKED: i32 = MASK;
const MAX_READERS: i32 = MASK - 1;
const READERS_WAITING: i32 = 1 << 30;
const WRITERS_WAITING: i32 = 1 << 31;
const READ_LOCKED: u32 = 1;
const MASK: u32 = (1 << 30) - 1;
const WRITE_LOCKED: u32 = MASK;
const MAX_READERS: u32 = MASK - 1;
const READERS_WAITING: u32 = 1 << 30;
const WRITERS_WAITING: u32 = 1 << 31;
fn is_unlocked(state: i32) -> bool {
fn is_unlocked(state: u32) -> bool {
state & MASK == 0
}
fn is_write_locked(state: i32) -> bool {
fn is_write_locked(state: u32) -> bool {
state & MASK == WRITE_LOCKED
}
fn has_readers_waiting(state: i32) -> bool {
fn has_readers_waiting(state: u32) -> bool {
state & READERS_WAITING != 0
}
fn has_writers_waiting(state: i32) -> bool {
fn has_writers_waiting(state: u32) -> bool {
state & WRITERS_WAITING != 0
}
fn is_read_lockable(state: i32) -> bool {
fn is_read_lockable(state: u32) -> bool {
// This also returns false if the counter could overflow if we tried to read lock it.
//
// We don't allow read-locking if there's readers waiting, even if the lock is unlocked
@ -53,14 +53,14 @@ fn is_read_lockable(state: i32) -> bool {
state & MASK < MAX_READERS && !has_readers_waiting(state) && !has_writers_waiting(state)
}
fn has_reached_max_readers(state: i32) -> bool {
fn has_reached_max_readers(state: u32) -> bool {
state & MASK == MAX_READERS
}
impl RwLock {
#[inline]
pub const fn new() -> Self {
Self { state: AtomicI32::new(0), writer_notify: AtomicI32::new(0) }
Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) }
}
#[inline]
@ -227,7 +227,7 @@ impl RwLock {
/// If both are waiting, this will wake up only one writer, but will fall
/// back to waking up readers if there was no writer to wake up.
#[cold]
fn wake_writer_or_readers(&self, mut state: i32) {
fn wake_writer_or_readers(&self, mut state: u32) {
assert!(is_unlocked(state));
// The readers waiting bit might be turned on at any point now,
@ -287,7 +287,7 @@ impl RwLock {
}
/// Spin for a while, but stop directly at the given condition.
fn spin_until(&self, f: impl Fn(i32) -> bool) -> i32 {
fn spin_until(&self, f: impl Fn(u32) -> bool) -> u32 {
let mut spin = 100; // Chosen by fair dice roll.
loop {
let state = self.state.load(Relaxed);
@ -299,12 +299,12 @@ impl RwLock {
}
}
fn spin_write(&self) -> i32 {
fn spin_write(&self) -> u32 {
// Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair.
self.spin_until(|state| is_unlocked(state) || has_writers_waiting(state))
}
fn spin_read(&self) -> i32 {
fn spin_read(&self) -> u32 {
// Stop spinning when it's unlocked or read locked, or when there's waiting threads.
self.spin_until(|state| {
!is_write_locked(state) || has_readers_waiting(state) || has_writers_waiting(state)

View file

@ -1,17 +1,21 @@
use crate::arch::wasm32;
use crate::convert::TryInto;
use crate::sync::atomic::AtomicI32;
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
unsafe {
wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout);
wasm32::memory_atomic_wait32(
futex as *const AtomicU32 as *mut i32,
expected as i32,
timeout,
);
}
}
pub fn futex_wake(futex: &AtomicI32) {
pub fn futex_wake(futex: &AtomicU32) {
unsafe {
wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1);
wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1);
}
}

View file

@ -1,14 +1,14 @@
use crate::sync::atomic::AtomicI32;
use crate::sync::atomic::AtomicU32;
use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::sys::futex::{futex_wait, futex_wake};
use crate::time::Duration;
const PARKED: i32 = -1;
const EMPTY: i32 = 0;
const NOTIFIED: i32 = 1;
const PARKED: u32 = u32::MAX;
const EMPTY: u32 = 0;
const NOTIFIED: u32 = 1;
pub struct Parker {
state: AtomicI32,
state: AtomicU32,
}
// Notes about memory ordering:
@ -34,7 +34,7 @@ pub struct Parker {
impl Parker {
#[inline]
pub const fn new() -> Self {
Parker { state: AtomicI32::new(EMPTY) }
Parker { state: AtomicU32::new(EMPTY) }
}
// Assumes this is only called by the thread that owns the Parker,

View file

@ -15,7 +15,8 @@ fn it_works() {
```
Tests "pass" if they return without an error. They "fail" if they [panic], or
return a [`Result`] with an error.
return a type such as [`Result`] that implements the [`Termination`] trait
with a non-zero value.
By passing the [`--test` option] to `rustc`, the compiler will build the crate
in a special mode to construct an executable that will run the tests in the
@ -304,6 +305,7 @@ Experimental support for using custom test harnesses is available on the
[`libtest`]: ../../test/index.html
[`main` function]: ../../reference/crates-and-source-files.html#main-functions
[`Result`]: ../../std/result/index.html
[`Termination`]: ../../std/process/trait.Termination.html
[`test` cfg option]: ../../reference/conditional-compilation.html#test
[attribute-ignore]: ../../reference/attributes/testing.html#the-ignore-attribute
[attribute-should_panic]: ../../reference/attributes/testing.html#the-should_panic-attribute

View file

@ -119,11 +119,14 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
// To make the difference between "mod foo {}" and "mod foo;". In case we "import" another
// file, we want to link to it. Otherwise no need to create a link.
if !span.overlaps(m.inner) {
if !span.overlaps(m.spans.inner_span) {
// Now that we confirmed it's a file import, we want to get the span for the module
// name only and not all the "mod foo;".
if let Some(Node::Item(item)) = self.tcx.hir().find(id) {
self.matches.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner)));
self.matches.insert(
item.ident.span,
LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)),
);
}
}
intravisit::walk_mod(self, m, id);

View file

@ -154,7 +154,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
m: &'tcx hir::Mod<'tcx>,
name: Symbol,
) -> Module<'tcx> {
let mut om = Module::new(name, id, m.inner);
let mut om = Module::new(name, id, m.spans.inner_span);
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
// Keep track of if there were any private modules in the path.
let orig_inside_public_path = self.inside_public_path;

View file

@ -1,7 +1,5 @@
// run-pass
#![feature(derive_default_enum)]
// nb: does not impl Default
#[derive(Debug, PartialEq)]
struct NotDefault;

View file

@ -5,7 +5,6 @@
#![feature(lang_items)]
#![feature(no_core)]
#![feature(rustc_attrs)]
#![feature(derive_default_enum)]
#![no_core]

View file

@ -1,7 +0,0 @@
#[derive(Default)] //~ ERROR deriving `Default` on enums is experimental
enum Foo {
#[default]
Alpha,
}
fn main() {}

View file

@ -1,13 +0,0 @@
error[E0658]: deriving `Default` on enums is experimental
--> $DIR/feature-gate-derive_default_enum.rs:1:10
|
LL | #[derive(Default)]
| ^^^^^^^
|
= note: see issue #86985 <https://github.com/rust-lang/rust/issues/86985> for more information
= help: add `#![feature(derive_default_enum)]` to the crate attributes to enable
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -8,15 +8,7 @@ where
//~^ ERROR cannot find type `T` in this scope
//~| NOTE not found in this scope
{
// The part where it claims that there is no method named `len` is a bug. Feel free to fix it.
// This test is intended to ensure that a different bug, where it claimed
// that `v` was a function, does not regress.
fn method(v: Vec<u8>) { v.len(); }
//~^ ERROR type annotations needed
//~| NOTE cannot infer type
//~| NOTE type must be known at this point
//~| ERROR no method named `len`
//~| NOTE private field, not a method
}
fn main() {}

View file

@ -12,21 +12,6 @@ error[E0412]: cannot find type `T` in this scope
LL | T: Copy,
| ^ not found in this scope
error[E0282]: type annotations needed
--> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31
|
LL | fn method(v: Vec<u8>) { v.len(); }
| ^^^ cannot infer type
|
= note: type must be known at this point
error: aborting due to 2 previous errors
error[E0599]: no method named `len` found for struct `Vec<u8>` in the current scope
--> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31
|
LL | fn method(v: Vec<u8>) { v.len(); }
| ^^^ private field, not a method
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0282, E0412, E0599.
For more information about an error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0412`.

View file

@ -1,5 +1,12 @@
// run-pass
// revisions: e2015 e2018 e2021 e2024
pub fn main() {
println!("hello, world");
//[e2018] edition:2018
//[e2021] edition:2021
//[e2024] edition:2024
//[e2024] compile-flags: -Zunstable-options
fn main() {
println!("hello");
}

View file

@ -1,6 +0,0 @@
// run-pass
// edition:2021
fn main() {
println!("hello, 2021");
}

View file

@ -4,10 +4,10 @@
* This crate declares two public paths, `m::Tr` and `prelude::_`. Make sure we prefer the former.
*/
extern crate overlapping_pub_trait_source;
//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
//~| SUGGESTION overlapping_pub_trait_source::m::Tr
fn main() {
//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
//~| SUGGESTION overlapping_pub_trait_source::m::Tr
use overlapping_pub_trait_source::S;
S.method();
//~^ ERROR no method named `method` found for struct `S` in the current scope [E0599]

View file

@ -5,10 +5,10 @@
* importing it by name, and instead we suggest importing it by glob.
*/
extern crate unnamed_pub_trait_source;
//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
//~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr
fn main() {
//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
//~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr
use unnamed_pub_trait_source::S;
S.method();
//~^ ERROR no method named `method` found for struct `S` in the current scope [E0599]

View file

@ -5,7 +5,6 @@
#![feature(trace_macros, concat_idents)]
#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)]
#![feature(derive_default_enum)]
use std::arch::asm;

View file

@ -1,41 +1,41 @@
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:14:5
--> $DIR/macros-nonfatal-errors.rs:13:5
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:19:36
--> $DIR/macros-nonfatal-errors.rs:18:36
|
LL | struct DefaultInnerAttrTupleStruct(#[default] ());
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:23:1
--> $DIR/macros-nonfatal-errors.rs:22:1
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:27:1
--> $DIR/macros-nonfatal-errors.rs:26:1
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:37:11
--> $DIR/macros-nonfatal-errors.rs:36:11
|
LL | Foo = #[default] 0,
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:38:14
--> $DIR/macros-nonfatal-errors.rs:37:14
|
LL | Bar([u8; #[default] 1]),
| ^^^^^^^^^^
error: no default declared
--> $DIR/macros-nonfatal-errors.rs:43:10
--> $DIR/macros-nonfatal-errors.rs:42:10
|
LL | #[derive(Default)]
| ^^^^^^^
@ -44,7 +44,7 @@ LL | #[derive(Default)]
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: multiple declared defaults
--> $DIR/macros-nonfatal-errors.rs:49:10
--> $DIR/macros-nonfatal-errors.rs:48:10
|
LL | #[derive(Default)]
| ^^^^^^^
@ -62,7 +62,7 @@ LL | Baz,
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `#[default]` attribute does not accept a value
--> $DIR/macros-nonfatal-errors.rs:61:5
--> $DIR/macros-nonfatal-errors.rs:60:5
|
LL | #[default = 1]
| ^^^^^^^^^^^^^^
@ -70,7 +70,7 @@ LL | #[default = 1]
= help: try using `#[default]`
error: multiple `#[default]` attributes
--> $DIR/macros-nonfatal-errors.rs:69:5
--> $DIR/macros-nonfatal-errors.rs:68:5
|
LL | #[default]
| ---------- `#[default]` used here
@ -81,13 +81,13 @@ LL | Foo,
|
= note: only one `#[default]` attribute is needed
help: try removing this
--> $DIR/macros-nonfatal-errors.rs:68:5
--> $DIR/macros-nonfatal-errors.rs:67:5
|
LL | #[default]
| ^^^^^^^^^^
error: multiple `#[default]` attributes
--> $DIR/macros-nonfatal-errors.rs:79:5
--> $DIR/macros-nonfatal-errors.rs:78:5
|
LL | #[default]
| ---------- `#[default]` used here
@ -99,7 +99,7 @@ LL | Foo,
|
= note: only one `#[default]` attribute is needed
help: try removing these
--> $DIR/macros-nonfatal-errors.rs:76:5
--> $DIR/macros-nonfatal-errors.rs:75:5
|
LL | #[default]
| ^^^^^^^^^^
@ -109,7 +109,7 @@ LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:86:5
--> $DIR/macros-nonfatal-errors.rs:85:5
|
LL | Foo {},
| ^^^
@ -117,7 +117,7 @@ LL | Foo {},
= help: consider a manual implementation of `Default`
error: default variant must be exhaustive
--> $DIR/macros-nonfatal-errors.rs:94:5
--> $DIR/macros-nonfatal-errors.rs:93:5
|
LL | #[non_exhaustive]
| ----------------- declared `#[non_exhaustive]` here
@ -127,37 +127,37 @@ LL | Foo,
= help: consider a manual implementation of `Default`
error: asm template must be a string literal
--> $DIR/macros-nonfatal-errors.rs:99:10
--> $DIR/macros-nonfatal-errors.rs:98:10
|
LL | asm!(invalid);
| ^^^^^^^
error: concat_idents! requires ident args
--> $DIR/macros-nonfatal-errors.rs:102:5
--> $DIR/macros-nonfatal-errors.rs:101:5
|
LL | concat_idents!("not", "idents");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:104:17
--> $DIR/macros-nonfatal-errors.rs:103:17
|
LL | option_env!(invalid);
| ^^^^^^^
error: expected string literal
--> $DIR/macros-nonfatal-errors.rs:105:10
--> $DIR/macros-nonfatal-errors.rs:104:10
|
LL | env!(invalid);
| ^^^^^^^
error: expected string literal
--> $DIR/macros-nonfatal-errors.rs:106:10
--> $DIR/macros-nonfatal-errors.rs:105:10
|
LL | env!(foo, abr, baz);
| ^^^
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
--> $DIR/macros-nonfatal-errors.rs:107:5
--> $DIR/macros-nonfatal-errors.rs:106:5
|
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -165,7 +165,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: format argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:109:13
--> $DIR/macros-nonfatal-errors.rs:108:13
|
LL | format!(invalid);
| ^^^^^^^
@ -176,19 +176,19 @@ LL | format!("{}", invalid);
| +++++
error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:111:14
--> $DIR/macros-nonfatal-errors.rs:110:14
|
LL | include!(invalid);
| ^^^^^^^
error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:113:18
--> $DIR/macros-nonfatal-errors.rs:112:18
|
LL | include_str!(invalid);
| ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:114:5
--> $DIR/macros-nonfatal-errors.rs:113:5
|
LL | include_str!("i'd be quite surprised if a file with this name existed");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -196,13 +196,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed")
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:115:20
--> $DIR/macros-nonfatal-errors.rs:114:20
|
LL | include_bytes!(invalid);
| ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:116:5
--> $DIR/macros-nonfatal-errors.rs:115:5
|
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -210,13 +210,13 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
error: trace_macros! accepts only `true` or `false`
--> $DIR/macros-nonfatal-errors.rs:118:5
--> $DIR/macros-nonfatal-errors.rs:117:5
|
LL | trace_macros!(invalid);
| ^^^^^^^^^^^^^^^^^^^^^^
error: cannot find macro `llvm_asm` in this scope
--> $DIR/macros-nonfatal-errors.rs:100:5
--> $DIR/macros-nonfatal-errors.rs:99:5
|
LL | llvm_asm!(invalid);
| ^^^^^^^^

View file

@ -0,0 +1,7 @@
struct Bug<A = [(); (let a = (), 1).1]> {
//~^ `let` expressions are not supported here
//~^^ `let` expressions in this position are unstable [E0658]
a: A
}
fn main() {}

View file

@ -0,0 +1,20 @@
error: `let` expressions are not supported here
--> $DIR/issue-92893.rs:1:22
|
LL | struct Bug<A = [(); (let a = (), 1).1]> {
| ^^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error[E0658]: `let` expressions in this position are unstable
--> $DIR/issue-92893.rs:1:22
|
LL | struct Bug<A = [(); (let a = (), 1).1]> {
| ^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -7,7 +7,6 @@
#![allow(unused)]
use m::Foo;
fn main() {
let s = m::S;
s.abc(); //~ ERROR no method named `abc`

View file

@ -0,0 +1,9 @@
fn foo()
where
T: Send,
//~^ cannot find type `T` in this scope
{
let s = "abc".to_string();
}
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0412]: cannot find type `T` in this scope
--> $DIR/autoderef-with-param-env-error.rs:3:5
|
LL | fn foo()
| - help: you might be missing a type parameter: `<T>`
LL | where
LL | T: Send,
| ^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0412`.

View file

@ -59,7 +59,7 @@ pub(super) fn check<'tcx>(
if let Some(indexed_extent) = indexed_extent {
let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id);
let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
return;
}
@ -262,7 +262,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
match res {
Res::Local(hir_id) => {
let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id).unwrap();
if index_used_directly {
self.indexed_directly.insert(
seqvar.segments[0].ident.name,

View file

@ -160,8 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool {
let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id());
let first_scope = scope_tree.var_scope(first);
let second_scope = scope_tree.var_scope(second);
let first_scope = scope_tree.var_scope(first).unwrap();
let second_scope = scope_tree.var_scope(second).unwrap();
scope_tree.is_subscope_of(second_scope, first_scope)
}

View file

@ -693,6 +693,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result<Edition> {
"2015" => Ok(Edition::Edition2015),
"2018" => Ok(Edition::Edition2018),
"2021" => Ok(Edition::Edition2021),
"2024" => Ok(Edition::Edition2024),
_ => Err(format_err!("Invalid value for `--edition`")),
}
}

View file

@ -423,6 +423,10 @@ pub enum Edition {
#[doc_hint = "2021"]
/// Edition 2021.
Edition2021,
#[value = "2024"]
#[doc_hint = "2024"]
/// Edition 2024.
Edition2024,
}
impl Default for Edition {
@ -437,6 +441,7 @@ impl From<Edition> for rustc_span::edition::Edition {
Edition::Edition2015 => Self::Edition2015,
Edition::Edition2018 => Self::Edition2018,
Edition::Edition2021 => Self::Edition2021,
Edition::Edition2024 => Self::Edition2024,
}
}
}