Skip to content

Explicitly deny elided lifetimes in associated consts #114716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 38 additions & 35 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2727,19 +2727,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
kind: LifetimeBinderKind::ConstItem,
},
|this| {
this.visit_generics(generics);
this.visit_ty(ty);

// Only impose the restrictions of `ConstRibKind` for an
// actual constant expression in a provided default.
if let Some(expr) = expr {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
this.resolve_const_body(expr, None);
}
this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
this.visit_generics(generics);
this.visit_ty(ty);

// Only impose the restrictions of `ConstRibKind` for an
// actual constant expression in a provided default.
if let Some(expr) = expr {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
this.resolve_const_body(expr, None);
}
});
},
);
}
Expand Down Expand Up @@ -2898,7 +2900,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
match &item.kind {
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
debug!("resolve_implementation AssocItemKind::Const");

self.with_generic_param_rib(
&generics.params,
RibKind::AssocItem,
Expand All @@ -2908,28 +2909,30 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
kind: LifetimeBinderKind::ConstItem,
},
|this| {
// If this is a trait impl, ensure the const
// exists in trait
this.check_trait_item(
item.id,
item.ident,
&item.kind,
ValueNS,
item.span,
seen_trait_items,
|i, s, c| ConstNotMemberOfTrait(i, s, c),
);
this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
// If this is a trait impl, ensure the const
// exists in trait
this.check_trait_item(
item.id,
item.ident,
&item.kind,
ValueNS,
item.span,
seen_trait_items,
|i, s, c| ConstNotMemberOfTrait(i, s, c),
);

this.visit_generics(generics);
this.visit_ty(ty);
if let Some(expr) = expr {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
this.resolve_const_body(expr, None);
}
this.visit_generics(generics);
this.visit_ty(ty);
if let Some(expr) = expr {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
this.resolve_const_body(expr, None);
}
});
},
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ trait Trait {
impl Trait for () {
const ASSOC: &dyn Fn(_) = 1i32;
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants
//~| ERROR `&` without an explicit lifetime name cannot be used here
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18
|
LL | const ASSOC: &dyn Fn(_) = 1i32;
| ^ explicit lifetime name needed here

error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
--> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26
|
LL | const ASSOC: &dyn Fn(_) = 1i32;
| ^ not allowed in type signatures

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0121`.
Some errors have detailed explanations: E0121, E0637.
For more information about an error, try `rustc --explain E0121`.
12 changes: 12 additions & 0 deletions tests/ui/consts/assoc-const-elided-lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use std::marker::PhantomData;

struct Foo<'a> {
x: PhantomData<&'a ()>,
}

impl<'a> Foo<'a> {
const FOO: Foo<'_> = Foo { x: PhantomData::<&'a ()> };
//~^ ERROR `'_` cannot be used here
}

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/consts/assoc-const-elided-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0637]: `'_` cannot be used here
--> $DIR/assoc-const-elided-lifetime.rs:8:20
|
LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&'a ()> };
| ^^ `'_` is a reserved lifetime name

error: aborting due to previous error

For more information about this error, try `rustc --explain E0637`.
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error[E0106]: missing lifetime specifier
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14
|
LL | const A: &str = "";
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL ~ trait ZstAssert<'a>: Sized {
LL ~ const A: &'a str = "";
|
| ^ explicit lifetime name needed here

error[E0106]: missing lifetime specifier
--> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14
Expand All @@ -23,19 +17,11 @@ LL | const A: &str = "";
LL ~ const B: S<'a> = S { s: &() };
|

error[E0106]: missing lifetime specifier
error[E0637]: `'_` cannot be used here
--> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15
|
LL | const C: &'_ str = "";
| ^^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL ~ trait ZstAssert<'a>: Sized {
LL | const A: &str = "";
LL | const B: S = S { s: &() };
LL ~ const C: &'a str = "";
|
| ^^ `'_` is a reserved lifetime name

error[E0106]: missing lifetime specifiers
--> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14
Expand All @@ -54,4 +40,5 @@ LL ~ const D: T<'a, 'a> = T { a: &(), b: &() };

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0106`.
Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
error[E0106]: missing lifetime specifier
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14
|
LL | const A: &str = "";
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL | const A<'a>: &'a str = "";
| ++++ ++
| ^ explicit lifetime name needed here

error[E0106]: missing lifetime specifier
--> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14
Expand All @@ -20,16 +15,11 @@ help: consider introducing a named lifetime parameter
LL | const B<'a>: S<'a> = S { s: &() };
| ++++ ++++

error[E0106]: missing lifetime specifier
error[E0637]: `'_` cannot be used here
--> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15
|
LL | const C: &'_ str = "";
| ^^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL | const C<'a>: &'a str = "";
| ++++ ~~
Comment on lines -27 to -32
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I could probably recover this suggestion by inverting the order of the lifetime ribs... Doesn't seem particularly useful, though.

Copy link
Member

@fmease fmease Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we end up deciding on dropping these suggestion diagnostics (personally I'm fine either way, I also don't know how useful they are, mainly they're consistent with other diagnostics), then you can get rid of the revisions of this test as well as LifetimeBinderKind::ConstItem (replace it with Item) in late/diagnostics.rs and error handling code related to it since it will become unreachable.

| ^^ `'_` is a reserved lifetime name

error[E0106]: missing lifetime specifiers
--> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14
Expand All @@ -44,4 +34,5 @@ LL | const D<'a>: T<'a, 'a> = T { a: &(), b: &() };

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0106`.
Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
4 changes: 2 additions & 2 deletions tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#![cfg_attr(generic_const_items, feature(generic_const_items), allow(incomplete_features))]

trait ZstAssert: Sized {
const A: &str = ""; //~ ERROR missing lifetime specifier
const A: &str = ""; //~ ERROR `&` without an explicit lifetime name cannot be used here
const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
const C: &'_ str = ""; //~ ERROR missing lifetime specifier
const C: &'_ str = ""; //~ ERROR `'_` cannot be used here
const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
}

Expand Down