1
Fork 0

Auto merge of #105883 - matthiaskrgr:rollup-v5n53t1, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #105419 (Add tests for #41731)
 - #105447 (Add a test for #103095)
 - #105842 (print argument name in arg mismatch if possible)
 - #105863 (Update browser-ui-test version to reduce GUI tests flakyness)
 - #105867 (remove redundant fn params that were only "used" in recursion)
 - #105869 (don't clone Copy types)
 - #105873 (use &str / String literals instead of format!())
 - #105879 (Revert "Introduce lowering_arena to avoid creating AST nodes on the fly")

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-12-19 01:13:58 +00:00
commit a474ebbc4e
44 changed files with 236 additions and 162 deletions

View file

@ -1,6 +1,6 @@
use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound}; use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt; use super::ResolverAstLoweringExt;
use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode}; use super::{FnDeclKind, LoweringContext, ParamMode};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
@ -24,7 +24,6 @@ use thin_vec::ThinVec;
pub(super) struct ItemLowerer<'a, 'hir> { pub(super) struct ItemLowerer<'a, 'hir> {
pub(super) tcx: TyCtxt<'hir>, pub(super) tcx: TyCtxt<'hir>,
pub(super) resolver: &'a mut ResolverAstLowering, pub(super) resolver: &'a mut ResolverAstLowering,
pub(super) ast_arena: &'a Arena<'static>,
pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>, pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>,
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>, pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
} }
@ -60,7 +59,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
tcx: self.tcx, tcx: self.tcx,
resolver: self.resolver, resolver: self.resolver,
arena: self.tcx.hir_arena, arena: self.tcx.hir_arena,
ast_arena: self.ast_arena,
// HirId handling. // HirId handling.
bodies: Vec::new(), bodies: Vec::new(),

View file

@ -42,7 +42,6 @@ extern crate tracing;
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
use rustc_arena::declare_arena;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::visit; use rustc_ast::visit;
use rustc_ast::{self as ast, *}; use rustc_ast::{self as ast, *};
@ -94,13 +93,6 @@ struct LoweringContext<'a, 'hir> {
/// Used to allocate HIR nodes. /// Used to allocate HIR nodes.
arena: &'hir hir::Arena<'hir>, arena: &'hir hir::Arena<'hir>,
/// Used to allocate temporary AST nodes for use during lowering.
/// This allows us to create "fake" AST -- these nodes can sometimes
/// be allocated on the stack, but other times we need them to live longer
/// than the current stack frame, so they can be collected into vectors
/// and things like that.
ast_arena: &'a Arena<'static>,
/// Bodies inside the owner being lowered. /// Bodies inside the owner being lowered.
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
/// Attributes inside the owner being lowered. /// Attributes inside the owner being lowered.
@ -146,15 +138,6 @@ struct LoweringContext<'a, 'hir> {
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>, generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
} }
declare_arena!([
[] tys: rustc_ast::Ty,
[] aba: rustc_ast::AngleBracketedArgs,
[] ptr: rustc_ast::PolyTraitRef,
// This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to
// use `'tcx`. If we don't have this we get a compile error.
[] _marker: std::marker::PhantomData<&'tcx ()>,
]);
trait ResolverAstLoweringExt { trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
@ -442,13 +425,10 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
tcx.definitions_untracked().def_index_count(), tcx.definitions_untracked().def_index_count(),
); );
let ast_arena = Arena::default();
for def_id in ast_index.indices() { for def_id in ast_index.indices() {
item::ItemLowerer { item::ItemLowerer {
tcx, tcx,
resolver: &mut resolver, resolver: &mut resolver,
ast_arena: &ast_arena,
ast_index: &ast_index, ast_index: &ast_index,
owners: &mut owners, owners: &mut owners,
} }
@ -1001,8 +981,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
GenericArgs::Parenthesized(data) => { GenericArgs::Parenthesized(data) => {
self.emit_bad_parenthesized_trait_in_assoc_ty(data); self.emit_bad_parenthesized_trait_in_assoc_ty(data);
let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args()); self.lower_angle_bracketed_parameter_data(
self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0 &data.as_angle_bracketed_args(),
ParamMode::Explicit,
itctx,
)
.0
} }
}; };
gen_args_ctor.into_generic_args(self) gen_args_ctor.into_generic_args(self)
@ -1067,13 +1051,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.with_dyn_type_scope(false, |this| { self.with_dyn_type_scope(false, |this| {
let node_id = this.next_node_id(); let node_id = this.next_node_id();
let ty = this.ast_arena.tys.alloc(Ty { let ty = this.lower_ty(
id: node_id, &Ty {
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), id: node_id,
span: this.lower_span(constraint.span), kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
tokens: None, span: this.lower_span(constraint.span),
}); tokens: None,
let ty = this.lower_ty(ty, itctx); },
itctx,
);
hir::TypeBindingKind::Equality { term: ty.into() } hir::TypeBindingKind::Equality { term: ty.into() }
}) })
@ -1217,13 +1203,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&& let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{ {
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
bound_generic_params: vec![],
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span
});
let bound = this.lower_poly_trait_ref( let bound = this.lower_poly_trait_ref(
poly_trait_ref, &PolyTraitRef {
bound_generic_params: vec![],
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span
},
itctx, itctx,
); );
let bounds = this.arena.alloc_from_iter([bound]); let bounds = this.arena.alloc_from_iter([bound]);

