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:
commit
f1a8854f9b
116 changed files with 1024 additions and 271 deletions
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
_,
|
||||
_,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(®ion_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#![feature(negative_impls)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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" })
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
8
src/test/ui/closures/binder/async-closure-with-binder.rs
Normal file
8
src/test/ui/closures/binder/async-closure-with-binder.rs
Normal 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
|
||||
}
|
16
src/test/ui/closures/binder/async-closure-with-binder.stderr
Normal file
16
src/test/ui/closures/binder/async-closure-with-binder.stderr
Normal 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
|
||||
|
6
src/test/ui/closures/binder/implicit-return.rs
Normal file
6
src/test/ui/closures/binder/implicit-return.rs
Normal 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
|
||||
}
|
10
src/test/ui/closures/binder/implicit-return.stderr
Normal file
10
src/test/ui/closures/binder/implicit-return.stderr
Normal 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
|
||||
|
27
src/test/ui/closures/binder/implicit-stuff.rs
Normal file
27
src/test/ui/closures/binder/implicit-stuff.rs
Normal 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
|
||||
}
|
107
src/test/ui/closures/binder/implicit-stuff.stderr
Normal file
107
src/test/ui/closures/binder/implicit-stuff.stderr
Normal 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`.
|
|
@ -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`
|
||||
}
|
|
@ -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`.
|
|
@ -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
|
||||
}
|
|
@ -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`.
|
|
@ -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) {}
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
21
src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Normal file
21
src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Normal 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() {}
|
|
@ -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`.
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue