Skip to content

Commit 089e8c0

Browse files
authoredFeb 16, 2023
Rollup merge of #107489 - compiler-errors:non_lifetime_binders, r=cjgillot
Implement partial support for non-lifetime binders This implements support for non-lifetime binders. It's pretty useless currently, but I wanted to put this up so the implementation can be discussed. Specifically, this piggybacks off of the late-bound lifetime collection code in `rustc_hir_typeck::collect::lifetimes`. This seems like a necessary step given the fact we don't resolve late-bound regions until this point, and binders are sometimes merged. Q: I'm not sure if I should go along this route, or try to modify the earlier nameres code to compute the right bound var indices for type and const binders eagerly... If so, I'll need to rename all these queries to something more appropriate (I've done this for `resolve_lifetime::Region` -> `resolve_lifetime::ResolvedArg`) cc rust-lang/types-team#81 r? `@ghost`
·
1.88.01.69.0
2 parents 6379c72 + 95f35fe commit 089e8c0

File tree

48 files changed

+709
-343
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+709
-343
lines changed
 

‎compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> {
294294
}
295295
}
296296

297-
fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
298-
// Check only lifetime parameters are present and that the lifetime
299-
// parameters that are present have no bounds.
300-
let non_lt_param_spans: Vec<_> = params
301-
.iter()
302-
.filter_map(|param| match param.kind {
303-
GenericParamKind::Lifetime { .. } => {
304-
if !param.bounds.is_empty() {
305-
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
306-
self.session.emit_err(ForbiddenLifetimeBound { spans });
307-
}
308-
None
309-
}
310-
_ => Some(param.ident.span),
311-
})
312-
.collect();
313-
if !non_lt_param_spans.is_empty() {
314-
self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
315-
}
316-
}
317-
318297
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
319298
self.check_decl_num_args(fn_decl);
320299
self.check_decl_cvaradic_pos(fn_decl);
@@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
745724
)
746725
.emit();
747726
});
748-
self.check_late_bound_lifetime_defs(&bfty.generic_params);
749727
if let Extern::Implicit(_) = bfty.ext {
750728
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
751729
self.maybe_lint_missing_abi(sig_span, ty.id);
@@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13181296
for predicate in &generics.where_clause.predicates {
13191297
match predicate {
13201298
WherePredicate::BoundPredicate(bound_pred) => {
1321-
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
1322-
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
1323-
13241299
// This is slightly complicated. Our representation for poly-trait-refs contains a single
13251300
// binder and thus we only allow a single level of quantification. However,
13261301
// the syntax of Rust permits quantification in two places in where clauses,
@@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13961371
visit::walk_param_bound(self, bound)
13971372
}
13981373

1399-
fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
1400-
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
1401-
visit::walk_poly_trait_ref(self, t);
1402-
}
1403-
14041374
fn visit_variant_data(&mut self, s: &'a VariantData) {
14051375
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
14061376
}
@@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14371407
.emit();
14381408
}
14391409

1440-
if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
1441-
self.check_late_bound_lifetime_defs(generic_params);
1442-
}
1443-
14441410
if let FnKind::Fn(
14451411
_,
14461412
_,

‎compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
1111
use rustc_span::Span;
1212
use rustc_target::spec::abi;
1313

14+
use crate::errors::ForbiddenLifetimeBound;
15+
1416
macro_rules! gate_feature_fn {
1517
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
1618
let (visitor, has_feature, span, name, explain, help) =
@@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
136138
}
137139
ImplTraitVisitor { vis: self }.visit_ty(ty);
138140
}
141+
142+
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
143+
// Check only lifetime parameters are present and that the lifetime
144+
// parameters that are present have no bounds.
145+
let non_lt_param_spans: Vec<_> = params
146+
.iter()
147+
.filter_map(|param| match param.kind {
148+
ast::GenericParamKind::Lifetime { .. } => None,
149+
_ => Some(param.ident.span),
150+
})
151+
.collect();
152+
// FIXME: gate_feature_post doesn't really handle multispans...
153+
if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
154+
feature_err(
155+
&self.sess.parse_sess,
156+
sym::non_lifetime_binders,
157+
non_lt_param_spans,
158+
rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param,
159+
)
160+
.emit();
161+
}
162+
for param in params {
163+
if !param.bounds.is_empty() {
164+
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
165+
self.sess.emit_err(ForbiddenLifetimeBound { spans });
166+
}
167+
}
168+
}
139169
}
140170

141171
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
147177
..
148178
}) = attr_info
149179
{
150-
gate_feature_fn!(self, has_feature, attr.span, *name, descr);
180+
gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
151181
}
152182
// Check unstable flavors of the `#[doc]` attribute.
153183
if attr.has_name(sym::doc) {
@@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
306336
ast::TyKind::BareFn(bare_fn_ty) => {
307337
// Function pointers cannot be `const`
308338
self.check_extern(bare_fn_ty.ext, ast::Const::No);
339+
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
309340
}
310341
ast::TyKind::Never => {
311342
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
318349
visit::walk_ty(self, ty)
319350
}
320351

352+
fn visit_generics(&mut self, g: &'a ast::Generics) {
353+
for predicate in &g.where_clause.predicates {
354+
match predicate {
355+
ast::WherePredicate::BoundPredicate(bound_pred) => {
356+
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
357+
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
358+
}
359+
_ => {}
360+
}
361+
}
362+
visit::walk_generics(self, g);
363+
}
364+
321365
fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
322366
if let ast::FnRetTy::Ty(output_ty) = ret_ty {
323367
if let ast::TyKind::Never = output_ty.kind {
@@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
437481
visit::walk_pat(self, pattern)
438482
}
439483

484+
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
485+
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
486+
visit::walk_poly_trait_ref(self, t);
487+
}
488+
440489
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
441490
if let Some(header) = fn_kind.header() {
442491
// Stability of const fn methods are covered in `visit_assoc_item` below.
443492
self.check_extern(header.ext, header.constness);
444493
}
445494

495+
if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
496+
self.check_late_bound_lifetime_defs(generic_params);
497+
}
498+
446499
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
447500
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
448501
}

0 commit comments

Comments
 (0)
Please sign in to comment.