Skip to content

Commit

Permalink
Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=…
Browse files Browse the repository at this point in the history
…cjgillot

Various changes to name resolution of anon consts

Sorry this PR is kind of all over the place ^^'

Fixes #111012

- Rewrites anon const nameres to all go through `fn resolve_anon_const` explicitly instead of `visit_anon_const` to ensure that we do not accidentally resolve anon consts as if they are allowed to use generics when they aren't. Also means that we dont have bits of code for resolving anon consts that will get out of sync (i.e. legacy const generics and resolving path consts that were parsed as type arguments)
- Renames two of the `LifetimeRibKind`, `AnonConst -> ConcreteAnonConst` and `ConstGeneric -> ConstParamTy`
- Noticed while doing this that under `generic_const_exprs` all lifetimes currently get resolved to errors without any error being emitted which was causing a bunch of tests to pass without their bugs having been fixed, incidentally fixed that in this PR and marked those tests as `// known-bug:`. I'm fine to break those since `generic_const_exprs` is a very unstable incomplete feature and this PR _does_ make generic_const_exprs "less broken" as a whole, also I can't be assed to figure out what the underlying causes of all of them are. This PR reopens #77357 #83993
- Changed `generics_of` to stop providing generics and predicates to enum variant discriminant anon consts since those are not allowed to use generic parameters
- Updated the error for non 'static lifetime in const arguments and the error for non 'static lifetime in const param tys to use `derive(Diagnostic)`

I have a vague idea why const-arg-in-const-arg.rs, in-closure.rs and simple.rs have started failing which is unfortunate since these were deliberately made to work, I think lifetime resolution being broken just means this regressed at some point and nobody noticed because the tests were not testing anything :( I'm fine breaking these too for the same reason as the tests for #77357 #83993. I couldn't get `// known-bug` to work for these ICEs and just kept getting different stderr between CI and local `--bless` so I just removed them and will create an issue to track re-adding (and fixing) the bugs if this PR lands.

r? `@cjgillot` cc `@compiler-errors`
  • Loading branch information
matthiaskrgr authored May 9, 2023
2 parents 985ea22 + 73b3ce2 commit 363d158
Show file tree
Hide file tree
Showing 70 changed files with 846 additions and 614 deletions.
13 changes: 10 additions & 3 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ impl 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.
Expand Down Expand Up @@ -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
Expand All @@ -1165,8 +1173,7 @@ impl Expr {
};

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 {
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ pub trait Visitor<'ast>: Sized {
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)
}
Expand Down Expand Up @@ -380,7 +383,7 @@ where
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);
}

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1190,13 +1190,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// 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,
Expand All @@ -1218,7 +1220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

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,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0771.md
Original file line number Diff line number Diff line change
@@ -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!
Expand Down
31 changes: 17 additions & 14 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = { .. }>;
Expand Down Expand Up @@ -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 {
Expand All @@ -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()))
}
Expand Down
29 changes: 27 additions & 2 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ resolve_param_in_ty_of_const_param =
the type of const parameters must not depend on other generic parameters
.label = the type must not depend on the parameter `{$name}`
resolve_type_param_in_ty_of_const_param =
type parameters may not be used in the type of const parameters
resolve_const_param_in_ty_of_const_param =
const parameters may not be used in the type of const parameters
resolve_lifetime_param_in_ty_of_const_param =
lifetime parameters may not be used in the type of const parameters
resolve_self_in_generic_param_default =
generic parameters cannot use `Self` in their defaults
.label = `Self` in generic parameter default
Expand All @@ -156,12 +165,15 @@ resolve_param_in_non_trivial_anon_const =
resolve_param_in_non_trivial_anon_const_help =
use `#![feature(generic_const_exprs)]` to allow generic const expressions
resolve_param_in_non_trivial_anon_const_sub_type =
resolve_type_param_in_non_trivial_anon_const =
type parameters may not be used in const expressions
resolve_param_in_non_trivial_anon_const_sub_non_type =
resolve_const_param_in_non_trivial_anon_const =
const parameters may only be used as standalone arguments, i.e. `{$name}`
resolve_lifetime_param_in_non_trivial_anon_const =
lifetime parameters may not be used in const expressions
resolve_unreachable_label =
use of unreachable label `{$name}`
.label = unreachable label `{$name}`
Expand Down Expand Up @@ -233,3 +245,16 @@ resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern
resolve_accessible_unsure = not sure whether the path is accessible or not
.note = the type may have associated items, but we are currently not checking them
resolve_param_in_enum_discriminant =
generic parameters may not be used in enum discriminant values
.label = cannot perform const operation using `{$name}`
resolve_type_param_in_enum_discriminant =
type parameters may not be used in enum discriminant values
resolve_const_param_in_enum_discriminant =
const parameters may not be used in enum discriminant values
resolve_lifetime_param_in_enum_discriminant =
lifetime parameters may not be used in enum discriminant values
19 changes: 10 additions & 9 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,25 +864,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::ForwardDeclaredGenericParam => {
self.tcx.sess.create_err(errs::ForwardDeclaredGenericParam { span })
}
ResolutionError::ParamInTyOfConstParam(name) => {
self.tcx.sess.create_err(errs::ParamInTyOfConstParam { span, name })
}
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
ResolutionError::ParamInTyOfConstParam { name, param_kind: is_type } => self
.tcx
.sess
.create_err(errs::ParamInTyOfConstParam { span, name, param_kind: is_type }),
ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => {
self.tcx.sess.create_err(errs::ParamInNonTrivialAnonConst {
span,
name,
sub_is_type: if is_type {
errs::ParamInNonTrivialAnonConstIsType::AType
} else {
errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
},
param_kind: is_type,
help: self
.tcx
.sess
.is_nightly_build()
.then_some(errs::ParamInNonTrivialAnonConstHelp),
})
}
ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
.tcx
.sess
.create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
ResolutionError::SelfInGenericParamDefault => {
self.tcx.sess.create_err(errs::SelfInGenericParamDefault { span })
}
Expand Down
47 changes: 41 additions & 6 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,18 @@ pub(crate) struct ParamInTyOfConstParam {
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) param_kind: Option<ParamKindInTyOfConstParam>,
}

