Auto merge of #99231 - Dylan-DPC:rollup-0tl8c0o, r=Dylan-DPC

Rollup of 5 pull requests

Successful merges:

 - #97720 (Always create elided lifetime parameters for functions)
 - #98315 (Stabilize `core::ffi:c_*` and rexport in `std::ffi`)
 - #98705 (Implement `for<>` lifetime binder for closures)
 - #99126 (remove allow(rustc::potential_query_instability) in rustc_span)
 - #99139 (Give a better error when `x dist` fails for an optional tool)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-07-14 11:00:30 +00:00
commit f1a8854f9b
116 changed files with 1024 additions and 271 deletions

View file

@ -1390,7 +1390,7 @@ pub enum ExprKind {
/// A closure (e.g., `move |a, b, c| a + b + c`).
///
/// The final span is the span of the argument block `|...|`.
Closure(CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span),
Closure(ClosureBinder, CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span),
/// A block (`'label: { ... }`).
Block(P<Block>, Option<Label>),
/// An async block (`async move { ... }`).
@ -1518,6 +1518,31 @@ pub enum Movability {
Movable,
}
/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ClosureBinder {
/// The binder is not present, all closure lifetimes are inferred.
NotPresent,
/// The binder is present.
For {
/// Span of the whole `for<>` clause
///
/// ```text
/// for<'a, 'b> |_: &'a (), _: &'b ()| { ... }
/// ^^^^^^^^^^^ -- this
/// ```
span: Span,
/// Lifetimes in the `for<>` closure
///
/// ```text
/// for<'a, 'b> |_: &'a (), _: &'b ()| { ... }
/// ^^^^^^ -- this
/// ```
generic_params: P<[GenericParam]>,
},
}
/// Represents a macro invocation. The `path` indicates which macro
/// is being invoked, and the `args` are arguments passed to it.
#[derive(Clone, Encodable, Decodable, Debug)]

View file

@ -125,6 +125,10 @@ pub trait MutVisitor: Sized {
noop_visit_asyncness(a, self);
}
fn visit_closure_binder(&mut self, b: &mut ClosureBinder) {
noop_visit_closure_binder(b, self);
}
fn visit_block(&mut self, b: &mut P<Block>) {
noop_visit_block(b, self);
}
@ -825,6 +829,17 @@ pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
}
}
pub fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis: &mut T) {
match binder {
ClosureBinder::NotPresent => {}
ClosureBinder::For { span: _, generic_params } => {
let mut vec = std::mem::take(generic_params).into_vec();
vec.flat_map_in_place(|param| vis.flat_map_generic_param(param));
*generic_params = P::from_vec(vec);
}
}
}
pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) {
match asyncness {
Async::Yes { span: _, closure_id, return_impl_trait_id } => {
@ -1336,7 +1351,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(expr);
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
}
ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => {
ExprKind::Closure(binder, _capture_by, asyncness, _movability, decl, body, span) => {
vis.visit_closure_binder(binder);
vis.visit_asyncness(asyncness);
vis.visit_fn_decl(decl);
vis.visit_expr(body);

View file

@ -56,14 +56,14 @@ pub enum FnKind<'a> {
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
/// E.g., `|x, y| body`.
Closure(&'a FnDecl, &'a Expr),
Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr),
}
impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> {
match *self {
FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
FnKind::Closure(_, _) => None,
FnKind::Closure(_, _, _) => None,
}
}
@ -77,7 +77,7 @@ impl<'a> FnKind<'a> {
pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
FnKind::Closure(decl, _) => decl,
FnKind::Closure(_, decl, _) => decl,
}
}
@ -155,6 +155,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_generics(&mut self, g: &'ast Generics) {
walk_generics(self, g)
}
fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
walk_closure_binder(self, b)
}
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
}
@ -636,6 +639,15 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
}
pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
match binder {
ClosureBinder::NotPresent => {}
ClosureBinder::For { generic_params, span: _ } => {
walk_list!(visitor, visit_generic_param, generic_params)
}
}
}
pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate {
@ -682,7 +694,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa
walk_fn_decl(visitor, &sig.decl);
walk_list!(visitor, visit_block, body);
}
FnKind::Closure(decl, body) => {
FnKind::Closure(binder, decl, body) => {
visitor.visit_closure_binder(binder);
walk_fn_decl(visitor, decl);
visitor.visit_expr(body);
}
@ -856,8 +869,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id)
ExprKind::Closure(ref binder, _, _, _, ref decl, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(binder, decl, body), expression.span, expression.id)
}
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);

View file

@ -155,6 +155,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_await(span, expr)
}
ExprKind::Closure(
ref binder,
capture_clause,
asyncness,
movability,
@ -164,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
) => {
if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure(
binder,
capture_clause,
e.id,
closure_id,
@ -173,6 +175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
} else {
self.lower_expr_closure(
binder,
capture_clause,
e.id,
movability,
@ -605,13 +608,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
// `static |_task_context| -> <ret_ty> { body }`:
let generator_kind = hir::ExprKind::Closure {
let generator_kind = {
let c = self.arena.alloc(hir::Closure {
binder: hir::ClosureBinder::Default,
capture_clause,
bound_generic_params: &[],
fn_decl,
body,
fn_decl_span: self.lower_span(span),
movability: Some(hir::Movability::Static),
});
hir::ExprKind::Closure(c)
};
let generator = hir::Expr {
hir_id: self.lower_node_id(closure_node_id),
@ -831,6 +839,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_expr_closure(
&mut self,
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
movability: Movability,
@ -838,7 +847,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
let (body, generator_option) = self.with_new_scopes(move |this| {
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
let (body_id, generator_option) = self.with_new_scopes(move |this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
@ -853,18 +864,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
(body_id, generator_option)
});
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
hir::ExprKind::Closure {
let c = self.arena.alloc(hir::Closure {
binder: binder_clause,
capture_clause,
bound_generic_params,
fn_decl,
body,
body: body_id,
fn_decl_span: this.lower_span(fn_decl_span),
movability: generator_option,
}
});
hir::ExprKind::Closure(c)
})
}
@ -906,8 +920,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn lower_closure_binder<'c>(
&mut self,
binder: &'c ClosureBinder,
) -> (hir::ClosureBinder, &'c [GenericParam]) {
let (binder, params) = match binder {
ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
&ClosureBinder::For { span, ref generic_params } => {
let span = self.lower_span(span);
(hir::ClosureBinder::For { span }, &**generic_params)
}
};
(binder, params)
}
fn lower_expr_async_closure(
&mut self,
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
inner_closure_id: NodeId,
@ -915,6 +945,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
if let &ClosureBinder::For { span, .. } = binder {
self.tcx.sess.span_err(
span,
"`for<...>` binders on `async` closures are not currently supported",
);
}
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
@ -952,20 +991,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
body_id
});
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
hir::ExprKind::Closure {
let c = self.arena.alloc(hir::Closure {
binder: binder_clause,
capture_clause,
bound_generic_params,
fn_decl,
body,
fn_decl_span: this.lower_span(fn_decl_span),
movability: None,
}
});
hir::ExprKind::Closure(c)
})
}

View file

