misc nameres changes for anon consts
This commit is contained in:
parent
4a18324a4d
commit
442617c046
@ -120,6 +120,12 @@ pub fn from_ident(ident: Ident) -> Path {
|
||||
pub fn is_global(&self) -> bool {
|
||||
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
|
||||
}
|
||||
|
||||
/// If this path is a single identifier with no arguments, does not ensure
|
||||
/// that the path resolves to a const param, the caller should check this.
|
||||
pub fn is_potential_trivial_const_arg(&self) -> bool {
|
||||
self.segments.len() == 1 && self.segments[0].args.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
|
||||
@ -1154,7 +1160,9 @@ impl Expr {
|
||||
///
|
||||
/// If this is not the case, name resolution does not resolve `N` when using
|
||||
/// `min_const_generics` as more complex expressions are not supported.
|
||||
pub fn is_potential_trivial_const_param(&self) -> bool {
|
||||
///
|
||||
/// Does not ensure that the path resolves to a const param, the caller should check this.
|
||||
pub fn is_potential_trivial_const_arg(&self) -> bool {
|
||||
let this = if let ExprKind::Block(block, None) = &self.kind
|
||||
&& block.stmts.len() == 1
|
||||
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
|
||||
@ -1165,8 +1173,7 @@ pub fn is_potential_trivial_const_param(&self) -> bool {
|
||||
};
|
||||
|
||||
if let ExprKind::Path(None, path) = &this.kind
|
||||
&& path.segments.len() == 1
|
||||
&& path.segments[0].args.is_none()
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
|
@ -188,6 +188,9 @@ fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) {
|
||||
fn visit_variant(&mut self, v: &'ast Variant) {
|
||||
walk_variant(self, v)
|
||||
}
|
||||
fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
|
||||
self.visit_anon_const(discr);
|
||||
}
|
||||
fn visit_label(&mut self, label: &'ast Label) {
|
||||
walk_label(self, label)
|
||||
}
|
||||
@ -380,7 +383,7 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
|
||||
visitor.visit_ident(variant.ident);
|
||||
visitor.visit_vis(&variant.vis);
|
||||
visitor.visit_variant_data(&variant.data);
|
||||
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
|
||||
walk_list!(visitor, visit_variant_discr, &variant.disr_expr);
|
||||
walk_list!(visitor, visit_attribute, &variant.attrs);
|
||||
}
|
||||
|
||||
|
@ -1190,13 +1190,15 @@ fn lower_generic_arg(
|
||||
// parsing. We try to resolve that ambiguity by attempting resolution in both the
|
||||
// type and value namespaces. If we resolved the path in the value namespace, we
|
||||
// transform it into a generic const argument.
|
||||
TyKind::Path(qself, path) => {
|
||||
TyKind::Path(None, path) => {
|
||||
if let Some(res) = self
|
||||
.resolver
|
||||
.get_partial_res(ty.id)
|
||||
.and_then(|partial_res| partial_res.full_res())
|
||||
{
|
||||
if !res.matches_ns(Namespace::TypeNS) {
|
||||
if !res.matches_ns(Namespace::TypeNS)
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
{
|
||||
debug!(
|
||||
"lower_generic_arg: Lowering type argument as const argument: {:?}",
|
||||
ty,
|
||||
@ -1218,7 +1220,7 @@ fn lower_generic_arg(
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty.id,
|
||||
kind: ExprKind::Path(qself.clone(), path.clone()),
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
|
@ -1,9 +1,11 @@
|
||||
#### Note: this error code is no longer emitted by the compiler
|
||||
|
||||
A non-`'static` lifetime was used in a const generic. This is currently not
|
||||
allowed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0771
|
||||
```compile_fail,E0770
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
fn function_with_str<'a, const STRING: &'a str>() {} // error!
|
||||
|
@ -51,7 +51,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
|
||||
None
|
||||
} else if tcx.lazy_normalization() {
|
||||
if let Some(param_id) = tcx.hir().opt_const_param_default_param_def_id(hir_id) {
|
||||
let parent_node = tcx.hir().get_parent(hir_id);
|
||||
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
||||
&& constant.hir_id == hir_id
|
||||
{
|
||||
// enum variant discriminants are not allowed to use any kind of generics
|
||||
None
|
||||
} else if let Some(param_id) =
|
||||
tcx.hir().opt_const_param_default_param_def_id(hir_id)
|
||||
{
|
||||
// If the def_id we are calling generics_of on is an anon ct default i.e:
|
||||
//
|
||||
// struct Foo<const N: usize = { .. }>;
|
||||
@ -94,15 +102,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
has_self: generics.has_self,
|
||||
has_late_bound_regions: generics.has_late_bound_regions,
|
||||
};
|
||||
} else {
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
// `feature(generic_const_expressions)` is enabled, so that const expressions
|
||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||
//
|
||||
// Note that we do not supply the parent generics when using
|
||||
// `min_const_generics`.
|
||||
Some(parent_def_id.to_def_id())
|
||||
}
|
||||
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
// `feature(generic_const_expressions)` is enabled, so that const expressions
|
||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||
//
|
||||
// Note that we do not supply the parent generics when using
|
||||
// `min_const_generics`.
|
||||
Some(parent_def_id.to_def_id())
|
||||
} else {
|
||||
let parent_node = tcx.hir().get_parent(hir_id);
|
||||
match parent_node {
|
||||
@ -115,11 +123,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
{
|
||||
Some(parent_def_id.to_def_id())
|
||||
}
|
||||
Node::Variant(Variant { disr_expr: Some(constant), .. })
|
||||
if constant.hir_id == hir_id =>
|
||||
{
|
||||
Some(parent_def_id.to_def_id())
|
||||
}
|
||||
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
|
||||
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
|
||||
}
|
||||
|
@ -1188,11 +1188,7 @@ fn validate_res_from_ribs(
|
||||
}
|
||||
|
||||
RibKind::ConstantItem(trivial, _) => {
|
||||
let features = self.tcx.sess.features_untracked();
|
||||
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
|
||||
if !(trivial == ConstantHasGenerics::Yes
|
||||
|| features.generic_const_exprs)
|
||||
{
|
||||
if let ConstantHasGenerics::No(cause) = trivial {
|
||||
// HACK(min_const_generics): If we encounter `Self` in an anonymous
|
||||
// constant we can't easily tell if it's generic at this stage, so
|
||||
// we instead remember this and then enforce the self type to be
|
||||
@ -1264,11 +1260,7 @@ fn validate_res_from_ribs(
|
||||
| RibKind::ForwardGenericParamBan => continue,
|
||||
|
||||
RibKind::ConstantItem(trivial, _) => {
|
||||
let features = self.tcx.sess.features_untracked();
|
||||
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
|
||||
if !(trivial == ConstantHasGenerics::Yes
|
||||
|| features.generic_const_exprs)
|
||||
{
|
||||
if let ConstantHasGenerics::No(cause) = trivial {
|
||||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
span,
|
||||
|
@ -66,6 +66,15 @@ enum IsRepeatExpr {
|
||||
Yes,
|
||||
}
|
||||
|
||||
/// Describes whether an `AnonConst` is a type level const arg or
|
||||
/// some other form of anon const (i.e. inline consts or enum discriminants)
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum AnonConstKind {
|
||||
EnumDiscriminant,
|
||||
InlineConst,
|
||||
ConstArg(IsRepeatExpr),
|
||||
}
|
||||
|
||||
impl PatternSource {
|
||||
fn descr(self) -> &'static str {
|
||||
match self {
|
||||
@ -105,7 +114,7 @@ pub(crate) enum HasGenericParams {
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum ConstantHasGenerics {
|
||||
Yes,
|
||||
No,
|
||||
No(NoConstantGenericsReason),
|
||||
}
|
||||
|
||||
impl ConstantHasGenerics {
|
||||
@ -114,6 +123,27 @@ fn force_yes_if(self, b: bool) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reason for why an anon const is not allowed to reference generic parameters
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum NoConstantGenericsReason {
|
||||
/// Const arguments are only allowed to use generic parameters when:
|
||||
/// - `feature(generic_const_exprs)` is enabled
|
||||
/// or
|
||||
/// - the const argument is a sole const generic paramater, i.e. `foo::<{ N }>()`
|
||||
///
|
||||
/// If neither of the above are true then this is used as the cause.
|
||||
NonTrivialConstArg,
|
||||
/// Enum discriminants are not allowed to reference generic parameters ever, this
|
||||
/// is used when an anon const is in the following position:
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// enum Foo<const N: isize> {
|
||||
/// Variant = { N }, // this anon const is not allowed to use generics
|
||||
/// }
|
||||
/// ```
|
||||
IsEnumDiscriminant,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum ConstantItemKind {
|
||||
Const,
|
||||
@ -273,15 +303,18 @@ enum LifetimeRibKind {
|
||||
/// Signal we cannot find which should be the anonymous lifetime.
|
||||
ElisionFailure,
|
||||
|
||||
/// 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,
|
||||
/// This rib forbids usage of generic parameters inside of const parameter types.
|
||||
///
|
||||
/// While this is desirable to support eventually, it is difficult to do and so is
|
||||
/// currently forbidden. See rust-lang/project-const-generics#28 for more info.
|
||||
ConstParamTy,
|
||||
|
||||
/// 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,
|
||||
/// Usage of generic parameters is forbidden in various positions for anon consts:
|
||||
/// - const arguments when `generic_const_exprs` is not enabled
|
||||
/// - enum discriminant values
|
||||
///
|
||||
/// This rib emits an error when a lifetime would resolve to a lifetime parameter.
|
||||
ConcreteAnonConst(NoConstantGenericsReason),
|
||||
|
||||
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
|
||||
Item,
|
||||
@ -648,13 +681,8 @@ fn visit_block(&mut self, block: &'ast Block) {
|
||||
self.resolve_block(block);
|
||||
self.parent_scope.macro_rules = old_macro_rules;
|
||||
}
|
||||
fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
|
||||
// We deal with repeat expressions explicitly in `resolve_expr`.
|
||||
self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||
this.resolve_anon_const(constant, IsRepeatExpr::No);
|
||||
})
|
||||
})
|
||||
fn visit_anon_const(&mut self, _constant: &'ast AnonConst) {
|
||||
bug!("encountered anon const without a manual call to `resolve_anon_const`");
|
||||
}
|
||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||
self.resolve_expr(expr, None);
|
||||
@ -676,7 +704,7 @@ fn visit_local(&mut self, local: &'ast Local) {
|
||||
fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
let prev = self.diagnostic_metadata.current_trait_object;
|
||||
let prev_ty = self.diagnostic_metadata.current_type_path;
|
||||
match ty.kind {
|
||||
match &ty.kind {
|
||||
TyKind::Ref(None, _) => {
|
||||
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
|
||||
// NodeId `ty.id`.
|
||||
@ -685,7 +713,7 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
self.resolve_elided_lifetime(ty.id, span);
|
||||
visit::walk_ty(self, ty);
|
||||
}
|
||||
TyKind::Path(ref qself, ref path) => {
|
||||
TyKind::Path(qself, path) => {
|
||||
self.diagnostic_metadata.current_type_path = Some(ty);
|
||||
self.smart_resolve_path(ty.id, &qself, path, PathSource::Type);
|
||||
|
||||
@ -730,11 +758,11 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
visit::walk_ty(self, ty);
|
||||
self.lifetime_elision_candidates = candidates;
|
||||
}
|
||||
TyKind::TraitObject(ref bounds, ..) => {
|
||||
TyKind::TraitObject(bounds, ..) => {
|
||||
self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
|
||||
visit::walk_ty(self, ty)
|
||||
}
|
||||
TyKind::BareFn(ref bare_fn) => {
|
||||
TyKind::BareFn(bare_fn) => {
|
||||
let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo());
|
||||
self.with_generic_param_rib(
|
||||
&bare_fn.generic_params,
|
||||
@ -769,6 +797,13 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
},
|
||||
)
|
||||
}
|
||||
TyKind::Array(element_ty, length) => {
|
||||
self.visit_ty(element_ty);
|
||||
self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
|
||||
}
|
||||
TyKind::Typeof(ct) => {
|
||||
self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
|
||||
}
|
||||
_ => visit::walk_ty(self, ty),
|
||||
}
|
||||
self.diagnostic_metadata.current_trait_object = prev;
|
||||
@ -994,36 +1029,25 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
|
||||
// namespace first, and if that fails we try again in the value namespace. If
|
||||
// resolution in the value namespace succeeds, we have an generic const argument on
|
||||
// our hands.
|
||||
if let TyKind::Path(ref qself, ref path) = ty.kind {
|
||||
if let TyKind::Path(None, ref path) = ty.kind {
|
||||
// We cannot disambiguate multi-segment paths right now as that requires type
|
||||
// checking.
|
||||
if path.segments.len() == 1 && path.segments[0].args.is_none() {
|
||||
if path.is_potential_trivial_const_arg() {
|
||||
let mut check_ns = |ns| {
|
||||
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
|
||||
.is_some()
|
||||
};
|
||||
if !check_ns(TypeNS) && check_ns(ValueNS) {
|
||||
// This must be equivalent to `visit_anon_const`, but we cannot call it
|
||||
// directly due to visitor lifetimes so we have to copy-paste some code.
|
||||
//
|
||||
// Note that we might not be inside of an repeat expression here,
|
||||
// but considering that `IsRepeatExpr` is only relevant for
|
||||
// non-trivial constants this is doesn't matter.
|
||||
self.with_constant_rib(
|
||||
IsRepeatExpr::No,
|
||||
ConstantHasGenerics::Yes,
|
||||
None,
|
||||
self.resolve_anon_const_manual(
|
||||
true,
|
||||
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
||||
|this| {
|
||||
this.smart_resolve_path(
|
||||
ty.id,
|
||||
qself,
|
||||
&None,
|
||||
path,
|
||||
PathSource::Expr(None),
|
||||
);
|
||||
|
||||
if let Some(ref qself) = *qself {
|
||||
this.visit_ty(&qself.ty);
|
||||
}
|
||||
this.visit_path(path, ty.id);
|
||||
},
|
||||
);
|
||||
@ -1037,7 +1061,9 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg),
|
||||
GenericArg::Const(ct) => self.visit_anon_const(ct),
|
||||
GenericArg::Const(ct) => {
|
||||
self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
|
||||
}
|
||||
}
|
||||
self.diagnostic_metadata.currently_processing_generics = prev;
|
||||
}
|
||||
@ -1053,7 +1079,9 @@ fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) {
|
||||
match constraint.kind {
|
||||
AssocConstraintKind::Equality { ref term } => match term {
|
||||
Term::Ty(ty) => self.visit_ty(ty),
|
||||
Term::Const(c) => self.visit_anon_const(c),
|
||||
Term::Const(c) => {
|
||||
self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
|
||||
}
|
||||
},
|
||||
AssocConstraintKind::Bound { ref bounds } => {
|
||||
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
|
||||
@ -1102,8 +1130,8 @@ fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::Elided(_)
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::AnonConst
|
||||
| LifetimeRibKind::ConstGeneric => {}
|
||||
| LifetimeRibKind::ConcreteAnonConst(_)
|
||||
| LifetimeRibKind::ConstParamTy => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1164,7 +1192,7 @@ fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
|
||||
InlineAsmOperand::Const { anon_const, .. } => {
|
||||
// Although this is `DefKind::AnonConst`, it is allowed to reference outer
|
||||
// generic parameters like an inline const.
|
||||
self.resolve_inline_const(anon_const);
|
||||
self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
|
||||
}
|
||||
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
|
||||
}
|
||||
@ -1188,6 +1216,10 @@ fn visit_variant(&mut self, v: &'ast Variant) {
|
||||
visit::walk_variant(self, v)
|
||||
}
|
||||
|
||||
fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
|
||||
self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, f: &'ast FieldDef) {
|
||||
self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
|
||||
visit::walk_field_def(self, f)
|
||||
@ -1386,7 +1418,7 @@ fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper:
|
||||
|
||||
this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
|
||||
this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
|
||||
this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
|
||||
this.visit_ty(ty)
|
||||
});
|
||||
this.ribs[TypeNS].pop().unwrap();
|
||||
@ -1395,9 +1427,10 @@ fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper:
|
||||
if let Some(ref expr) = default {
|
||||
this.ribs[TypeNS].push(forward_ty_ban_rib);
|
||||
this.ribs[ValueNS].push(forward_const_ban_rib);
|
||||
this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
|
||||
this.resolve_anon_const(expr, IsRepeatExpr::No)
|
||||
});
|
||||
this.resolve_anon_const(
|
||||
expr,
|
||||
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
||||
);
|
||||
forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
|
||||
forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
|
||||
}
|
||||
@ -1475,8 +1508,8 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
LifetimeUseSet::Many
|
||||
}),
|
||||
LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ConstGeneric => None,
|
||||
LifetimeRibKind::AnonConst => {
|
||||
| LifetimeRibKind::ConstParamTy => None,
|
||||
LifetimeRibKind::ConcreteAnonConst(_) => {
|
||||
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
})
|
||||
@ -1495,7 +1528,7 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
|
||||
match rib.kind {
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::ConstGeneric => {
|
||||
LifetimeRibKind::ConstParamTy => {
|
||||
self.emit_non_static_lt_in_const_generic_error(lifetime);
|
||||
self.record_lifetime_res(
|
||||
lifetime.id,
|
||||
@ -1504,7 +1537,7 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
);
|
||||
return;
|
||||
}
|
||||
LifetimeRibKind::AnonConst => {
|
||||
LifetimeRibKind::ConcreteAnonConst(cause) => {
|
||||
self.maybe_emit_forbidden_non_static_lifetime_error(lifetime);
|
||||
self.record_lifetime_res(
|
||||
lifetime.id,
|
||||
@ -1604,9 +1637,9 @@ fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
|
||||
return;
|
||||
}
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||
LifetimeRibKind::AnonConst => {
|
||||
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
|
||||
LifetimeRibKind::ConcreteAnonConst(_) => {
|
||||
// There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
|
||||
span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
}
|
||||
@ -1826,9 +1859,9 @@ fn resolve_elided_lifetimes_in_path(
|
||||
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
|
||||
break;
|
||||
}
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||
LifetimeRibKind::AnonConst => {
|
||||
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
|
||||
LifetimeRibKind::ConcreteAnonConst(_) => {
|
||||
// There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
|
||||
span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
}
|
||||
@ -2560,7 +2593,7 @@ fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||
}
|
||||
|
||||
// HACK(min_const_generics,const_evaluatable_unchecked): We
|
||||
// HACK(min_const_generics, generic_const_exprs): We
|
||||
// want to keep allowing `[0; std::mem::size_of::<*mut T>()]`
|
||||
// with a future compat lint for now. We do this by adding an
|
||||
// additional special case for repeat expressions.
|
||||
@ -2576,18 +2609,26 @@ fn with_constant_rib(
|
||||
item: Option<(Ident, ConstantItemKind)>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
self.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
|
||||
this.with_rib(
|
||||
TypeNS,
|
||||
RibKind::ConstantItem(
|
||||
may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
|
||||
item,
|
||||
),
|
||||
|this| {
|
||||
this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
|
||||
},
|
||||
)
|
||||
});
|
||||
let f = |this: &mut Self| {
|
||||
this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
|
||||
this.with_rib(
|
||||
TypeNS,
|
||||
RibKind::ConstantItem(
|
||||
may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
|
||||
item,
|
||||
),
|
||||
|this| {
|
||||
this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
|
||||
},
|
||||
)
|
||||
})
|
||||
};
|
||||
|
||||
if let ConstantHasGenerics::No(cause) = may_use_generics {
|
||||
self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f)
|
||||
} else {
|
||||
f(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||
@ -3924,24 +3965,54 @@ fn resolve_block(&mut self, block: &'ast Block) {
|
||||
debug!("(resolving block) leaving block");
|
||||
}
|
||||
|
||||
fn resolve_anon_const(&mut self, constant: &'ast AnonConst, is_repeat: IsRepeatExpr) {
|
||||
debug!("resolve_anon_const {:?} is_repeat: {:?}", constant, is_repeat);
|
||||
self.with_constant_rib(
|
||||
is_repeat,
|
||||
if constant.value.is_potential_trivial_const_param() {
|
||||
ConstantHasGenerics::Yes
|
||||
} else {
|
||||
ConstantHasGenerics::No
|
||||
},
|
||||
None,
|
||||
|this| visit::walk_anon_const(this, constant),
|
||||
fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) {
|
||||
debug!(
|
||||
"resolve_anon_const(constant: {:?}, anon_const_kind: {:?})",
|
||||
constant, anon_const_kind
|
||||
);
|
||||
|
||||
self.resolve_anon_const_manual(
|
||||
constant.value.is_potential_trivial_const_arg(),
|
||||
anon_const_kind,
|
||||
|this| this.resolve_expr(&constant.value, None),
|
||||
)
|
||||
}
|
||||
|
||||
fn resolve_inline_const(&mut self, constant: &'ast AnonConst) {
|
||||
debug!("resolve_anon_const {constant:?}");
|
||||
self.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, None, |this| {
|
||||
visit::walk_anon_const(this, constant)
|
||||
/// There are a few places that we need to resolve an anon const but we did not parse an
|
||||
/// anon const so cannot provide an `&'ast AnonConst`. Right now this is just unbraced
|
||||
/// const arguments that were parsed as type arguments, and `legact_const_generics` which
|
||||
/// parse as normal function argument expressions. To avoid duplicating the code for resolving
|
||||
/// an anon const we have this function which lets the caller manually call `resolve_expr` or
|
||||
/// `smart_resolve_path`.
|
||||
fn resolve_anon_const_manual(
|
||||
&mut self,
|
||||
is_trivial_const_arg: bool,
|
||||
anon_const_kind: AnonConstKind,
|
||||
resolve_expr: impl FnOnce(&mut Self),
|
||||
) {
|
||||
let is_repeat_expr = match anon_const_kind {
|
||||
AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr,
|
||||
_ => IsRepeatExpr::No,
|
||||
};
|
||||
|
||||
let may_use_generics = match anon_const_kind {
|
||||
AnonConstKind::EnumDiscriminant => {
|
||||
ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
|
||||
}
|
||||
AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
|
||||
AnonConstKind::ConstArg(_) => {
|
||||
if self.r.tcx.features().generic_const_exprs || is_trivial_const_arg {
|
||||
ConstantHasGenerics::Yes
|
||||
} else {
|
||||
ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||
resolve_expr(this);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -4046,17 +4117,10 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
|
||||
// Constant arguments need to be treated as AnonConst since
|
||||
// that is how they will be later lowered to HIR.
|
||||
if const_args.contains(&idx) {
|
||||
self.with_constant_rib(
|
||||
IsRepeatExpr::No,
|
||||
if argument.is_potential_trivial_const_param() {
|
||||
ConstantHasGenerics::Yes
|
||||
} else {
|
||||
ConstantHasGenerics::No
|
||||
},
|
||||
None,
|
||||
|this| {
|
||||
this.resolve_expr(argument, None);
|
||||
},
|
||||
self.resolve_anon_const_manual(
|
||||
argument.is_potential_trivial_const_arg(),
|
||||
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
||||
|this| this.resolve_expr(argument, None),
|
||||
);
|
||||
} else {
|
||||
self.resolve_expr(argument, None);
|
||||
@ -4115,14 +4179,10 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
|
||||
}
|
||||
ExprKind::Repeat(ref elem, ref ct) => {
|
||||
self.visit_expr(elem);
|
||||
self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||
this.resolve_anon_const(ct, IsRepeatExpr::Yes)
|
||||
})
|
||||
});
|
||||
self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
|
||||
}
|
||||
ExprKind::ConstBlock(ref ct) => {
|
||||
self.resolve_inline_const(ct);
|
||||
self.resolve_anon_const(ct, AnonConstKind::InlineConst);
|
||||
}
|
||||
ExprKind::Index(ref elem, ref idx) => {
|
||||
self.resolve_expr(elem, Some(expr));
|
||||
|
Loading…
Reference in New Issue
Block a user