Skip to content

Commit 363d158

Browse files
authored
Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=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`
2 parents 985ea22 + 73b3ce2 commit 363d158

File tree

70 files changed

+846
-614
lines changed

Some content is hidden

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

70 files changed

+846
-614
lines changed

compiler/rustc_ast/src/ast.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ impl Path {
120120
pub fn is_global(&self) -> bool {
121121
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
122122
}
123+
124+
/// If this path is a single identifier with no arguments, does not ensure
125+
/// that the path resolves to a const param, the caller should check this.
126+
pub fn is_potential_trivial_const_arg(&self) -> bool {
127+
self.segments.len() == 1 && self.segments[0].args.is_none()
128+
}
123129
}
124130

125131
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
@@ -1154,7 +1160,9 @@ impl Expr {
11541160
///
11551161
/// If this is not the case, name resolution does not resolve `N` when using
11561162
/// `min_const_generics` as more complex expressions are not supported.
1157-
pub fn is_potential_trivial_const_param(&self) -> bool {
1163+
///
1164+
/// Does not ensure that the path resolves to a const param, the caller should check this.
1165+
pub fn is_potential_trivial_const_arg(&self) -> bool {
11581166
let this = if let ExprKind::Block(block, None) = &self.kind
11591167
&& block.stmts.len() == 1
11601168
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
@@ -1165,8 +1173,7 @@ impl Expr {
11651173
};
11661174

11671175
if let ExprKind::Path(None, path) = &this.kind
1168-
&& path.segments.len() == 1
1169-
&& path.segments[0].args.is_none()
1176+
&& path.is_potential_trivial_const_arg()
11701177
{
11711178
true
11721179
} else {

compiler/rustc_ast/src/visit.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ pub trait Visitor<'ast>: Sized {
188188
fn visit_variant(&mut self, v: &'ast Variant) {
189189
walk_variant(self, v)
190190
}
191+
fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
192+
self.visit_anon_const(discr);
193+
}
191194
fn visit_label(&mut self, label: &'ast Label) {
192195
walk_label(self, label)
193196
}
@@ -380,7 +383,7 @@ where
380383
visitor.visit_ident(variant.ident);
381384
visitor.visit_vis(&variant.vis);
382385
visitor.visit_variant_data(&variant.data);
383-
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
386+
walk_list!(visitor, visit_variant_discr, &variant.disr_expr);
384387
walk_list!(visitor, visit_attribute, &variant.attrs);
385388
}
386389

compiler/rustc_ast_lowering/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1190,13 +1190,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11901190
// parsing. We try to resolve that ambiguity by attempting resolution in both the
11911191
// type and value namespaces. If we resolved the path in the value namespace, we
11921192
// transform it into a generic const argument.
1193-
TyKind::Path(qself, path) => {
1193+
TyKind::Path(None, path) => {
11941194
if let Some(res) = self
11951195
.resolver
11961196
.get_partial_res(ty.id)
11971197
.and_then(|partial_res| partial_res.full_res())
11981198
{
1199-
if !res.matches_ns(Namespace::TypeNS) {
1199+
if !res.matches_ns(Namespace::TypeNS)
1200+
&& path.is_potential_trivial_const_arg()
1201+
{
12001202
debug!(
12011203
"lower_generic_arg: Lowering type argument as const argument: {:?}",
12021204
ty,
@@ -1218,7 +1220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12181220

12191221
let path_expr = Expr {
12201222
id: ty.id,
1221-
kind: ExprKind::Path(qself.clone(), path.clone()),
1223+
kind: ExprKind::Path(None, path.clone()),
12221224
span,
12231225
attrs: AttrVec::new(),
12241226
tokens: None,

compiler/rustc_error_codes/src/error_codes/E0771.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#### Note: this error code is no longer emitted by the compiler
2+
13
A non-`'static` lifetime was used in a const generic. This is currently not
24
allowed.
35

46
Erroneous code example:
57