@ -1597,6 +1597,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.emit();
}
if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
self.check_late_bound_lifetime_defs(generic_params);
}
if let FnKind::Fn(
_,
_,

View file

@ -744,6 +744,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
gate_all!(
closure_lifetime_binder,
"`for<...>` binders for closures are experimental",
"consider removing `for<...>`"
);
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");

View file

@ -389,6 +389,7 @@ impl<'a> State<'a> {
self.bclose(expr.span, empty);
}
ast::ExprKind::Closure(
ref binder,
capture_clause,
asyncness,
movability,
@ -396,6 +397,7 @@ impl<'a> State<'a> {
ref body,
_,
) => {
self.print_closure_binder(binder);
self.print_movability(movability);
self.print_asyncness(asyncness);
self.print_capture_clause(capture_clause);
@ -594,6 +596,15 @@ impl<'a> State<'a> {
self.end(); // Close enclosing cbox.
}
fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
match binder {
ast::ClosureBinder::NotPresent => {}
ast::ClosureBinder::For { generic_params, .. } => {
self.print_formal_generic_params(&generic_params)
}
}
}
fn print_movability(&mut self, movability: ast::Movability) {
match movability {
ast::Movability::Static => self.word_space("static"),

View file

@ -891,7 +891,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure { body, fn_decl_span, .. } = expr {
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
for (captured_place, place) in self
.infcx
.tcx
@ -904,11 +904,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if target_place == place.as_ref() =>
{
debug!("closure_span: found captured local {:?}", place);
let body = self.infcx.tcx.hir().body(*body);
let body = self.infcx.tcx.hir().body(body);
let generator_kind = body.generator_kind();
return Some((
*fn_decl_span,
fn_decl_span,
generator_kind,
captured_place.get_capture_kind_span(self.infcx.tcx),
captured_place.get_path_span(self.infcx.tcx),

View file

@ -325,7 +325,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
// Can't have BrEnv in functions, constants or generators.
bug!("BrEnv outside of closure.");
};
let hir::ExprKind::Closure { fn_decl_span, .. }
let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. })
= tcx.hir().expect_expr(self.mir_hir_id()).kind
else {
bug!("Closure is not defined by a closure expr");
@ -701,16 +701,16 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let (return_span, mir_description, hir_ty) = match hir.get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, body, fn_decl_span, .. }),
..
}) => {
let (mut span, mut hir_ty) = match fn_decl.output {
hir::FnRetTy::DefaultReturn(_) => {
(tcx.sess.source_map().end_point(*fn_decl_span), None)
(tcx.sess.source_map().end_point(fn_decl_span), None)
}
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
};
let mir_description = match hir.body(*body).generator_kind {
let mir_description = match hir.body(body).generator_kind {
Some(hir::GeneratorKind::Async(gen)) => match gen {
hir::AsyncGeneratorKind::Block => " of async block",
hir::AsyncGeneratorKind::Closure => " of async closure",
@ -841,9 +841,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let yield_span = match tcx.hir().get(self.mir_hir_id()) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. },
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
}) => (tcx.sess.source_map().end_point(*fn_decl_span)),
}) => (tcx.sess.source_map().end_point(fn_decl_span)),
_ => self.body.span,
};

View file

@ -294,7 +294,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Block(_, _)
| ExprKind::Box(_)
| ExprKind::Break(_, _)
| ExprKind::Closure(_, _, _, _, _, _)
| ExprKind::Closure(_, _, _, _, _, _, _)
| ExprKind::ConstBlock(_)
| ExprKind::Continue(_)
| ExprKind::Err

View file

@ -520,6 +520,7 @@ impl<'a> ExtCtxt<'a> {
self.expr(
span,
ast::ExprKind::Closure(
ast::ClosureBinder::NotPresent,
ast::CaptureBy::Ref,
ast::Async::No,
ast::Movability::Movable,

View file

@ -148,6 +148,8 @@ declare_features! (
/// below (it has to be checked before expansion possibly makes
/// macros disappear).
(active, allow_internal_unstable, "1.0.0", None, None),
/// Allows using anonymous lifetimes in argument-position impl-trait.
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
/// Allows identifying the `compiler_builtins` crate.
(active, compiler_builtins, "1.13.0", None, None),
/// Outputs useful `assert!` messages
@ -328,6 +330,8 @@ declare_features! (
(active, cfg_target_thread_local, "1.7.0", Some(29594), None),
/// Allow conditional compilation depending on rust version
(active, cfg_version, "1.45.0", Some(64796), None),
/// Allows `for<...>` on closures and generators.
(active, closure_lifetime_binder, "1.64.0", Some(97362), None),
/// Allows `#[track_caller]` on closures and generators.
(active, closure_track_caller, "1.57.0", Some(87417), None),
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.

View file

@ -12,6 +12,7 @@ macro_rules! arena_types {
[] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span),
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
[] attribute: rustc_ast::Attribute,
[] closure: rustc_hir::Closure<'tcx>,
[] block: rustc_hir::Block<'tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<'tcx>,
[] body: rustc_hir::Body<'tcx>,

View file

@ -922,6 +922,17 @@ pub struct Crate<'hir> {
pub hir_hash: Fingerprint,
}
#[derive(Debug, HashStable_Generic)]
pub struct Closure<'hir> {
pub binder: ClosureBinder,
pub capture_clause: CaptureBy,
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub fn_decl: &'hir FnDecl<'hir>,
pub body: BodyId,
pub fn_decl_span: Span,
pub movability: Option<Movability>,
}
/// A block of statements `{ .. }`, which may have a label (in this case the
/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
/// the `rules` being anything but `DefaultBlock`.
@ -1915,14 +1926,7 @@ pub enum ExprKind<'hir> {
///
/// This may also be a generator literal or an `async block` as indicated by the
/// `Option<Movability>`.
Closure {
capture_clause: CaptureBy,
bound_generic_params: &'hir [GenericParam<'hir>],
fn_decl: &'hir FnDecl<'hir>,
body: BodyId,
fn_decl_span: Span,
movability: Option<Movability>,
},
Closure(&'hir Closure<'hir>),
/// A block (e.g., `'label: { ... }`).
Block(&'hir Block<'hir>, Option<Label>),
@ -2700,6 +2704,17 @@ impl FnRetTy<'_> {
}
}
/// Represents `for<...>` binder before a closure
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum ClosureBinder {
/// Binder is not specified.
Default,
/// Binder is specified.
///
/// Span points to the whole `for<...>`.
For { span: Span },
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct Mod<'hir> {
pub spans: ModSpans,
@ -3464,7 +3479,7 @@ impl<'hir> Node<'hir> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
rustc_data_structures::static_assert_size!(super::Expr<'static>, 64);
rustc_data_structures::static_assert_size!(super::Expr<'static>, 56);
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);

View file

@ -928,7 +928,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
FnKind::ItemFn(_, generics, ..) => {
visitor.visit_generics(generics);
}
FnKind::Method(..) | FnKind::Closure => {}
FnKind::Closure | FnKind::Method(..) => {}
}
}
@ -1147,14 +1147,15 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure {
ExprKind::Closure(&Closure {
binder: _,
bound_generic_params,
ref fn_decl,
fn_decl,
body,
capture_clause: _,
fn_decl_span: _,
movability: _,
} => {
}) => {
walk_list!(visitor, visit_generic_param, bound_generic_params);
visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
}

View file

@ -6,6 +6,7 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::LifetimeParamKind;
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::SourceMap;
@ -1452,15 +1453,16 @@ impl<'a> State<'a> {
}
self.bclose(expr.span);
}
hir::ExprKind::Closure {
hir::ExprKind::Closure(&hir::Closure {
binder,
capture_clause,
bound_generic_params,
fn_decl,
body,
fn_decl_span: _,
movability: _,
} => {
self.print_formal_generic_params(bound_generic_params);
}) => {
self.print_closure_binder(binder, bound_generic_params);
self.print_capture_clause(capture_clause);
self.print_closure_params(fn_decl, body);
@ -2045,6 +2047,42 @@ impl<'a> State<'a> {
}
}
pub fn print_closure_binder(
&mut self,
binder: hir::ClosureBinder,
generic_params: &[GenericParam<'_>],
) {
let generic_params = generic_params
.iter()
.filter(|p| {
matches!(
p,
GenericParam {
kind: GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit },
..
}
)
})
.collect::<Vec<_>>();
match binder {
hir::ClosureBinder::Default => {}
// we need to distinguish `|...| {}` from `for<> |...| {}` as `for<>` adds additional restrictions
hir::ClosureBinder::For { .. } if generic_params.is_empty() => self.word("for<>"),
hir::ClosureBinder::For { .. } => {
self.word("for");
self.word("<");
self.commasep(Inconsistent, &generic_params, |s, param| {
s.print_generic_param(param)
});
self.word(">");
self.nbsp();
}
}
}
pub fn print_bounds<'b>(
&mut self,
prefix: &'static str,

View file

@ -6,7 +6,7 @@ use rustc_hir::def::Res;
use rustc_hir::def::{CtorOf, DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
@ -1051,7 +1051,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
if let (
&ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
&ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
ty::Closure(_, substs),
) = (&expr.kind, node_ty.kind())
{

View file

@ -154,6 +154,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
self.check_id(closure_id);
}
}
run_early_pass!(self, check_fn_post, fk, span, id);
}
@ -218,7 +219,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
// Explicitly check for lints associated with 'closure_id', since
// it does not have a corresponding AST node
match e.kind {
ast::ExprKind::Closure(_, ast::Async::Yes { closure_id, .. }, ..)
ast::ExprKind::Closure(_, _, ast::Async::Yes { closure_id, .. }, ..)
| ast::ExprKind::Async(_, closure_id, ..) => self.check_id(closure_id),
_ => {}
}

View file

@ -22,7 +22,7 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
Node::Expr(Expr { kind: ExprKind::Closure { fn_decl, .. }, .. })
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. })
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
Some(fn_decl)
}
@ -54,7 +54,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
})
| Node::Expr(Expr { kind: ExprKind::Closure { body, .. }, .. }) => Some(*body),
| Node::Expr(Expr { kind: ExprKind::Closure(Closure { body, .. }), .. }) => Some(*body),
Node::AnonConst(constant) => Some(constant.body),
@ -279,8 +279,8 @@ impl<'hir> Map<'hir> {
}
Node::Field(_) => DefKind::Field,
Node::Expr(expr) => match expr.kind {
ExprKind::Closure { movability: None, .. } => DefKind::Closure,
ExprKind::Closure { movability: Some(_), .. } => DefKind::Generator,
ExprKind::Closure(Closure { movability: None, .. }) => DefKind::Closure,
ExprKind::Closure(Closure { movability: Some(_), .. }) => DefKind::Generator,
_ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
},
Node::GenericParam(param) => match param.kind {
@ -1021,7 +1021,9 @@ impl<'hir> Map<'hir> {
_ => named_span(item.span, item.ident, None),
},
Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)),
Node::Expr(Expr { kind: ExprKind::Closure { fn_decl_span, .. }, .. }) => *fn_decl_span,
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), .. }) => {
*fn_decl_span
}
_ => self.span_with_body(hir_id),
};
Some(span)

View file

