Ban non-static lifetimes from AnonConst on AST.

The extra diagnostics come from the compiler no longer aborting before
typeck.
This commit is contained in:
Camille GILLOT 2022-03-31 20:10:37 +02:00
parent b711723d41
commit 865d0fef2f
3 changed files with 37 additions and 38 deletions

View File

@ -204,6 +204,11 @@ enum LifetimeRibKind {
/// lifetimes in const generics. See issue #74052 for discussion. /// lifetimes in const generics. See issue #74052 for discussion.
ConstGeneric, ConstGeneric,
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
AnonConst,
/// For **Modern** cases, create a new anonymous region parameter /// For **Modern** cases, create a new anonymous region parameter
/// and reference that. /// and reference that.
/// ///
@ -532,7 +537,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
} }
fn visit_anon_const(&mut self, constant: &'ast AnonConst) { fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
// We deal with repeat expressions explicitly in `resolve_expr`. // We deal with repeat expressions explicitly in `resolve_expr`.
self.resolve_anon_const(constant, IsRepeatExpr::No); self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
this.resolve_anon_const(constant, IsRepeatExpr::No);
})
} }
fn visit_expr(&mut self, expr: &'ast Expr) { fn visit_expr(&mut self, expr: &'ast Expr) {
self.resolve_expr(expr, None); self.resolve_expr(expr, None);
@ -1117,7 +1124,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.ribs[TypeNS].push(forward_ty_ban_rib); this.ribs[TypeNS].push(forward_ty_ban_rib);
this.ribs[ValueNS].push(forward_const_ban_rib); this.ribs[ValueNS].push(forward_const_ban_rib);
this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
this.visit_anon_const(expr) this.resolve_anon_const(expr, IsRepeatExpr::No)
}); });
forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
@ -1174,6 +1181,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error);
return; return;
} }
LifetimeRibKind::AnonConst => {
self.maybe_emit_forbidden_non_static_lifetime_error(lifetime);
self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error);
return;
}
_ => {} _ => {}
} }
} }
@ -3076,9 +3088,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
is_repeat, is_repeat,
constant.value.is_potential_trivial_const_param(), constant.value.is_potential_trivial_const_param(),
None, None,
|this| { |this| visit::walk_anon_const(this, constant),
visit::walk_anon_const(this, constant);
},
); );
} }
@ -3229,7 +3239,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} }
ExprKind::Repeat(ref elem, ref ct) => { ExprKind::Repeat(ref elem, ref ct) => {
self.visit_expr(elem); self.visit_expr(elem);
self.resolve_anon_const(ct, IsRepeatExpr::Yes); self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
this.resolve_anon_const(ct, IsRepeatExpr::Yes)
});
}
ExprKind::ConstBlock(ref ct) => {
self.resolve_anon_const(ct, IsRepeatExpr::No);
} }
ExprKind::Index(ref elem, ref idx) => { ExprKind::Index(ref elem, ref idx) => {
self.resolve_expr(elem, Some(expr)); self.resolve_expr(elem, Some(expr));

View File

@ -1901,6 +1901,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) )
.emit(); .emit();
} }
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
crate fn maybe_emit_forbidden_non_static_lifetime_error(&self, lifetime_ref: &ast::Lifetime) {
let feature_active = self.r.session.features_untracked().generic_const_exprs;
if !feature_active {
feature_err(
&self.r.session.parse_sess,
sym::generic_const_exprs,
lifetime_ref.ident.span,
"a non-static lifetime is not allowed in a `const`",
)
.emit();
}
}
} }
impl<'tcx> LifetimeContext<'_, 'tcx> { impl<'tcx> LifetimeContext<'_, 'tcx> {
@ -2398,32 +2414,4 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
_ => unreachable!(), _ => unreachable!(),
} }
} }
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
crate fn maybe_emit_forbidden_non_static_lifetime_error(
&self,
body_id: hir::BodyId,
lifetime_ref: &'tcx hir::Lifetime,
) {
let is_anon_const = matches!(
self.tcx.def_kind(self.tcx.hir().body_owner_def_id(body_id)),
hir::def::DefKind::AnonConst
);
let is_allowed_lifetime = matches!(
lifetime_ref.name,
hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
);
if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
feature_err(
&self.tcx.sess.parse_sess,
sym::generic_const_exprs,
lifetime_ref.span,
"a non-static lifetime is not allowed in a `const`",
)
.emit();
}
}
} }

View File

@ -2243,10 +2243,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let result = loop { let result = loop {
match *scope { match *scope {
Scope::Body { id, s } => { Scope::Body { id, s } => {
// Non-static lifetimes are prohibited in anonymous constants without
// `generic_const_exprs`.
self.maybe_emit_forbidden_non_static_lifetime_error(id, lifetime_ref);
outermost_body = Some(id); outermost_body = Some(id);
scope = s; scope = s;
} }