View file

@ -148,7 +148,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
if let Some(p) = self.pointer { if let Some(p) = self.pointer {
self.pointer = self.graph.next_constraints[p]; self.pointer = self.graph.next_constraints[p];
Some(self.constraints[p].clone()) Some(self.constraints[p])
} else if let Some(next_static_idx) = self.next_static_idx { } else if let Some(next_static_idx) = self.next_static_idx {
self.next_static_idx = if next_static_idx == (self.graph.first_constraints.len() - 1) { self.next_static_idx = if next_static_idx == (self.graph.first_constraints.len() - 1) {
None None

View file

@ -649,7 +649,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if !assign_value.is_empty() { if !assign_value.is_empty() {
err.span_suggestion_verbose( err.span_suggestion_verbose(
sugg_span.shrink_to_hi(), sugg_span.shrink_to_hi(),
format!("consider assigning a value"), "consider assigning a value",
format!(" = {}", assign_value), format!(" = {}", assign_value),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View file

@ -270,7 +270,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
for extra in extra_info { for extra in extra_info {
match extra { match extra {
ExtraConstraintInfo::PlaceholderFromPredicate(span) => { ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime")); err.span_note(*span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
} }
} }
} }

View file

@ -472,7 +472,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
for extra in extra_info { for extra in extra_info {
match extra { match extra {
ExtraConstraintInfo::PlaceholderFromPredicate(span) => { ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime")); diag.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
} }
} }
} }

View file

@ -831,7 +831,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if self.eval_verify_bound( if self.eval_verify_bound(
infcx, infcx,
param_env, param_env,
body,
generic_ty, generic_ty,
type_test.lower_bound, type_test.lower_bound,
&type_test.verify_bound, &type_test.verify_bound,
@ -962,14 +961,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// where `ur` is a local bound -- we are sometimes in a // where `ur` is a local bound -- we are sometimes in a
// position to prove things that our caller cannot. See // position to prove things that our caller cannot. See
// #53570 for an example. // #53570 for an example.
if self.eval_verify_bound( if self.eval_verify_bound(infcx, param_env, generic_ty, ur, &type_test.verify_bound) {
infcx,
param_env,
body,
generic_ty,
ur,
&type_test.verify_bound,
) {
continue; continue;
} }
@ -1190,7 +1182,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&self, &self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
generic_ty: Ty<'tcx>, generic_ty: Ty<'tcx>,
lower_bound: RegionVid, lower_bound: RegionVid,
verify_bound: &VerifyBound<'tcx>, verify_bound: &VerifyBound<'tcx>,
@ -1213,25 +1204,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} }
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
self.eval_verify_bound( self.eval_verify_bound(infcx, param_env, generic_ty, lower_bound, verify_bound)
infcx,
param_env,
body,
generic_ty,
lower_bound,
verify_bound,
)
}), }),
VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| {
self.eval_verify_bound( self.eval_verify_bound(infcx, param_env, generic_ty, lower_bound, verify_bound)
infcx,
param_env,
body,
generic_ty,
lower_bound,
verify_bound,
)
}), }),
} }
} }

View file

@ -612,7 +612,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
let locations = location.to_locations(); let locations = location.to_locations();
for constraint in constraints.outlives().iter() { for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone(); let mut constraint = *constraint;
constraint.locations = locations; constraint.locations = locations;
if let ConstraintCategory::Return(_) if let ConstraintCategory::Return(_)
| ConstraintCategory::UseAsConst | ConstraintCategory::UseAsConst

View file

@ -144,7 +144,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
// We prefer the latter because it matches the behavior of // We prefer the latter because it matches the behavior of
// Clang. // Clang.
if late && matches!(reg, InlineAsmRegOrRegClass::Reg(_)) { if late && matches!(reg, InlineAsmRegOrRegClass::Reg(_)) {
constraints.push(format!("{}", reg_to_llvm(reg, Some(&in_value.layout)))); constraints.push(reg_to_llvm(reg, Some(&in_value.layout)).to_string());
} else { } else {
constraints.push(format!("{}", op_idx[&idx])); constraints.push(format!("{}", op_idx[&idx]));
} }

View file

@ -2240,7 +2240,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
), ),
"s", "s",
), ),
[only] => (format!("{only}"), ""), [only] => (only.to_string(), ""),
[] => unreachable!(), [] => unreachable!(),
}; };
let last_span = *arg_spans.last().unwrap(); let last_span = *arg_spans.last().unwrap();

View file