@ -68,9 +68,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
// Figure out what primary body this item has.
let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { fn_decl, body, .. }, .. }) => {
(*body, fn_decl.output.span(), None)
}
Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { fn_decl, body, .. }),
..
}) => (*body, fn_decl.output.span(), None),
Node::Item(hir::Item {
kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
span,

View file

@ -15,10 +15,10 @@ use rustc_ast::util::classify;
use rustc_ast::util::literal::LitError;
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
use rustc_ast::visit::Visitor;
use rustc_ast::StmtKind;
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp, DUMMY_NODE_ID};
use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
use rustc_ast::{ClosureBinder, StmtKind};
use rustc_ast_pretty::pprust;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
@ -1343,11 +1343,7 @@ impl<'a> Parser<'a> {
self.parse_if_expr(attrs)
} else if self.check_keyword(kw::For) {
if self.choose_generics_over_qpath(1) {
// NOTE(Centril, eddyb): DO NOT REMOVE! Beyond providing parser recovery,
// this is an insurance policy in case we allow qpaths in (tuple-)struct patterns.
// When `for <Foo as Bar>::Proj in $expr $block` is wanted,
// you can disambiguate in favor of a pattern with `(...)`.
self.recover_quantified_closure_expr(attrs)
self.parse_closure_expr(attrs)
} else {
assert!(self.eat_keyword(kw::For));
self.parse_for_expr(None, self.prev_token.span, attrs)
@ -2096,30 +2092,22 @@ impl<'a> Parser<'a> {
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
}
/// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`.
fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
let _ = self.parse_late_bound_lifetime_defs()?;
let span_for = lo.to(self.prev_token.span);
let closure = self.parse_closure_expr(attrs)?;
self.struct_span_err(span_for, "cannot introduce explicit parameters for a closure")
.span_label(closure.span, "the parameters are attached to this closure")
.span_suggestion(
span_for,
"remove the parameters",
"",
Applicability::MachineApplicable,
)
.emit();
Ok(self.mk_expr_err(lo.to(closure.span)))
}
/// Parses a closure expression (e.g., `move |args| expr`).
fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
let binder = if self.check_keyword(kw::For) {
let lo = self.token.span;
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
let span = lo.to(self.prev_token.span);
self.sess.gated_spans.gate(sym::closure_lifetime_binder, span);
ClosureBinder::For { span, generic_params: P::from_vec(lifetime_defs) }
} else {
ClosureBinder::NotPresent
};
let movability =
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
@ -2162,7 +2150,15 @@ impl<'a> Parser<'a> {
let closure = self.mk_expr(
lo.to(body.span),
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
ExprKind::Closure(
binder,
capture_clause,
asyncness,
movability,
decl,
body,
lo.to(decl_hi),
),
attrs,
);

View file

@ -57,7 +57,13 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
hir::ExprKind::Loop(ref b, _, source, _) => {
self.with_context(Loop(source), |v| v.visit_block(&b));
}
hir::ExprKind::Closure { ref fn_decl, body, fn_decl_span, movability, .. } => {
hir::ExprKind::Closure(&hir::Closure {
ref fn_decl,
body,
fn_decl_span,
movability,
..
}) => {
let cx = if let Some(Movability::Static) = movability {
AsyncClosure(fn_decl_span)
} else {

View file

@ -273,7 +273,10 @@ impl<'tcx> ReachableContext<'tcx> {
}
hir::ImplItemKind::TyAlias(_) => {}
},
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) => {
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
..
}) => {
self.visit_nested_body(body);
}
// Nothing to recurse on for these

View file

@ -259,7 +259,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = match expr.kind {
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
ExprKind::Closure(_, asyncness, ..) => {
ExprKind::Closure(_, _, asyncness, ..) => {
// Async closures desugar to closures inside of closures, so
// we must create two defs.
let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);

View file

@ -268,6 +268,7 @@ enum LifetimeBinderKind {
WhereBound,
Item,
Function,
Closure,
ImplBlock,
}
@ -281,6 +282,7 @@ impl LifetimeBinderKind {
Item => "item",
ImplBlock => "impl block",
Function => "function",
Closure => "closure",
}
}
}
@ -758,7 +760,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// We don't need to deal with patterns in parameters, because
// they are not possible for foreign or bodiless functions.
self.with_lifetime_rib(
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
LifetimeRibKind::AnonymousCreateParameter {
binder: fn_id,
report_in_path: false,
},
|this| walk_list!(this, visit_param, &sig.decl.inputs),
);
self.with_lifetime_rib(
@ -792,18 +797,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// generic parameters. This is especially useful for `async fn`, where
// these fresh generic parameters can be applied to the opaque `impl Trait`
// return type.
let rib = if async_node_id.is_some() {
// Only emit a hard error for `async fn`, since this kind of
// elision has always been allowed in regular `fn`s.
this.with_lifetime_rib(
LifetimeRibKind::AnonymousCreateParameter {
binder: fn_id,
report_in_path: true,
}
} else {
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
};
this.with_lifetime_rib(
rib,
// Only emit a hard error for `async fn`, since this kind of
// elision has always been allowed in regular `fn`s.
report_in_path: async_node_id.is_some(),
},
// Add each argument to the rib.
|this| this.resolve_params(&declaration.inputs),
);
@ -868,19 +868,30 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
this.in_func_body = previous_state;
}
}
FnKind::Closure(declaration, body) => {
// We do not have any explicit generic lifetime parameter.
// FIXME(rfc3216): Change when implementing `for<>` bounds on closures.
FnKind::Closure(binder, declaration, body) => {
this.visit_closure_binder(binder);
this.with_lifetime_rib(
match binder {
// We do not have any explicit generic lifetime parameter.
ClosureBinder::NotPresent => {
LifetimeRibKind::AnonymousCreateParameter {
binder: fn_id,
report_in_path: false,
}
}
ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
},
// Add each argument to the rib.
|this| this.resolve_params(&declaration.inputs),
);
this.with_lifetime_rib(
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
match binder {
ClosureBinder::NotPresent => {
LifetimeRibKind::AnonymousPassThrough(fn_id, true)
}
ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
},
|this| visit::walk_fn_ret_ty(this, &declaration.output),
);
@ -915,6 +926,18 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
}
}
fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
match b {
ClosureBinder::NotPresent => {}
ClosureBinder::For { generic_params, .. } => {
self.visit_generic_params(
&generic_params,
self.diagnostic_metadata.current_self_item.is_some(),
);
}
}
}
fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
debug!("visit_generic_arg({:?})", arg);
let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true);
@ -3519,7 +3542,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
// resolve the arguments within the proper scopes so that usages of them inside the
// closure are detected as upvars rather than normal closure arg usages.
ExprKind::Closure(_, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
ExprKind::Closure(_, _, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
self.with_rib(ValueNS, NormalRibKind, |this| {
this.with_label_rib(ClosureOrAsyncRibKind, |this| {
// Resolve arguments:
@ -3539,6 +3562,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
});
}
// For closures, ClosureOrAsyncRibKind is added in visit_fn
ExprKind::Closure(ClosureBinder::For { ref generic_params, span }, ..) => {
self.with_generic_param_rib(
&generic_params,
NormalRibKind,
LifetimeRibKind::Generics {
binder: expr.id,
kind: LifetimeBinderKind::Closure,
span,
},
|this| visit::walk_expr(this, expr),
);
}
ExprKind::Closure(..) => visit::walk_expr(self, expr),
ExprKind::Async(..) => {
self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr));

View file

@ -70,6 +70,8 @@ pub(crate) enum ForLifetimeSpanType {
BoundTail,
TypeEmpty,
TypeTail,
ClosureEmpty,
ClosureTail,
}
impl ForLifetimeSpanType {
@ -77,13 +79,15 @@ impl ForLifetimeSpanType {
match self {
Self::BoundEmpty | Self::BoundTail => "bound",
Self::TypeEmpty | Self::TypeTail => "type",
Self::ClosureEmpty | Self::ClosureTail => "closure",
}
}
pub(crate) fn suggestion(&self, sugg: &str) -> String {
match self {
Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
Self::ClosureEmpty => format!("for<{}>", sugg),
Self::BoundTail | Self::TypeTail | Self::ClosureTail => format!(", {}", sugg),
}
}
}

View file

@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
use rustc_hir::{GenericParamKind, HirIdMap};
use rustc_hir::{GenericParamKind, HirIdMap, LifetimeParamKind};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*;
@ -571,7 +571,54 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
if let hir::ExprKind::Closure(hir::Closure {
binder, bound_generic_params, fn_decl, ..
}) = e.kind
{
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
struct V(Option<Span>);
impl<'v> Visitor<'v> for V {
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
match t.kind {
_ if self.0.is_some() => (),
hir::TyKind::Infer => {
self.0 = Some(t.span);
}
_ => intravisit::walk_ty(self, t),
}
}
}
let mut v = V(None);
v.visit_ty(ty);
v.0
}
let infer_in_rt_sp = match fn_decl.output {
hir::FnRetTy::DefaultReturn(sp) => Some(sp),
hir::FnRetTy::Return(ty) => span_of_infer(ty),
};
let infer_spans = fn_decl
.inputs
.into_iter()
.filter_map(span_of_infer)
.chain(infer_in_rt_sp)
.collect::<Vec<_>>();
if !infer_spans.is_empty() {
self.tcx.sess
.struct_span_err(
infer_spans,
"implicit types in closure signatures are forbidden when `for<...>` is present",
)
.span_label(for_sp, "`for<...>` is here")
.emit();
}
}
let next_early_index = self.next_early_index();
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
bound_generic_params
@ -584,6 +631,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
(pair, r)
})
.unzip();
self.map.late_bound_vars.insert(e.hir_id, binders);
let scope = Scope::Binder {
hir_id: e.hir_id,
@ -595,11 +643,41 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
allow_late_bound: true,
where_bound_origin: None,
};
if let &hir::ClosureBinder::For { span, .. } = binder {
let last_lt = bound_generic_params
.iter()
.filter(|p| {
matches!(
p,
GenericParam {
kind: GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit
},
..
}
)
})
.last();
let (span, span_type) = match last_lt {
Some(GenericParam { span: last_sp, .. }) => {
(last_sp.shrink_to_hi(), ForLifetimeSpanType::ClosureTail)
}
None => (span, ForLifetimeSpanType::ClosureEmpty),
};
self.missing_named_lifetime_spots
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
}
self.with(scope, |this| {
// a closure has no bounds, so everything
// contained within is scoped within its binder.
intravisit::walk_expr(this, e)
});
if let hir::ClosureBinder::For { .. } = binder {
self.missing_named_lifetime_spots.pop();
}
} else {
intravisit::walk_expr(self, e)
}
@ -1677,7 +1755,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
break None;
}
Scope::Binder { ref lifetimes, scope_type, s, .. } => {
Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
if let Some(&def) = lifetimes.get(&region_def_id) {
break Some(def.shifted(late_depth));
}
@ -1685,6 +1763,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
BinderScopeType::Normal => late_depth += 1,
BinderScopeType::Concatenating => {}
}
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
// regular fns.
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
&& let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
rustc_session::parse::feature_err(
&self.tcx.sess.parse_sess,
sym::anonymous_lifetime_in_impl_trait,
lifetime_ref.span,
"anonymous lifetimes in `impl Trait` are unstable",
).emit();
return;
}
scope = s;
}

View file

@ -1353,7 +1353,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
}
}
hir::ExprKind::Closure { ref fn_decl, body, .. } => {
hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, .. }) => {
let id = format!("${}", ex.hir_id);
// walk arg and return types

View file

@ -644,7 +644,10 @@ pub fn debug_hygiene_data(verbose: bool) -> String {
let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID");
debug_expn_data((&id.to_expn_id(), expn_data))
});
// Sort the hash map for more reproducible output.
// Because of this, it is fine to rely on the unstable iteration order of the map.
#[allow(rustc::potential_query_instability)]
let mut foreign_expn_data: Vec<_> = data.foreign_expn_data.iter().collect();
foreign_expn_data.sort_by_key(|(id, _)| (id.krate, id.local_id));
foreign_expn_data.into_iter().for_each(debug_expn_data);
@ -1208,6 +1211,7 @@ impl HygieneEncodeContext {
// It's fine to iterate over a HashMap, because the serialization
// of the table that we insert data into doesn't depend on insertion
// order
#[allow(rustc::potential_query_instability)]
for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| {
if self.serialized_ctxts.lock().insert(ctxt) {
encode_ctxt(encoder, index, data);
@ -1216,6 +1220,8 @@ impl HygieneEncodeContext {
let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
// Same as above, this is fine as we are inserting into a order-independent hashset
#[allow(rustc::potential_query_instability)]
for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
if self.serialized_expns.lock().insert(expn) {
encode_expn(encoder, expn, data, hash);

View file

@ -20,7 +20,6 @@
#![feature(negative_impls)]
#![feature(min_specialization)]
#![feature(rustc_attrs)]
#![allow(rustc::potential_query_instability)]
#[macro_use]
extern crate rustc_macros;

View file

@ -341,6 +341,7 @@ symbols! {
always,
and,
and_then,
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,
arbitrary_enum_discriminant,
@ -459,6 +460,7 @@ symbols! {
clone_closures,
clone_from,
closure,
closure_lifetime_binder,
closure_to_fn_coercion,
closure_track_caller,
cmp,

View file

@ -1086,7 +1086,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let hir = self.tcx.hir();
Some(match node {
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure { body, fn_decl_span, .. },
kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }),
..
}) => (
sm.guess_head_span(fn_decl_span),

View file

@ -103,7 +103,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
})
}),
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { body, movability, .. },
kind: hir::ExprKind::Closure(hir::Closure { body, movability, .. }),
..
}) => self.describe_generator(*body).or_else(|| {
Some(if movability.is_some() { "an async closure" } else { "a closure" })

View file

@ -786,7 +786,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Get the name of the callable and the arguments to be used in the suggestion.
let (snippet, sugg) = match hir.get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl, fn_decl_span, .. },
kind: hir::ExprKind::Closure(hir::Closure { fn_decl, fn_decl_span, .. }),
..
})) => {
err.span_label(*fn_decl_span, "consider calling this closure");

View file

@ -285,29 +285,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let parent_node = hir.get(parent_hir_id);
if let (
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, body, .. },
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, body, .. }),
..
}),
hir::ExprKind::Block(..),
) = (parent_node, callee_node)
{
let fn_decl_span = if hir.body(*body).generator_kind
let fn_decl_span = if hir.body(body).generator_kind
== Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
{
// Actually need to unwrap a few more layers of HIR to get to
// the _real_ closure...
let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. },
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
}) = hir.get(async_closure)
{
*fn_decl_span
fn_decl_span
} else {
return;
}
} else {
*fn_decl_span
fn_decl_span
};
let start = fn_decl_span.shrink_to_lo();