6-
```compile_fail,E0771
8+
```compile_fail,E0770
79
#![feature(adt_const_params)]
810
911
fn function_with_str<'a, const STRING: &'a str>() {} // error!

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+17-14
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
5151
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
5252
None
5353
} else if tcx.lazy_normalization() {
54-
if let Some(param_id) = tcx.hir().opt_const_param_default_param_def_id(hir_id) {
54+
let parent_node = tcx.hir().get_parent(hir_id);
55+
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
56+
&& constant.hir_id == hir_id
57+
{
58+
// enum variant discriminants are not allowed to use any kind of generics
59+
None
60+
} else if let Some(param_id) =
61+
tcx.hir().opt_const_param_default_param_def_id(hir_id)
62+
{
5563
// If the def_id we are calling generics_of on is an anon ct default i.e:
5664
//
5765
// struct Foo<const N: usize = { .. }>;
@@ -94,15 +102,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
94102
has_self: generics.has_self,
95103
has_late_bound_regions: generics.has_late_bound_regions,
96104
};
105+
} else {
106+
// HACK(eddyb) this provides the correct generics when
107+
// `feature(generic_const_expressions)` is enabled, so that const expressions
108+
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
109+
//
110+
// Note that we do not supply the parent generics when using
111+
// `min_const_generics`.
112+
Some(parent_def_id.to_def_id())
97113
}
98-
99-
// HACK(eddyb) this provides the correct generics when
100-
// `feature(generic_const_expressions)` is enabled, so that const expressions
101-
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
102-
//
103-
// Note that we do not supply the parent generics when using
104-
// `min_const_generics`.
105-
Some(parent_def_id.to_def_id())
106114
} else {
107115
let parent_node = tcx.hir().get_parent(hir_id);
108116
match parent_node {
@@ -115,11 +123,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
115123
{
116124
Some(parent_def_id.to_def_id())
117125
}
118-
Node::Variant(Variant { disr_expr: Some(constant), .. })
119-
if constant.hir_id == hir_id =>
120-
{
121-
Some(parent_def_id.to_def_id())
122-
}
123126
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
124127
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
125128
}

compiler/rustc_resolve/messages.ftl

+27-2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ resolve_param_in_ty_of_const_param =
145145
the type of const parameters must not depend on other generic parameters
146146
.label = the type must not depend on the parameter `{$name}`
147147
148+
resolve_type_param_in_ty_of_const_param =
149+
type parameters may not be used in the type of const parameters
150+
151+
resolve_const_param_in_ty_of_const_param =
152+
const parameters may not be used in the type of const parameters
153+
154+
resolve_lifetime_param_in_ty_of_const_param =
155+
lifetime parameters may not be used in the type of const parameters
156+
148157
resolve_self_in_generic_param_default =
149158
generic parameters cannot use `Self` in their defaults
150159
.label = `Self` in generic parameter default
@@ -156,12 +165,15 @@ resolve_param_in_non_trivial_anon_const =
156165
resolve_param_in_non_trivial_anon_const_help =
157166
use `#![feature(generic_const_exprs)]` to allow generic const expressions
158167
159-
resolve_param_in_non_trivial_anon_const_sub_type =
168+
resolve_type_param_in_non_trivial_anon_const =
160169
type parameters may not be used in const expressions
161170
162-
resolve_param_in_non_trivial_anon_const_sub_non_type =
171+
resolve_const_param_in_non_trivial_anon_const =
163172
const parameters may only be used as standalone arguments, i.e. `{$name}`
164173
174+
resolve_lifetime_param_in_non_trivial_anon_const =
175+
lifetime parameters may not be used in const expressions
176+
165177
resolve_unreachable_label =
166178
use of unreachable label `{$name}`
167179
.label = unreachable label `{$name}`
@@ -233,3 +245,16 @@ resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern
233245
234246
resolve_accessible_unsure = not sure whether the path is accessible or not
235247
.note = the type may have associated items, but we are currently not checking them
248+
249+
resolve_param_in_enum_discriminant =
250+
generic parameters may not be used in enum discriminant values
251+
.label = cannot perform const operation using `{$name}`
252+
253+
resolve_type_param_in_enum_discriminant =
254+
type parameters may not be used in enum discriminant values
255+
256+
resolve_const_param_in_enum_discriminant =
257+
const parameters may not be used in enum discriminant values
258+
259+
resolve_lifetime_param_in_enum_discriminant =
260+
lifetime parameters may not be used in enum discriminant values

compiler/rustc_resolve/src/diagnostics.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -864,25 +864,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
864864
ResolutionError::ForwardDeclaredGenericParam => {
865865
self.tcx.sess.create_err(errs::ForwardDeclaredGenericParam { span })
866866
}
867-
ResolutionError::ParamInTyOfConstParam(name) => {
868-
self.tcx.sess.create_err(errs::ParamInTyOfConstParam { span, name })
869-
}
870-
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
867+
ResolutionError::ParamInTyOfConstParam { name, param_kind: is_type } => self
868+
.tcx
869+
.sess
870+
.create_err(errs::ParamInTyOfConstParam { span, name, param_kind: is_type }),
871+
ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => {
871872
self.tcx.sess.create_err(errs::ParamInNonTrivialAnonConst {
872873
span,
873874
name,
874-
sub_is_type: if is_type {
875-
errs::ParamInNonTrivialAnonConstIsType::AType
876-
} else {
877-
errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
878-
},
875+
param_kind: is_type,
879876
help: self
880877
.tcx
881878
.sess
882879
.is_nightly_build()
883880
.then_some(errs::ParamInNonTrivialAnonConstHelp),
884881
})
885882
}
883+
ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
884+
.tcx
885+
.sess
886+
.create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
886887
ResolutionError::SelfInGenericParamDefault => {
887888
self.tcx.sess.create_err(errs::SelfInGenericParamDefault { span })
888889
}

compiler/rustc_resolve/src/errors.rs

+41-6
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,18 @@ pub(crate) struct ParamInTyOfConstParam {
326326
#[label]
327327
pub(crate) span: Span,
328328
pub(crate) name: Symbol,
329+
#[subdiagnostic]
330+
pub(crate) param_kind: Option<ParamKindInTyOfConstParam>,
331+
}
332+
333+
#[derive(Subdiagnostic)]
334+
pub(crate) enum ParamKindInTyOfConstParam {
335+
#[note(resolve_type_param_in_ty_of_const_param)]
336+
Type,
337+
#[note(resolve_const_param_in_ty_of_const_param)]
338+
Const,
339+
#[note(resolve_lifetime_param_in_ty_of_const_param)]
340+
Lifetime,
329341
}
330342

331343
#[derive(Diagnostic)]
@@ -344,7 +356,7 @@ pub(crate) struct ParamInNonTrivialAnonConst {
344356
pub(crate) span: Span,
345357
pub(crate) name: Symbol,
346358
#[subdiagnostic]
347-
pub(crate) sub_is_type: ParamInNonTrivialAnonConstIsType,
359+
pub(crate) param_kind: ParamKindInNonTrivialAnonConst,
348360
#[subdiagnostic]
349361
pub(crate) help: Option<ParamInNonTrivialAnonConstHelp>,
350362
}
@@ -354,11 +366,13 @@ pub(crate) struct ParamInNonTrivialAnonConst {
354366
pub(crate) struct ParamInNonTrivialAnonConstHelp;
355367

356368
#[derive(Subdiagnostic)]
357-
pub(crate) enum ParamInNonTrivialAnonConstIsType {
358-
#[note(resolve_param_in_non_trivial_anon_const_sub_type)]
359-
AType,
360-
#[help(resolve_param_in_non_trivial_anon_const_sub_non_type)]
361-
NotAType { name: Symbol },
369+
pub(crate) enum ParamKindInNonTrivialAnonConst {
370+
#[note(resolve_type_param_in_non_trivial_anon_const)]
371+
Type,
372+
#[help(resolve_const_param_in_non_trivial_anon_const)]
373+
Const { name: Symbol },
374+
#[note(resolve_lifetime_param_in_non_trivial_anon_const)]
375+
Lifetime,
362376
}
363377

364378
#[derive(Diagnostic)]
@@ -539,3 +553,24 @@ pub(crate) struct CfgAccessibleUnsure {
539553
#[primary_span]
540554
pub(crate) span: Span,
541555
}
556+
557+
#[derive(Diagnostic)]
558+
#[diag(resolve_param_in_enum_discriminant)]
559+
pub(crate) struct ParamInEnumDiscriminant {
560+
#[primary_span]
561+
#[label]
562+
pub(crate) span: Span,
563+
pub(crate) name: Symbol,
564+
#[subdiagnostic]
565+
pub(crate) param_kind: ParamKindInEnumDiscriminant,
566+
}
567+
568+
#[derive(Subdiagnostic)]
569+
pub(crate) enum ParamKindInEnumDiscriminant {
570+
#[note(resolve_type_param_in_enum_discriminant)]
571+
Type,
572+
#[note(resolve_const_param_in_enum_discriminant)]
573+
Const,
574+
#[note(resolve_lifetime_param_in_enum_discriminant)]
575+
Lifetime,
576+
}

0 commit comments

Comments
 (0)