@ -99,18 +99,17 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
ty: Ty<'tcx>, ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> bool { ) -> bool {
// We don't just accept all !needs_drop fields, due to semver concerns. // We don't just accept all !needs_drop fields, due to semver concerns.
match ty.kind() { match ty.kind() {
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
ty::Tuple(tys) => { ty::Tuple(tys) => {
// allow tuples of allowed types // allow tuples of allowed types
tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env, span)) tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env))
} }
ty::Array(elem, _len) => { ty::Array(elem, _len) => {
// Like `Copy`, we do *not* special-case length 0. // Like `Copy`, we do *not* special-case length 0.
allowed_union_field(*elem, tcx, param_env, span) allowed_union_field(*elem, tcx, param_env)
} }
_ => { _ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`. // Fallback case: allow `ManuallyDrop` and things that are `Copy`.
@ -124,7 +123,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
for field in &def.non_enum_variant().fields { for field in &def.non_enum_variant().fields {
let field_ty = field.ty(tcx, substs); let field_ty = field.ty(tcx, substs);
if !allowed_union_field(field_ty, tcx, param_env, span) { if !allowed_union_field(field_ty, tcx, param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local. // We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span), Some(Node::Field(field)) => (field.span, field.ty.span),

View file

@ -1548,7 +1548,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
cause, cause,
expected, expected,
found, found,
coercion_error.clone(), coercion_error,
fcx, fcx,
parent_id, parent_id,
expression, expression,
@ -1567,7 +1567,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
cause, cause,
expected, expected,
found, found,
coercion_error.clone(), coercion_error,
fcx, fcx,
id, id,
expression, expression,
@ -1583,7 +1583,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
cause, cause,
expected, expected,
found, found,
coercion_error.clone(), coercion_error,
); );
} }
} }

View file

@ -163,7 +163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr = expr.peel_drop_temps(); let expr = expr.peel_drop_temps();
let cause = self.misc(expr.span); let cause = self.misc(expr.span);
let expr_ty = self.resolve_vars_with_obligations(checked_ty); let expr_ty = self.resolve_vars_with_obligations(checked_ty);
let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e.clone()); let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e);
let is_insufficiently_polymorphic = let is_insufficiently_polymorphic =
matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..)); matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..));
@ -406,7 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let note_about_variant_field_privacy = (field_is_local && !field_is_accessible) let note_about_variant_field_privacy = (field_is_local && !field_is_accessible)
.then(|| format!(" (its field is private, but it's local to this crate and its privacy can be changed)")); .then(|| " (its field is private, but it's local to this crate and its privacy can be changed)".to_string());
let sole_field_ty = sole_field.ty(self.tcx, substs); let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) { if self.can_coerce(expr_ty, sole_field_ty) {

View file

@ -28,7 +28,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, sym, Span}; use rustc_span::{self, sym, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
@ -1013,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else { } else {
args_span args_span
}; };
labels.push((span, format!("multiple arguments are missing"))); labels.push((span, "multiple arguments are missing".to_string()));
suggestion_text = match suggestion_text { suggestion_text = match suggestion_text {
SuggestionText::None | SuggestionText::Provide(_) => { SuggestionText::None | SuggestionText::Provide(_) => {
SuggestionText::Provide(true) SuggestionText::Provide(true)
@ -1141,6 +1141,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"()".to_string() "()".to_string()
} else if expected_ty.is_suggestable(tcx, false) { } else if expected_ty.is_suggestable(tcx, false) {
format!("/* {} */", expected_ty) format!("/* {} */", expected_ty)
} else if let Some(fn_def_id) = fn_def_id
&& self.tcx.def_kind(fn_def_id).is_fn_like()
&& let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
&& let Some(arg) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
&& arg.name != kw::SelfLower
{
format!("/* {} */", arg.name)
} else { } else {
"/* value */".to_string() "/* value */".to_string()
} }

View file

@ -319,11 +319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
err.multipart_suggestion_verbose( err.multipart_suggestion_verbose("use parentheses to call these", sugg, applicability);
format!("use parentheses to call these"),
sugg,
applicability,
);
true true
} else { } else {

View file

@ -1007,7 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter { if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
err.span_suggestion( err.span_suggestion(
span, span,
&format!("there is a method with a similar name",), "there is a method with a similar name",
lev_candidate.name, lev_candidate.name,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View file

@ -2130,7 +2130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{ {
let ty = self.resolve_vars_if_possible(ti.expected); let ty = self.resolve_vars_if_possible(ti.expected);
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty); let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(ty);
match is_slice_or_array_or_vector.1.kind() { match is_slice_or_array_or_vector.1.kind() {
ty::Adt(adt_def, _) ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did()) if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
@ -2159,17 +2159,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.emit(); err.emit();
} }
fn is_slice_or_array_or_vector( fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
&self,
err: &mut Diagnostic,
snippet: String,
ty: Ty<'tcx>,
) -> (bool, Ty<'tcx>) {
match ty.kind() { match ty.kind() {
ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => { ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
(true, ty) (true, ty)
} }
ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty), ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(*ty),
ty::Slice(..) | ty::Array(..) => (true, ty), ty::Slice(..) | ty::Array(..) => (true, ty),
_ => (false, ty), _ => (false, ty),
} }

View file

@ -184,7 +184,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
let text = if br.has_name() { let text = if br.has_name() {
format!("the lifetime `{}` as defined here", br.name) format!("the lifetime `{}` as defined here", br.name)
} else { } else {
format!("the anonymous lifetime as defined here") "the anonymous lifetime as defined here".to_string()
}; };
(text, sp) (text, sp)
} }
@ -203,7 +203,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
sp = param.span; sp = param.span;
} }
let text = if name == kw::UnderscoreLifetime { let text = if name == kw::UnderscoreLifetime {
format!("the anonymous lifetime as defined here") "the anonymous lifetime as defined here".to_string()
} else { } else {
format!("the lifetime `{}` as defined here", name) format!("the lifetime `{}` as defined here", name)
}; };

View file

@ -44,7 +44,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
); );
} }
(Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => { (Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
err.span_note(sub_span, format!("the lifetime defined here...")); err.span_note(sub_span, "the lifetime defined here...");
err.span_note( err.span_note(
sup_span, sup_span,
format!("...must outlive the lifetime `{sup_symbol}` defined here"), format!("...must outlive the lifetime `{sup_symbol}` defined here"),
@ -55,17 +55,11 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
sub_span, sub_span,
format!("the lifetime `{sub_symbol}` defined here..."), format!("the lifetime `{sub_symbol}` defined here..."),
); );
err.span_note( err.span_note(sup_span, "...must outlive the lifetime defined here");
sup_span,
format!("...must outlive the lifetime defined here"),
);
} }
(Some(sub_span), Some(sup_span), _, _) => { (Some(sub_span), Some(sup_span), _, _) => {
err.span_note(sub_span, format!("the lifetime defined here...")); err.span_note(sub_span, "the lifetime defined here...");
err.span_note( err.span_note(sup_span, "...must outlive the lifetime defined here");
sup_span,
format!("...must outlive the lifetime defined here"),
);
} }
_ => {} _ => {}
} }

View file

@ -127,7 +127,7 @@ impl<'tcx> Queries<'tcx> {
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> { pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
self.register_plugins.compute(|| { self.register_plugins.compute(|| {
let crate_name = self.crate_name()?.peek().clone(); let crate_name = *self.crate_name()?.peek();
let krate = self.parse()?.take(); let krate = self.parse()?.take();
let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {}; let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};

View file

@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|lint| { |lint| {
let suggested_ident = let suggested_ident =
format!("{}{}", binding_annot.prefix_str(), ident); format!("{}{}", binding_annot.prefix_str(), ident);
lint.set_arg("ident", ident.clone()).span_suggestion( lint.set_arg("ident", ident).span_suggestion(
fieldpat.span, fieldpat.span,
fluent::suggestion, fluent::suggestion,
suggested_ident, suggested_ident,
@ -2052,7 +2052,7 @@ impl KeywordIdents {
ident.span, ident.span,
fluent::lint_builtin_keyword_idents, fluent::lint_builtin_keyword_idents,
|lint| { |lint| {
lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion( lint.set_arg("kw", ident).set_arg("next", next_edition).span_suggestion(
ident.span, ident.span,
fluent::suggestion, fluent::suggestion,
format!("r#{}", ident), format!("r#{}", ident),

View file

@ -71,11 +71,11 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
); );
} else { } else {
lint.multipart_suggestion_verbose( lint.multipart_suggestion_verbose(
format!("to check pattern in a loop use `while let`"), "to check pattern in a loop use `while let`",
vec![ vec![
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
(expr.span.with_hi(pat.span.lo()), format!("while let {var}(")), (expr.span.with_hi(pat.span.lo()), format!("while let {var}(")),
(pat.span.between(arg.span), format!(") = ")), (pat.span.between(arg.span), ") = ".to_string()),
], ],
Applicability::MaybeIncorrect Applicability::MaybeIncorrect
); );
@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
vec![ vec![
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
(expr.span.with_hi(pat.span.lo()), format!("if let {var}(")), (expr.span.with_hi(pat.span.lo()), format!("if let {var}(")),
(pat.span.between(arg.span), format!(") = ")), (pat.span.between(arg.span), ") = ".to_string()),
], ],
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
) )

View file

@ -39,10 +39,8 @@ impl<'a> DiagnosticDerive<'a> {
let init = match builder.slug.value_ref() { let init = match builder.slug.value_ref() {
None => { None => {
span_err(builder.span, "diagnostic slug not specified") span_err(builder.span, "diagnostic slug not specified")
.help(format!( .help("specify the slug as the first argument to the `#[diag(...)]` \
"specify the slug as the first argument to the `#[diag(...)]` \ attribute, such as `#[diag(hir_analysis_example_error)]`")
attribute, such as `#[diag(hir_analysis_example_error)]`",
))
.emit(); .emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error(); return DiagnosticDeriveError::ErrorHandled.to_compile_error();
} }
@ -133,10 +131,8 @@ impl<'a> LintDiagnosticDerive<'a> {
match builder.slug.value_ref() { match builder.slug.value_ref() {
None => { None => {
span_err(builder.span, "diagnostic slug not specified") span_err(builder.span, "diagnostic slug not specified")
.help(format!( .help("specify the slug as the first argument to the attribute, such as \
"specify the slug as the first argument to the attribute, such as \ `#[diag(compiletest_example)]`")
`#[diag(compiletest_example)]`",
))
.emit(); .emit();
DiagnosticDeriveError::ErrorHandled.to_compile_error() DiagnosticDeriveError::ErrorHandled.to_compile_error()
} }

View file

@ -332,7 +332,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Symbol {
s.emit_str(self.as_str()); s.emit_str(self.as_str());
} }
Entry::Occupied(o) => { Entry::Occupied(o) => {
let x = o.get().clone(); let x = *o.get();
s.emit_u8(SYMBOL_OFFSET); s.emit_u8(SYMBOL_OFFSET);
s.emit_usize(x); s.emit_usize(x);
} }

View file

@ -448,15 +448,15 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
// FIXME: this is a poor version of `pretty_print_const_value`. // FIXME: this is a poor version of `pretty_print_const_value`.
let fmt_val = |val: &ConstValue<'tcx>| match val { let fmt_val = |val: &ConstValue<'tcx>| match val {
ConstValue::ZeroSized => format!("<ZST>"), ConstValue::ZeroSized => "<ZST>".to_string(),
ConstValue::Scalar(s) => format!("Scalar({:?})", s), ConstValue::Scalar(s) => format!("Scalar({:?})", s),
ConstValue::Slice { .. } => format!("Slice(..)"), ConstValue::Slice { .. } => "Slice(..)".to_string(),
ConstValue::ByRef { .. } => format!("ByRef(..)"), ConstValue::ByRef { .. } => "ByRef(..)".to_string(),
}; };
let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree { let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf), ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
ty::ValTree::Branch(_) => format!("ValTree::Branch(..)"), ty::ValTree::Branch(_) => "ValTree::Branch(..)".to_string(),
}; };
let val = match literal { let val = match literal {

View file

@ -76,7 +76,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
let Some((otherwise, rest)) = arms.split_last() else { let Some((otherwise, rest)) = arms.split_last() else {
return Err(ParseError { return Err(ParseError {
span, span,
item_description: format!("no arms"), item_description: "no arms".to_string(),
expected: "at least one arm".to_string(), expected: "at least one arm".to_string(),
}) })
}; };

View file

@ -965,7 +965,7 @@ impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Symbol {
s.emit_str(self.as_str()); s.emit_str(self.as_str());
} }
Entry::Occupied(o) => { Entry::Occupied(o) => {
let x = o.get().clone(); let x = *o.get();
s.emit_u8(SYMBOL_OFFSET); s.emit_u8(SYMBOL_OFFSET);
s.emit_usize(x); s.emit_usize(x);
} }

View file

@ -277,11 +277,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let override_suggestion = let override_suggestion =
if ["true", "false"].contains(&item_str.to_string().to_lowercase().as_str()) { if ["true", "false"].contains(&item_str.to_string().to_lowercase().as_str()) {
let item_typo = item_str.to_string().to_lowercase(); let item_typo = item_str.to_string().to_lowercase();
Some(( Some((item_span, "you may want to use a bool value instead", item_typo))
item_span,
"you may want to use a bool value instead",
format!("{}", item_typo),
))
// FIXME(vincenzopalazzo): make the check smarter, // FIXME(vincenzopalazzo): make the check smarter,
// and maybe expand with levenshtein distance checks // and maybe expand with levenshtein distance checks
} else if item_str.as_str() == "printf" { } else if item_str.as_str() == "printf" {
@ -2324,7 +2320,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let message = format!("consider introducing lifetime `{}` here", name); let message = format!("consider introducing lifetime `{}` here", name);
should_continue = suggest(err, false, span, &message, sugg); should_continue = suggest(err, false, span, &message, sugg);
} else { } else {
let message = format!("consider introducing a named lifetime parameter"); let message = "consider introducing a named lifetime parameter";
should_continue = suggest(err, false, span, &message, sugg); should_continue = suggest(err, false, span, &message, sugg);
} }
} }