#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInTyOfConstParam {
#[note(resolve_type_param_in_ty_of_const_param)]
Type,
#[note(resolve_const_param_in_ty_of_const_param)]
Const,
#[note(resolve_lifetime_param_in_ty_of_const_param)]
Lifetime,
}

#[derive(Diagnostic)]
Expand All @@ -344,7 +356,7 @@ pub(crate) struct ParamInNonTrivialAnonConst {
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) sub_is_type: ParamInNonTrivialAnonConstIsType,
pub(crate) param_kind: ParamKindInNonTrivialAnonConst,
#[subdiagnostic]
pub(crate) help: Option<ParamInNonTrivialAnonConstHelp>,
}
Expand All @@ -354,11 +366,13 @@ pub(crate) struct ParamInNonTrivialAnonConst {
pub(crate) struct ParamInNonTrivialAnonConstHelp;

#[derive(Subdiagnostic)]
pub(crate) enum ParamInNonTrivialAnonConstIsType {
#[note(resolve_param_in_non_trivial_anon_const_sub_type)]
AType,
#[help(resolve_param_in_non_trivial_anon_const_sub_non_type)]
NotAType { name: Symbol },
pub(crate) enum ParamKindInNonTrivialAnonConst {
#[note(resolve_type_param_in_non_trivial_anon_const)]
Type,
#[help(resolve_const_param_in_non_trivial_anon_const)]
Const { name: Symbol },
#[note(resolve_lifetime_param_in_non_trivial_anon_const)]
Lifetime,
}

#[derive(Diagnostic)]
Expand Down Expand Up @@ -539,3 +553,24 @@ pub(crate) struct CfgAccessibleUnsure {
#[primary_span]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_param_in_enum_discriminant)]
pub(crate) struct ParamInEnumDiscriminant {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) param_kind: ParamKindInEnumDiscriminant,
}

#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInEnumDiscriminant {
#[note(resolve_type_param_in_enum_discriminant)]
Type,
#[note(resolve_const_param_in_enum_discriminant)]
Const,
#[note(resolve_lifetime_param_in_enum_discriminant)]
Lifetime,
}
Loading

0 comments on commit 363d158

Please sign in to comment.