View file

@ -1577,8 +1577,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let parent_id = fcx.tcx.hir().get_parent_node(id);
let parent = fcx.tcx.hir().get(parent_id);
if let Some(expr) = expression
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) = parent
&& !matches!(fcx.tcx.hir().body(*body).value.kind, hir::ExprKind::Block(..))
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { body, .. }), .. }) = parent
&& !matches!(fcx.tcx.hir().body(body).value.kind, hir::ExprKind::Block(..))
{
fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
}

View file

@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
let Some(Node::Expr(hir::Expr {
hir_id: expr_hir_id,
kind: hir::ExprKind::Closure { fn_decl: closure_fn_decl, .. },
kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
..
})) = self.tcx.hir().find(param_parent) else {
return None;

View file

@ -35,7 +35,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir::{Closure, ExprKind, HirId, QPath};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferOk;
@ -319,7 +319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Match(discrim, arms, match_src) => {
self.check_match(expr, &discrim, arms, expected, match_src)
}
ExprKind::Closure { capture_clause, fn_decl, body, movability, .. } => {
ExprKind::Closure(&Closure { capture_clause, fn_decl, body, movability, .. }) => {
self.check_expr_closure(expr, capture_clause, &fn_decl, body, movability, expected)
}
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),

View file

@ -1825,7 +1825,7 @@ fn label_fn_like<'tcx>(
} else {
match tcx.hir().get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. },
kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
..
})) => {
let spans: MultiSpan = (*fn_decl_span).into();

View file

@ -335,7 +335,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
match expr.kind {
// Manually recurse over closures and inline consts, because they are the only
// case of nested bodies that share the parent environment.
hir::ExprKind::Closure { body, .. }
hir::ExprKind::Closure(&hir::Closure { body, .. })
| hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
let body = visitor.tcx.hir().body(body);
visitor.visit_body(body);

View file

@ -142,7 +142,7 @@ struct InferBorrowKindVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Closure { capture_clause, body: body_id, .. } => {
hir::ExprKind::Closure(&hir::Closure { capture_clause, body: body_id, .. }) => {
let body = self.fcx.tcx.hir().body(body_id);
self.visit_body(body);
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);

View file

@ -263,7 +263,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
self.fix_index_builtin_expr(e);
match e.kind {
hir::ExprKind::Closure { body, .. } => {
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let body = self.fcx.tcx.hir().body(body);
for param in body.params {
self.visit_node_id(e.span, param.hir_id);

View file

@ -1717,8 +1717,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
// provide junk type parameter defs - the only place that
// cares about anything but the length is instantiation,
// and we don't do that for closures.
if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { movability: gen, .. }, .. }) =
node
if let Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { movability: gen, .. }),
..
}) = node
{
let dummy_args = if gen.is_some() {
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
@ -2564,7 +2566,7 @@ fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> {
match tcx.hir().get_if_local(def_id) {
Some(Node::Expr(&rustc_hir::Expr {
kind: rustc_hir::ExprKind::Closure { body, .. },
kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
..
})) => tcx.hir().body(body).generator_kind(),
Some(_) => None,

View file

@ -108,7 +108,6 @@
#![feature(const_refs_to_cell)]
#![feature(core_c_str)]
#![feature(core_intrinsics)]
#![feature(core_ffi_c)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(cstr_from_bytes_until_nul)]

View file

@ -12,7 +12,6 @@
#![feature(const_ptr_write)]
#![feature(const_try)]
#![feature(core_c_str)]
#![feature(core_ffi_c)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]

View file

@ -26,7 +26,7 @@ macro_rules! type_alias_no_nz {
} => {
#[doc = include_str!($Docfile)]
$( $Cfg )*
#[unstable(feature = "core_ffi_c", issue = "94501")]
#[stable(feature = "core_ffi_c", since = "1.64.0")]
pub type $Alias = $Real;
}
}

View file

@ -19,7 +19,6 @@
#![feature(const_ptr_write)]
#![feature(const_trait_impl)]
#![feature(const_likely)]
#![feature(core_ffi_c)]
#![feature(core_intrinsics)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]

View file

@ -168,6 +168,12 @@ pub type FromBytesWithNulError = core::ffi::FromBytesWithNulError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsStr, OsString};
#[stable(feature = "core_ffi_c", since = "1.64.0")]
pub use core::ffi::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
c_ulong, c_ulonglong, c_ushort,
};
#[stable(feature = "core_c_void", since = "1.30.0")]
pub use core::ffi::c_void;

View file

@ -317,7 +317,6 @@
#![feature(cfg_eval)]
#![feature(concat_bytes)]
#![feature(const_format_args)]
#![feature(core_ffi_c)]
#![feature(core_panic)]
#![feature(custom_test_frameworks)]
#![feature(edition_panic)]

View file

@ -39,7 +39,11 @@ fn missing_tool(tool_name: &str, skip: bool) {
if skip {
println!("Unable to build {}, skipping dist", tool_name)
} else {
panic!("Unable to build {}", tool_name)
let help = "note: not all tools are available on all nightlies\nhelp: see https://forge.rust-lang.org/infra/toolstate.html for more information";
panic!(
"Unable to build submodule tool {} (use `missing-tools = true` to ignore this failure)\n{}",
tool_name, help
)
}
}

View file

@ -93,7 +93,7 @@ impl CustomStruct {
fn test_alias(
value: CustomAlias,
reference: &CustomAlias, //~ ERROR passing `CustomAlias<>` by reference
reference: &CustomAlias, //~ ERROR passing `CustomAlias<'_>` by reference
) {
}
}

View file

@ -94,11 +94,11 @@ error: passing `CustomStruct` by reference
LL | reference: &CustomStruct,
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
error: passing `CustomAlias<>` by reference
error: passing `CustomAlias<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:96:20
|
LL | reference: &CustomAlias,
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<'_>`
error: passing `WithParameters<T, 1>` by reference
--> $DIR/rustc_pass_by_value.rs:110:20

View file

@ -114,6 +114,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
let decl = P(FnDecl { inputs: vec![], output: FnRetTy::Default(DUMMY_SP) });
iter_exprs(depth - 1, &mut |e| {
g(ExprKind::Closure(
ClosureBinder::NotPresent,
CaptureBy::Value,
Async::No,
Movability::Movable,

View file

@ -0,0 +1,8 @@
// edition:2021
#![feature(closure_lifetime_binder)]
#![feature(async_closure)]
fn main() {
for<'a> async || ();
//~^ ERROR `for<...>` binders on `async` closures are not currently supported
//~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
}

View file

@ -0,0 +1,16 @@
error: `for<...>` binders on `async` closures are not currently supported
--> $DIR/async-closure-with-binder.rs:5:5
|
LL | for<'a> async || ();
| ^^^^^^^
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/async-closure-with-binder.rs:5:5
|
LL | for<'a> async || ();
| -------^^^^^^^^^
| |
| `for<...>` is here
error: aborting due to 2 previous errors

View file

@ -0,0 +1,6 @@
#![feature(closure_lifetime_binder)]
fn main() {
let _f = for<'a> |_: &'a ()| {};
//~^ implicit types in closure signatures are forbidden when `for<...>` is present
}

View file

@ -0,0 +1,10 @@
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-return.rs:4:34
|
LL | let _f = for<'a> |_: &'a ()| {};
| ------- ^
| |
| `for<...>` is here
error: aborting due to previous error

View file

@ -0,0 +1,27 @@
#![feature(closure_lifetime_binder)]
fn main() {
// Implicit types
let _ = for<> || {}; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> || -> &'a _ { &() }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x| -> &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x: &'a _| -> &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x: &'a Vec::<_>| -> &'a Vec::<()> { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x: &'a Vec<()>| -> &'a Vec<_> { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x: &'a _| -> &'a &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
let _: &u8 = x;
let _: u32 = y;
let _: i32 = z;
x
};
// Lifetime elision
let _ = for<> |_: &()| -> () {}; //~ ERROR `&` without an explicit lifetime name cannot be used here
let _ = for<> |x: &()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here
//~| ERROR `&` without an explicit lifetime name cannot be used here
let _ = for<> |x: &'_ ()| -> &'_ () { x }; //~ ERROR `'_` cannot be used here
//~| ERROR `'_` cannot be used here
let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here
let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here
}

View file

@ -0,0 +1,107 @@
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/implicit-stuff.rs:20:23
|
LL | let _ = for<> |_: &()| -> () {};
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/implicit-stuff.rs:21:23
|
LL | let _ = for<> |x: &()| -> &() { x };
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/implicit-stuff.rs:21:31
|
LL | let _ = for<> |x: &()| -> &() { x };
| ^ explicit lifetime name needed here
error[E0637]: `'_` cannot be used here
--> $DIR/implicit-stuff.rs:23:24
|
LL | let _ = for<> |x: &'_ ()| -> &'_ () { x };
| ^^ `'_` is a reserved lifetime name
error[E0637]: `'_` cannot be used here
--> $DIR/implicit-stuff.rs:23:35
|
LL | let _ = for<> |x: &'_ ()| -> &'_ () { x };
| ^^ `'_` is a reserved lifetime name
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/implicit-stuff.rs:25:25
|
LL | let _ = for<'a> |x: &()| -> &'a () { x };
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/implicit-stuff.rs:26:36
|
LL | let _ = for<'a> |x: &'a ()| -> &() { x };
| ^ explicit lifetime name needed here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:5:22
|
LL | let _ = for<> || {};
| ----- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:6:31
|
LL | let _ = for<'a> || -> &'a _ { &() };
| ------- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:7:22
|
LL | let _ = for<'a> |x| -> &'a () { x };
| ------- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:8:29
|
LL | let _ = for<'a> |x: &'a _| -> &'a () { x };
| ------- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:9:35
|
LL | let _ = for<'a> |x: &'a Vec::<_>| -> &'a Vec::<()> { x };
| ------- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:10:49
|
LL | let _ = for<'a> |x: &'a Vec<()>| -> &'a Vec<_> { x };
| ------- `for<...>` is here ^
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:11:29
|
LL | let _ = for<'a> |x: &'a _| -> &'a &'a () { x };
| ------- ^
| |
| `for<...>` is here
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:12:29
|
LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ {
| ------- ^ ^ ^ ^
| |
| `for<...>` is here
error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0637`.

View file

@ -0,0 +1,7 @@
#![feature(closure_lifetime_binder)]
fn main() {
for<> |_: &'a ()| -> () {};
//~^ ERROR use of undeclared lifetime name `'a`
for<'a> |_: &'b ()| -> () {};
//~^ ERROR use of undeclared lifetime name `'b`
}

View file

@ -0,0 +1,33 @@
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:3:16
|
LL | for<> |_: &'a ()| -> () {};
| ^^ undeclared lifetime
|
help: consider introducing lifetime `'a` here
|
LL | for<'a, > |_: &'a ()| -> () {};
| +++
help: consider introducing lifetime `'a` here
|
LL | fn main<'a>() {
| ++++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:5:18
|
LL | for<'a> |_: &'b ()| -> () {};
| ^^ undeclared lifetime
|
help: consider introducing lifetime `'b` here
|
LL | for<'b, 'a> |_: &'b ()| -> () {};
| +++
help: consider introducing lifetime `'b` here
|
LL | fn main<'b>() {
| ++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0261`.

View file

@ -0,0 +1,8 @@
fn main() {
for<> || -> () {};
//~^ ERROR `for<...>` binders for closures are experimental
for<'a> || -> () {};
//~^ ERROR `for<...>` binders for closures are experimental
for<'a, 'b> |_: &'a ()| -> () {};
//~^ ERROR `for<...>` binders for closures are experimental
}

View file

@ -0,0 +1,33 @@
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
LL | for<> || -> () {};
| ^^^^^
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
= help: consider removing `for<...>`
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/feature-gate-closure_lifetime_binder.rs:4:5
|
LL | for<'a> || -> () {};
| ^^^^^^^
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
= help: consider removing `for<...>`
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/feature-gate-closure_lifetime_binder.rs:6:5
|
LL | for<'a, 'b> |_: &'a ()| -> () {};
| ^^^^^^^^^^^
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
= help: consider removing `for<...>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
note: lifetime parameter instantiated with the anonymous lifetime as defined here
--> $DIR/issue-87748.rs:18:5
|
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
note: but lifetime parameter must outlive the anonymous lifetime as defined here
--> $DIR/issue-87748.rs:18:5
|
LL | fn do_sth(_: u32) {}

View file

@ -3,7 +3,7 @@
// at some point in the future.
#![feature(generic_associated_types)]
#![feature(anonymous_lifetime_in_impl_trait)]
trait Foo {
type Item<'a>;
}
@ -11,7 +11,10 @@ trait Foo {
fn foo(x: &impl Foo<Item<'_> = u32>) { }
//~^ ERROR `'_` cannot be used here [E0637]
// Ok: the anonymous lifetime is bound to the function.
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
//~^ ERROR missing lifetime specifier
// Ok: the anonymous lifetime is bound to the function.
fn baz(x: &impl for<'a> Foo<Item<'a> = &u32>) { }
fn main() {}

View file

@ -4,18 +4,6 @@ error[E0637]: `'_` cannot be used here
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
| ^^ `'_` is a reserved lifetime name
error[E0106]: missing lifetime specifier
--> $DIR/issue-95305.rs:14:41
|
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
| ^^ expected named lifetime parameter
|
help: consider using the `'a` lifetime
|
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'a u32>) { }
| ~~
error: aborting due to previous error
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
For more information about this error, try `rustc --explain E0637`.

View file

@ -6,7 +6,7 @@ LL | fn next(&'a mut self) -> Option<Self::Item>
|
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
note: the anonymous lifetime #1 defined here...
note: the anonymous lifetime as defined here...
--> $DIR/issue-37884.rs:6:5
|
LL | fn next(&'a mut self) -> Option<Self::Item>

View file

@ -2,14 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
--> $DIR/impl-trait-captures.rs:11:5
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
LL | x
| ^
|
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error

View file

@ -1,10 +1,12 @@
fn main() {
for<'a> |x: &'a u8| *x + 1;
//~^ ERROR cannot introduce explicit parameters for a closure
//~^ ERROR `for<...>` binders for closures are experimental
//~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
}
enum Foo { Bar }
fn foo(x: impl Iterator<Item = Foo>) {
for <Foo>::Bar in x {}
//~^ ERROR expected one of `move`, `static`, `|`
//~^^ ERROR `for<...>` binders for closures are experimental
}

View file

@ -1,16 +1,37 @@
error: cannot introduce explicit parameters for a closure
--> $DIR/recover-quantified-closure.rs:2:5
|
LL | for<'a> |x: &'a u8| *x + 1;
| ^^^^^^^ ------------------ the parameters are attached to this closure
| |
| help: remove the parameters
error: expected one of `move`, `static`, `|`, or `||`, found `::`
--> $DIR/recover-quantified-closure.rs:8:14
--> $DIR/recover-quantified-closure.rs:9:14
|
LL | for <Foo>::Bar in x {}
| ^^ expected one of `move`, `static`, `|`, or `||`
error: aborting due to 2 previous errors
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/recover-quantified-closure.rs:2:5
|
LL | for<'a> |x: &'a u8| *x + 1;
| ^^^^^^^
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
= help: consider removing `for<...>`
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/recover-quantified-closure.rs:9:5
|
LL | for <Foo>::Bar in x {}
| ^^^^^^^^^
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
= help: consider removing `for<...>`
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/recover-quantified-closure.rs:2:25
|
LL | for<'a> |x: &'a u8| *x + 1;
| ------- ^
| |
| `for<...>` is here
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,21 @@
// edition:2021
// gate-test-anonymous_lifetime_in_impl_trait
// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.
fn f(_: impl Iterator<Item = &'_ ()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~| ERROR missing lifetime specifier
// Anonymous lifetimes in async fn are already allowed.
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
async fn h(_: impl Iterator<Item = &'_ ()>) {}
// Anonymous lifetimes in async fn are already allowed.
// But that lifetime does not participate in resolution.
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier
fn main() {}

View file

@ -0,0 +1,44 @@
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
| ^^
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:50
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:31
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:18:56
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0106, E0658.
For more information about an error, try `rustc --explain E0106`.

View file

@ -1,2 +1,19 @@
fn f(_: impl Iterator<Item = &'_ ()>) {} //~ ERROR missing lifetime specifier
// edition:2021
#![feature(anonymous_lifetime_in_impl_trait)]
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
fn f(_: impl Iterator<Item = &'_ ()>) {}
// But that lifetime does not participate in resolution.
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
async fn h(_: impl Iterator<Item = &'_ ()>) {}
// But that lifetime does not participate in resolution.
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier
fn main() {}

View file

@ -1,14 +1,27 @@
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime.rs:1:31
--> $DIR/impl-trait-missing-lifetime.rs:9:50
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
| ++++ ~~
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error: aborting due to previous error
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime.rs:16:56
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0106`.

View file

@ -21,11 +21,11 @@ note: because this has an unmet lifetime requirement
|
LL | pub struct Wrapper<T: Trait>(T);
| ^^^^^ introduces a `'static` lifetime requirement
note: the anonymous lifetime #1 defined here...
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5
note: the anonymous lifetime as defined here...
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29
|
LL | pub fn repro(_: Wrapper<Ref>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^
note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
|

View file

@ -6,7 +6,7 @@ use clippy_utils::ty::implements_trait;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BlockCheckMode, Expr, ExprKind};
use rustc_hir::{BlockCheckMode, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -51,7 +51,7 @@ struct ExVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Closure { body, .. } = expr.kind {
if let ExprKind::Closure(&Closure { body, .. }) = expr.kind {
// do not lint if the closure is called using an iterator (see #1141)
if_chain! {
if let Some(parent) = get_parent_expr(self.cx, expr);

View file

@ -5,7 +5,7 @@ use clippy_utils::visitors::is_local_used;
use clippy_utils::{path_to_local_id, paths, peel_blocks, peel_ref_operators, strip_pat_refs};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind};
use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, UintTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
if count.ident.name == sym::count;
if let ExprKind::MethodCall(filter, [filter_recv, filter_arg], _) = count_recv.kind;
if filter.ident.name == sym!(filter);
if let ExprKind::Closure { body, .. } = filter_arg.kind;
if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind;
let body = cx.tcx.hir().body(body);
if let [param] = body.params;
if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;

View file

@ -7,7 +7,7 @@ use clippy_utils::{higher, is_adjusted, path_to_local, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, Param, PatKind, Unsafety};
use rustc_hir::{Closure, Expr, ExprKind, Param, PatKind, Unsafety};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
return;
}
let body = match expr.kind {
ExprKind::Closure { body, .. } => cx.tcx.hir().body(body),
ExprKind::Closure(&Closure { body, .. }) => cx.tcx.hir().body(body),
_ => return,
};
if body.value.span.from_expansion() {

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{higher, match_def_path, path_def_id, paths};
use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{sym, Symbol};
@ -159,7 +159,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
}
}
if method.ident.name == sym!(flat_map) && args.len() == 2 {
if let ExprKind::Closure { body, .. } = args[1].kind {
if let ExprKind::Closure(&Closure { body, .. }) = args[1].kind {
let body = cx.tcx.hir().body(body);
return is_infinite(cx, &body.value);
}

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{ImplItem, ImplItemKind};
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
let decl = &signature.decl;
if decl.implicit_self.has_implicit_self();
if decl.inputs.len() == 1;
if impl_item.generics.params.is_empty();
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
// Check if return type is String
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);

View file

@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, LifetimeParamKind, ParamName, PolyTraitRef,
PredicateOrigin, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -338,7 +338,10 @@ fn could_use_elision<'tcx>(
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
let mut allowed_lts = FxHashSet::default();
for par in named_generics.iter() {
if let GenericParamKind::Lifetime { .. } = par.kind {
if let GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} = par.kind
{
allowed_lts.insert(RefLt::Named(par.name.ident().name));
}
}
@ -379,6 +382,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
self.lts.push(RefLt::Static);
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
// Fresh lifetimes generated should be ignored.
self.lts.push(RefLt::Unnamed);
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
} else {

View file

@ -9,7 +9,7 @@ use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::middle::region;
use rustc_middle::ty::{self, Ty};
@ -369,7 +369,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
self.visit_expr(expr);
}
},
ExprKind::Closure { body, .. } => {
ExprKind::Closure(&Closure { body, .. }) => {
let body = self.cx.tcx.hir().body(body);
self.visit_expr(&body.value);
},

View file

@ -8,7 +8,7 @@ use clippy_utils::{
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
use rustc_hir::{Closure, def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_span::{symbol::sym, Symbol};
@ -220,7 +220,7 @@ fn uses_iter<'tcx>(cx: &LateContext<'tcx>, iter_expr: &IterExpr, container: &'tc
if let Some(e) = e {
self.visit_expr(e);
}
} else if let ExprKind::Closure { body: id, .. } = e.kind {
} else if let ExprKind::Closure(&Closure { body: id, .. }) = e.kind {
if is_res_used(self.cx, self.iter_expr.path, id) {
self.uses_iter = true;
}
@ -260,7 +260,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
if let Some(e) = e {
self.visit_expr(e);
}
} else if let ExprKind::Closure { body: id, .. } = e.kind {
} else if let ExprKind::Closure(&Closure { body: id, .. }) = e.kind {
self.used_iter = is_res_used(self.cx, self.iter_expr.path, id);
} else {
walk_expr(self, e);
@ -307,7 +307,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
if let Some(e) = e {
self.visit_expr(e);
}
} else if let ExprKind::Closure { body: id, .. } = e.kind {
} else if let ExprKind::Closure(&Closure { body: id, .. }) = e.kind {
self.used_after = is_res_used(self.cx, self.iter_expr.path, id);
} else {
walk_expr(self, e);

View file

@ -6,7 +6,7 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
@ -177,7 +177,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
if let Some(block_expr) = block.expr;
if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
if args.len() == 1;
if let Expr{kind: ExprKind::Closure { body, .. }, ..} = args[0];
if let Expr{kind: ExprKind::Closure(&Closure { body, .. }), ..} = args[0];
let closure_body = cx.tcx.hir().body(body);
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
then {

View file

@ -5,7 +5,7 @@ use clippy_utils::{is_lang_ctor, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{ResultErr, ResultOk};
use rustc_hir::{Expr, ExprKind, PatKind};
use rustc_hir::{Closure, Expr, ExprKind, PatKind};
use rustc_lint::LintContext;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
@ -88,7 +88,7 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
}
}
if_chain! {
if let ExprKind::Closure { body, .. } = map_expr.kind;
if let ExprKind::Closure(&Closure { body, .. }) = map_expr.kind;
let body = cx.tcx.hir().body(body);
if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;

View file

@ -148,7 +148,7 @@ fn check_to_owned(
fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) {
if let hir::ExprKind::MethodCall(_, [_, closure], _) = filter_expr.kind
&& let hir::ExprKind::Closure{ body, ..} = closure.kind
&& let hir::ExprKind::Closure(&hir::Closure { body, ..}) = closure.kind
&& let filter_body = cx.tcx.hir().body(body)
&& let [filter_params] = filter_body.params
&& let Some(sugg) = match filter_params.pat.kind {

View file

@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
if method.ident.name == sym::map;
let ty = cx.typeck_results().expr_ty(&args[0]);
if is_type_diagnostic_item(cx, ty, sym::Option) || is_trait_method(cx, e, sym::Iterator);
if let hir::ExprKind::Closure { body, .. } = args[1].kind;
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = args[1].kind;
then {
let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(&closure_body.value);

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::{CaptureBy, Expr, ExprKind, PatKind};
use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -119,12 +119,12 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
if method.ident.as_str() == "map_err" && args.len() == 2 {
// make sure the first argument is a closure, and grab the CaptureRef, BodyId, and fn_decl_span
// fields
if let ExprKind::Closure {
if let ExprKind::Closure(&Closure {
capture_clause,
body,
fn_decl_span,
..
} = args[1].kind
}) = args[1].kind
{
// check if this is by Reference (meaning there's no move statement)
if capture_clause == CaptureBy::Ref {

View file

@ -169,7 +169,7 @@ fn unit_closure<'tcx>(
expr: &hir::Expr<'_>,
) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
if_chain! {
if let hir::ExprKind::Closure { fn_decl, body, .. } = expr.kind;
if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind;
let body = cx.tcx.hir().body(body);
let body_expr = &body.value;
if fn_decl.inputs.len() == 1;

View file

@ -150,7 +150,7 @@ pub(crate) trait BindInsteadOfMap {
}
match arg.kind {
hir::ExprKind::Closure { body, fn_decl_span, .. } => {
hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) => {
let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(&closure_body.value);

View file

@ -6,7 +6,7 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::{Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_span::source_map::Span;
use rustc_span::symbol::{sym, Symbol};
@ -22,8 +22,8 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
segments.segments.last().unwrap().ident.name == method_name
},
hir::ExprKind::Closure { body, .. } => {
let body = cx.tcx.hir().body(*body);
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(&body.value);
let arg_id = body.params[0].pat.hir_id;
match closure_expr.kind {
@ -106,7 +106,7 @@ pub(super) fn check<'tcx>(
if is_trait_method(cx, map_recv, sym::Iterator);
// filter(|x| ...is_some())...
if let ExprKind::Closure { body: filter_body_id, .. } = filter_arg.kind;
if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
let filter_body = cx.tcx.hir().body(filter_body_id);
if let [filter_param] = filter_body.params;
// optional ref pattern: `filter(|&x| ..)`
@ -129,7 +129,7 @@ pub(super) fn check<'tcx>(
if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
// ...map(|x| ...unwrap())
if let ExprKind::Closure { body: map_body_id, .. } = map_arg.kind;
if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
let map_body = cx.tcx.hir().body(map_body_id);
if let [map_param] = map_body.params;
if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;

View file

@ -51,7 +51,7 @@ pub(super) fn check<'tcx>(
.map_or(false, |fun_def_id| {
deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
}),
hir::ExprKind::Closure { body, .. } => {
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(&closure_body.value);

View file

@ -71,7 +71,7 @@ pub(super) fn check<'tcx>(
if is_option {
let self_snippet = snippet(cx, recv.span, "..");
if_chain! {
if let hir::ExprKind::Closure { body, fn_decl_span, .. } = map_arg.kind;
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind;
let arg_snippet = snippet(cx, fn_decl_span, "..");
let body = cx.tcx.hir().body(body);
if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);

View file

@ -41,7 +41,7 @@ pub(super) fn check<'tcx>(
let mut applicability = Applicability::MachineApplicable;
let any_search_snippet = if_chain! {
if search_method == "find";
if let hir::ExprKind::Closure { body, .. } = search_arg.kind;
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind;
let closure_body = cx.tcx.hir().body(body);
if let Some(closure_arg) = closure_body.params.get(0);
then {

View file

@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
return;
}
if let hir::ExprKind::Closure { body, .. } = arg.kind {
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind {
let body = cx.tcx.hir().body(body);
let arg_id = body.params[0].pat.hir_id;
let mutates_arg =

View file

@ -29,7 +29,7 @@ pub(super) fn check(
) {
if_chain! {
// Extract the body of the closure passed to fold
if let hir::ExprKind::Closure { body, .. } = acc.kind;
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(&closure_body.value);

View file

@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
if is_option || is_result {
if let hir::ExprKind::Closure { body, .. } = arg.kind {
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind {
let body = cx.tcx.hir().body(body);
let body_expr = &body.value;

View file

@ -1,7 +1,7 @@
use rustc_errors::Applicability;
use rustc_hir::{
intravisit::{walk_expr, Visitor},
Expr, ExprKind, Stmt, StmtKind,
Closure, Expr, ExprKind, Stmt, StmtKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some();
// Skip the lint if the body is not block because this is simpler than `for` loop.
// e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
if let ExprKind::Closure { body, .. } = for_each_arg.kind;
if let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind;
let body = cx.tcx.hir().body(body);
if let ExprKind::Block(..) = body.value.kind;
then {

View file

@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_hir::intravisit::{walk_expr, walk_stmt, FnKind, Visitor};
use rustc_hir::{
Arm, Block, Body, Expr, ExprKind, Guard, HirId, ImplicitSelfKind, Let, Local, Pat, PatKind, Path, PathSegment,
Arm, Closure, Block, Body, Expr, ExprKind, Guard, HirId, ImplicitSelfKind, Let, Local, Pat, PatKind, Path, PathSegment,
QPath, Stmt, StmtKind, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
@ -298,7 +298,7 @@ impl<'tcx> Visitor<'tcx> for SideEffectVisit<'tcx> {
},
ExprKind::Match(expr, arms, _) => self.visit_match(expr, arms),
// since analysing the closure is not easy, just set all variables in it to side-effect
ExprKind::Closure { body, .. } => {
ExprKind::Closure(&Closure { body, .. }) => {
let body = self.tcx.hir().body(body);
self.visit_body(body);
let vars = std::mem::take(&mut self.ret_vars);

View file

@ -495,12 +495,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
if let FnRetTy::Return(ty) = sig.decl.output
&& let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty)
{
let out_region = cx.tcx.named_region(out.hir_id);
let args: Option<Vec<_>> = sig
.decl
.inputs
.iter()
.filter_map(get_rptr_lm)
.filter(|&(lt, _, _)| lt.name == out.name)
.filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
.map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span))
.collect();
if let Some(args) = args

Some files were not shown because too many files have changed in this diff Show more