View file

@ -1491,7 +1491,7 @@ impl<'a> Resolver<'a> {
label_res_map: self.label_res_map.clone(), label_res_map: self.label_res_map.clone(),
lifetimes_res_map: self.lifetimes_res_map.clone(), lifetimes_res_map: self.lifetimes_res_map.clone(),
extra_lifetime_params_map: self.extra_lifetime_params_map.clone(), extra_lifetime_params_map: self.extra_lifetime_params_map.clone(),
next_node_id: self.next_node_id.clone(), next_node_id: self.next_node_id,
node_id_to_def_id: self.node_id_to_def_id.clone(), node_id_to_def_id: self.node_id_to_def_id.clone(),
def_id_to_node_id: self.def_id_to_node_id.clone(), def_id_to_node_id: self.def_id_to_node_id.clone(),
trait_map: self.trait_map.clone(), trait_map: self.trait_map.clone(),

View file

@ -159,13 +159,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
orig_env, orig_env,
orig_env, orig_env,
&mut fresh_preds, &mut fresh_preds,
false,
) else { ) else {
return AutoTraitResult::NegativeImpl; return AutoTraitResult::NegativeImpl;
}; };
let (full_env, full_user_env) = self let (full_env, full_user_env) = self
.evaluate_predicates(&infcx, trait_did, ty, new_env, user_env, &mut fresh_preds, true) .evaluate_predicates(&infcx, trait_did, ty, new_env, user_env, &mut fresh_preds)
.unwrap_or_else(|| { .unwrap_or_else(|| {
panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env) panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
}); });
@ -247,7 +246,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
user_env: ty::ParamEnv<'tcx>, user_env: ty::ParamEnv<'tcx>,
fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>, fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
only_projections: bool,
) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> { ) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
let tcx = infcx.tcx; let tcx = infcx.tcx;
@ -322,7 +320,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
fresh_preds, fresh_preds,
&mut predicates, &mut predicates,
&mut select, &mut select,
only_projections,
) { ) {
return None; return None;
} }
@ -600,7 +597,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>, fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>, predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
selcx: &mut SelectionContext<'_, 'tcx>, selcx: &mut SelectionContext<'_, 'tcx>,
only_projections: bool,
) -> bool { ) -> bool {
let dummy_cause = ObligationCause::dummy(); let dummy_cause = ObligationCause::dummy();
@ -744,7 +740,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
fresh_preds, fresh_preds,
predicates, predicates,
selcx, selcx,
only_projections,
) { ) {
return false; return false;
} }

View file

@ -138,10 +138,10 @@ pub fn is_const_evaluatable<'tcx>(
} else if uv.has_non_region_param() { } else if uv.has_non_region_param() {
NotConstEvaluatable::MentionsParam NotConstEvaluatable::MentionsParam
} else { } else {
let guar = infcx.tcx.sess.delay_span_bug( let guar = infcx
span, .tcx
format!("Missing value for constant, but no error reported?"), .sess
); .delay_span_bug(span, "Missing value for constant, but no error reported?");
NotConstEvaluatable::Error(guar) NotConstEvaluatable::Error(guar)
}; };

View file

@ -1574,7 +1574,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&error.obligation.cause, &error.obligation.cause,
expected_found.expected, expected_found.expected,
expected_found.found, expected_found.found,
err.clone(), *err,
) )
.emit(); .emit();
} }
@ -1583,7 +1583,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&error.obligation.cause, &error.obligation.cause,
expected_found.expected, expected_found.expected,
expected_found.found, expected_found.found,
err.clone(), *err,
); );
let code = error.obligation.cause.code().peel_derives().peel_match_impls(); let code = error.obligation.cause.code().peel_derives().peel_match_impls();
if let ObligationCauseCode::BindingObligation(..) if let ObligationCauseCode::BindingObligation(..)
@ -2332,9 +2332,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// get rid of :: between Trait and <type> // get rid of :: between Trait and <type>
// must be '::' between them, otherwise the parser won't accept the code // must be '::' between them, otherwise the parser won't accept the code
suggestions.push((between_span, "".to_string(),)); suggestions.push((between_span, "".to_string(),));
suggestions.push((generic_arg.span_ext.shrink_to_hi(), format!(">"))); suggestions.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
} else { } else {
suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), format!(">"))); suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), ">".to_string()));
} }
err.multipart_suggestion( err.multipart_suggestion(
message, message,

View file

@ -2740,7 +2740,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
ty::Closure(def_id, _) => err.span_note( ty::Closure(def_id, _) => err.span_note(
self.tcx.def_span(def_id), self.tcx.def_span(def_id),
&format!("required because it's used within this closure"), "required because it's used within this closure",
), ),
_ => err.note(&msg), _ => err.note(&msg),
}; };
@ -3386,7 +3386,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
err.span_note( err.span_note(
multi_span, multi_span,
format!("the method call chain might not have had the expected associated types"), "the method call chain might not have had the expected associated types",
); );
} }
} }

