diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-07-12 13:34:24 +0400 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-07-12 21:00:03 +0400 |
| commit | c2dbd62c7c60cd4017c9d499101e40c129e4bc61 (patch) | |
| tree | 2b995dbbc34a3a74ea4ff4b8a6dcbd3b66198afa /compiler/rustc_resolve/src | |
| parent | f89ef3cf66206b7c0ba0ca134de40b567c7bda83 (diff) | |
| download | rust-c2dbd62c7c60cd4017c9d499101e40c129e4bc61.tar.gz rust-c2dbd62c7c60cd4017c9d499101e40c129e4bc61.zip | |
Lower closure binders to hir & properly check them
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 49 |
2 files changed, 90 insertions, 8 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index caf6f8c8392..80186650fe8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -844,19 +844,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( - LifetimeRibKind::AnonymousCreateParameter { - binder: fn_id, - report_in_path: false, + 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), ); @@ -891,6 +902,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); @@ -3515,6 +3538,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::Function, + 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)); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 557dbecfabe..547255498a0 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -571,7 +571,51 @@ 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 { 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 +628,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { (pair, r) }) .unzip(); + + // FIXME: missing_named_lifetime_spots + self.map.late_bound_vars.insert(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, |
