diff options
| author | bors <bors@rust-lang.org> | 2022-04-30 07:52:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-04-30 07:52:18 +0000 |
| commit | 76d4862fdd131b6f79dc0a31857f888d26bcdb27 (patch) | |
| tree | fa699104ad1098a95d9e25d704d517ddeb465a76 /compiler | |
| parent | 9a98c63b30bd8419be662b8fb3f3b22ba33d72c5 (diff) | |
| parent | 7d990a8c1838a18c54a4b8a9f5fe74ea507ecbb3 (diff) | |
Auto merge of #95776 - cjgillot:ast-lifetimes-static, r=petrochenkov
Enforce static lifetimes in consts during late resolution This PR moves the handling of implicitly and explicitly static lifetimes in constants from HIR to the AST.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 77 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 15 |
3 files changed, 70 insertions, 70 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index aafef3e3137..53bd589fdcd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -199,6 +199,16 @@ enum LifetimeRibKind { /// This rib declares generic parameters. Generics { parent: NodeId, span: Span, kind: LifetimeBinderKind }, + /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const + /// generics. We are disallowing this until we can decide on how we want to handle non-'static + /// lifetimes in const generics. See issue #74052 for discussion. + 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 /// and reference that. /// @@ -527,7 +537,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_anon_const(&mut self, constant: &'ast AnonConst) { // 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) { self.resolve_expr(expr, None); @@ -1102,14 +1114,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); - this.visit_ty(ty); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.visit_ty(ty) + }); this.ribs[TypeNS].pop().unwrap(); this.ribs[ValueNS].pop().unwrap(); if let Some(ref expr) = default { this.ribs[TypeNS].push(forward_ty_ban_rib); this.ribs[ValueNS].push(forward_const_ban_rib); - this.visit_anon_const(expr); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.resolve_anon_const(expr, IsRepeatExpr::No) + }); forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); } @@ -1158,8 +1174,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { return; } - if let LifetimeRibKind::Item = rib.kind { - break; + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::ConstGeneric => { + self.emit_non_static_lt_in_const_generic_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } + LifetimeRibKind::AnonConst => { + self.maybe_emit_forbidden_non_static_lifetime_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } + _ => {} } } @@ -3065,9 +3092,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { is_repeat, constant.value.is_potential_trivial_const_param(), None, - |this| { - visit::walk_anon_const(this, constant); - }, + |this| visit::walk_anon_const(this, constant), ); } @@ -3218,7 +3243,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } ExprKind::Repeat(ref elem, ref ct) => { 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) => { self.resolve_expr(elem, Some(expr)); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a9edb713b0d..894ff0f17f8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1886,6 +1886,37 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.emit(); } + + crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) { + struct_span_err!( + self.r.session, + lifetime_ref.ident.span, + E0771, + "use of non-static lifetime `{}` in const generic", + lifetime_ref.ident + ) + .note( + "for more information, see issue #74052 \ + <https://github.com/rust-lang/rust/issues/74052>", + ) + .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> { @@ -1982,24 +2013,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { } } - // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const - // generics. We are disallowing this until we can decide on how we want to handle non-'static - // lifetimes in const generics. See issue #74052 for discussion. - crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) { - let mut err = struct_span_err!( - self.tcx.sess, - lifetime_ref.span, - E0771, - "use of non-static lifetime `{}` in const generic", - lifetime_ref - ); - err.note( - "for more information, see issue #74052 \ - <https://github.com/rust-lang/rust/issues/74052>", - ); - err.emit(); - } - crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { if [ @@ -2401,32 +2414,4 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { _ => 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(); - } - } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ce3069265d0..35a40a0a321 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -164,8 +164,6 @@ crate struct LifetimeContext<'a, 'tcx> { map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - is_in_const_generic: bool, - /// Indicates that we only care about the definition of a trait. This should /// be false if the `Item` we are resolving lifetimes for is not a trait or /// we eventually need lifetimes resolve for trait items. @@ -452,7 +450,6 @@ fn do_resolve( tcx, map: &mut named_region_map, scope: ROOT_SCOPE, - is_in_const_generic: false, trait_definition_only, labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), @@ -1266,10 +1263,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, Region::Static); return; } - if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error { - self.emit_non_static_lt_in_const_generic_error(lifetime_ref); - return; - } self.resolve_lifetime_ref(lifetime_ref); } @@ -1341,14 +1334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } GenericParamKind::Const { ref ty, default } => { - let was_in_const_generic = this.is_in_const_generic; - this.is_in_const_generic = true; walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); if let Some(default) = default { this.visit_body(this.tcx.hir().body(default.body)); } - this.is_in_const_generic = was_in_const_generic; } } } @@ -1798,7 +1788,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { tcx: *tcx, map, scope: &wrap_scope, - is_in_const_generic: self.is_in_const_generic, trait_definition_only: self.trait_definition_only, labels_in_fn, xcrate_object_lifetime_defaults, @@ -2254,10 +2243,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let result = loop { match *scope { 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); scope = s; } |