View file

@ -123,7 +123,7 @@ where
let fix_state = |state| if state == other.start { self.accepting } else { state }; let fix_state = |state| if state == other.start { self.accepting } else { state };
let entry = transitions.entry(fix_state(source)).or_default(); let entry = transitions.entry(fix_state(source)).or_default();
for (edge, destinations) in transition { for (edge, destinations) in transition {
let entry = entry.entry(edge.clone()).or_default(); let entry = entry.entry(edge).or_default();
for destination in destinations { for destination in destinations {
entry.insert(fix_state(destination)); entry.insert(fix_state(destination));
} }
@ -147,7 +147,7 @@ where
} }
let entry = transitions.entry(source).or_default(); let entry = transitions.entry(source).or_default();
for (edge, destinations) in transition { for (edge, destinations) in transition {
let entry = entry.entry(edge.clone()).or_default(); let entry = entry.entry(*edge).or_default();
for &(mut destination) in destinations { for &(mut destination) in destinations {
// if dest is accepting state of `other`, replace with accepting state of `self` // if dest is accepting state of `other`, replace with accepting state of `self`
if destination == other.accepting { if destination == other.accepting {

View file

@ -94,8 +94,8 @@ LL | let closure = |x| x;
| ^^^ | ^^^
help: provide the argument help: provide the argument
| |
LL | closure(/* value */); LL | closure(/* x */);
| ~~~~~~~~~~~~~ | ~~~~~~~~~
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -0,0 +1,30 @@
// check-pass
trait FnOnceForGenericRef<T>: FnOnce(&T) -> Self::FnOutput {
type FnOutput;
}
impl<T, R, F: FnOnce(&T) -> R> FnOnceForGenericRef<T> for F {
type FnOutput = R;
}
struct Data<T, D: FnOnceForGenericRef<T>> {
value: Option<T>,
output: Option<D::FnOutput>,
}
impl<T, D: FnOnceForGenericRef<T>> Data<T, D> {
fn new(value: T, f: D) -> Self {
let output = f(&value);
Self {
value: Some(value),
output: Some(output),
}
}
}
fn test() {
Data::new(String::new(), |_| {});
}
fn main() {}

View file

@ -11,8 +11,8 @@ LL | let f = |x| x * 3;
| ^^^ | ^^^
help: provide the argument help: provide the argument
| |
LL | let a = f(/* value */); LL | let a = f(/* x */);
| ~~~~~~~~~~~~~ | ~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/E0057.rs:5:13 --> $DIR/E0057.rs:5:13

View file

@ -11,8 +11,8 @@ LL | fn f<I>(i: I)
| ^ ---- | ^ ----
help: provide the argument help: provide the argument
| |
LL | f(&[f(/* value */)]); LL | f(&[f(/* i */)]);
| ~~~~~~~~~~~~~ | ~~~~~~~~~
error: aborting due to previous error error: aborting due to previous error

View file

@ -0,0 +1,15 @@
// compile-flags: -Z trace-macros
#![recursion_limit = "5"]
fn main() {
macro_rules! stack {
($overflow:expr) => {
print!(stack!($overflow));
//~^ ERROR recursion limit reached while expanding
//~| ERROR format argument must be a string literal
};
}
stack!("overflow");
}

View file

@ -0,0 +1,38 @@
error: recursion limit reached while expanding `$crate::format_args!`
--> $DIR/issue-41731-infinite-macro-print.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "10"]` attribute to your crate (`issue_41731_infinite_macro_print`)
= note: this error originates in the macro `print` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info)
note: trace_macro
--> $DIR/issue-41731-infinite-macro-print.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= note: expanding `stack! { "overflow" }`
= note: to `print! (stack! ("overflow")) ;`
= note: expanding `print! { stack! ("overflow") }`
= note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }`
= note: expanding `stack! { "overflow" }`
= note: to `print! (stack! ("overflow")) ;`
= note: expanding `print! { stack! ("overflow") }`
= note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }`
error: format argument must be a string literal
--> $DIR/issue-41731-infinite-macro-print.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `print` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might be missing a string literal to format with
|
LL | print!("{}", stack!($overflow));
| +++++
error: aborting due to 2 previous errors

View file

@ -0,0 +1,15 @@
// compile-flags: -Z trace-macros
#![recursion_limit = "5"]
fn main() {
macro_rules! stack {
($overflow:expr) => {
println!(stack!($overflow));
//~^ ERROR recursion limit reached while expanding
//~| ERROR format argument must be a string literal
};
}
stack!("overflow");
}

View file

@ -0,0 +1,38 @@
error: recursion limit reached while expanding `$crate::format_args_nl!`
--> $DIR/issue-41731-infinite-macro-println.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "10"]` attribute to your crate (`issue_41731_infinite_macro_println`)
= note: this error originates in the macro `println` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info)
note: trace_macro
--> $DIR/issue-41731-infinite-macro-println.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= note: expanding `stack! { "overflow" }`
= note: to `println! (stack! ("overflow")) ;`
= note: expanding `println! { stack! ("overflow") }`
= note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }`
= note: expanding `stack! { "overflow" }`
= note: to `println! (stack! ("overflow")) ;`
= note: expanding `println! { stack! ("overflow") }`
= note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }`
error: format argument must be a string literal
--> $DIR/issue-41731-infinite-macro-println.rs:14:5
|
LL | stack!("overflow");
| ^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `println` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might be missing a string literal to format with
|
LL | println!("{}", stack!($overflow));
| +++++
error: aborting due to 2 previous errors

View file

@ -13,7 +13,7 @@ help: provide the argument
| |
LL ~ needlesArr.iter().fold(|x, y| { LL ~ needlesArr.iter().fold(|x, y| {
LL + LL +
LL ~ }, /* value */); LL ~ }, /* f */);
| |
error: aborting due to previous error error: aborting due to previous error