Skip to content

Commit cfea522

Browse files
Rollup merge of rust-lang#41939 - eddyb:trait-assoc-const-default, r=petrochenkov
rustc_resolve: don't deny outer type parameters in embedded constants. This solves a problem noted at rust-lang#29646 (comment), where an associated const default in a trait couldn't refer to `Self` or type parameters, due to inaccuracies in lexical scoping. I've also allowed "embedded expressions" (`[T; expr]`, `[x; expr]`, `typeof expr`) to refer to type parameters in scope. *However*, the typesystem still doesn't handle rust-lang#34344. Fully resolving that issue requires breaking cycles more aggressively (e.g. lazy evaluation), *even* in when the expression doesn't depend on type parameters, to type-check it at all, and then also type-level "constant projections" (in the vein of `{expr}` from const generics).
2 parents 27ea129 + dc7ffbe commit cfea522

13 files changed

+74
-51
lines changed

src/librustc_resolve/diagnostics.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1222,27 +1222,26 @@ fn foo() {
12221222
"##,
12231223

12241224
E0435: r##"
1225-
A non-constant value was used to initialise a constant.
1225+
A non-constant value was used in a constant expression.
12261226
12271227
Erroneous code example:
12281228
12291229
```compile_fail,E0435
1230-
let foo = 42u32;
1231-
const FOO : u32 = foo; // error: attempt to use a non-constant value in a
1232-
// constant
1230+
let foo = 42;
1231+
let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
12331232
```
12341233
12351234
To fix this error, please replace the value with a constant. Example:
12361235
12371236
```
1238-
const FOO : u32 = 42u32; // ok!
1237+
let a: [u8; 42]; // ok!
12391238
```
12401239
12411240
Or:
12421241
12431242
```
1244-
const OTHER_FOO : u32 = 42u32;
1245-
const FOO : u32 = OTHER_FOO; // ok!
1243+
const FOO: usize = 42;
1244+
let a: [u8; FOO]; // ok!
12461245
```
12471246
"##,
12481247

@@ -1560,7 +1559,7 @@ register_diagnostics! {
15601559
// E0157, unused error code
15611560
// E0257,
15621561
// E0258,
1563-
E0402, // cannot use an outer type parameter in this context
1562+
// E0402, // cannot use an outer type parameter in this context
15641563
// E0406, merged into 420
15651564
// E0410, merged into 408
15661565
// E0413, merged into 530

src/librustc_resolve/lib.rs

+25-28
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ impl Ord for BindingError {
127127
enum ResolutionError<'a> {
128128
/// error E0401: can't use type parameters from outer function
129129
TypeParametersFromOuterFunction,
130-
/// error E0402: cannot use an outer type parameter in this context
131-
OuterTypeParameterContext,
132130
/// error E0403: the name is already used for a type parameter in this type parameter list
133131
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
134132
/// error E0407: method is not a member of trait
@@ -187,12 +185,6 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
187185
err.span_label(span, "use of type variable from outer function");
188186
err
189187
}
190-
ResolutionError::OuterTypeParameterContext => {
191-
struct_span_err!(resolver.session,
192-
span,
193-
E0402,
194-
"cannot use an outer type parameter in this context")
195-
}
196188
ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
197189
let mut err = struct_span_err!(resolver.session,
198190
span,
@@ -1671,16 +1663,16 @@ impl<'a> Resolver<'a> {
16711663
this.check_proc_macro_attrs(&trait_item.attrs);
16721664

16731665
match trait_item.node {
1674-
TraitItemKind::Const(_, ref default) => {
1666+
TraitItemKind::Const(ref ty, ref default) => {
1667+
this.visit_ty(ty);
1668+
16751669
// Only impose the restrictions of
1676-
// ConstRibKind if there's an actual constant
1670+
// ConstRibKind for an actual constant
16771671
// expression in a provided default.
1678-
if default.is_some() {
1672+
if let Some(ref expr) = *default{
16791673
this.with_constant_rib(|this| {
1680-
visit::walk_trait_item(this, trait_item)
1674+
this.visit_expr(expr);
16811675
});
1682-
} else {
1683-
visit::walk_trait_item(this, trait_item)
16841676
}
16851677
}
16861678
TraitItemKind::Method(ref sig, _) => {
@@ -1709,9 +1701,13 @@ impl<'a> Resolver<'a> {
17091701
});
17101702
}
17111703

1712-
ItemKind::Const(..) | ItemKind::Static(..) => {
1713-
self.with_constant_rib(|this| {
1714-
visit::walk_item(this, item);
1704+
ItemKind::Static(ref ty, _, ref expr) |
1705+
ItemKind::Const(ref ty, ref expr) => {
1706+
self.with_item_rib(|this| {
1707+
this.visit_ty(ty);
1708+
this.with_constant_rib(|this| {
1709+
this.visit_expr(expr);
1710+
});
17151711
});
17161712
}
17171713

@@ -1782,13 +1778,21 @@ impl<'a> Resolver<'a> {
17821778
self.label_ribs.pop();
17831779
}
17841780

1781+
fn with_item_rib<F>(&mut self, f: F)
1782+
where F: FnOnce(&mut Resolver)
1783+
{
1784+
self.ribs[ValueNS].push(Rib::new(ItemRibKind));
1785+
self.ribs[TypeNS].push(Rib::new(ItemRibKind));
1786+
f(self);
1787+
self.ribs[TypeNS].pop();
1788+
self.ribs[ValueNS].pop();
1789+
}
1790+
17851791
fn with_constant_rib<F>(&mut self, f: F)
17861792
where F: FnOnce(&mut Resolver)
17871793
{
17881794
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
1789-
self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
17901795
f(self);
1791-
self.ribs[TypeNS].pop();
17921796
self.ribs[ValueNS].pop();
17931797
}
17941798

@@ -2755,7 +2759,8 @@ impl<'a> Resolver<'a> {
27552759
for rib in ribs {
27562760
match rib.kind {
27572761
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
2758-
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
2762+
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
2763+
ConstantItemRibKind => {
27592764
// Nothing to do. Continue.
27602765
}
27612766
ItemRibKind => {
@@ -2767,14 +2772,6 @@ impl<'a> Resolver<'a> {
27672772
}
27682773
return Def::Err;
27692774
}
2770-
ConstantItemRibKind => {
2771-
// see #9186
2772-
if record_used {
2773-
resolve_error(self, span,
2774-
ResolutionError::OuterTypeParameterContext);
2775-
}
2776-
return Def::Err;
2777-
}
27782775
}
27792776
}
27802777
}

src/test/compile-fail/E0435.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010

1111
fn main () {
1212
let foo = 42u32;
13-
const FOO : u32 = foo; //~ ERROR E0435
13+
let _: [u8; foo]; //~ ERROR E0435
1414
//~| NOTE non-constant used with constant
1515
}

src/test/compile-fail/associated-const-type-parameter-arrays-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl Foo for Def {
2626

2727
pub fn test<A: Foo, B: Foo>() {
2828
let _array = [4; <A as Foo>::Y];
29-
//~^ ERROR cannot use an outer type parameter in this context [E0402]
29+
//~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
3030
}
3131

3232
fn main() {

src/test/compile-fail/associated-const-type-parameter-arrays.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl Foo for Def {
2626

2727
pub fn test<A: Foo, B: Foo>() {
2828
let _array: [u32; <A as Foo>::Y];
29-
//~^ ERROR cannot use an outer type parameter in this context [E0402]
29+
//~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
3030
}
3131

3232
fn main() {

src/test/compile-fail/inner-static-type-parameter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
1414

1515
fn foo<T>() {
1616
static a: Bar<T> = Bar::What;
17-
//~^ ERROR cannot use an outer type parameter in this context
17+
//~^ ERROR can't use type parameters from outer function; try using a local type parameter instead
1818
}
1919

2020
fn main() {

src/test/compile-fail/issue-27433.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
fn main() {
1212
let foo = 42u32;
1313
const FOO : u32 = foo;
14-
//~^ ERROR attempt to use a non-constant value in a constant
14+
//~^ ERROR can't capture dynamic environment
1515
}

src/test/compile-fail/issue-3521-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() {
1212
let foo = 100;
1313

1414
static y: isize = foo + 1;
15-
//~^ ERROR attempt to use a non-constant value in a constant
15+
//~^ ERROR can't capture dynamic environment
1616

1717
println!("{}", y);
1818
}

src/test/compile-fail/issue-3668-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
fn f(x:isize) {
1212
static child: isize = x + 1;
13-
//~^ ERROR attempt to use a non-constant value in a constant
13+
//~^ ERROR can't capture dynamic environment
1414
}
1515

1616
fn main() {}

src/test/compile-fail/issue-3668.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ trait PTrait {
1616
impl PTrait for P {
1717
fn getChildOption(&self) -> Option<Box<P>> {
1818
static childVal: Box<P> = self.child.get();
19-
//~^ ERROR attempt to use a non-constant value in a constant
19+
//~^ ERROR can't capture dynamic environment
2020
panic!();
2121
}
2222
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Dim {
12+
fn dim() -> usize;
13+
}
14+
15+
enum Dim3 {}
16+
17+
impl Dim for Dim3 {
18+
fn dim() -> usize {
19+
3
20+
}
21+
}
22+
23+
fn main() {
24+
let array: [usize; Dim3::dim()]
25+
//~^ ERROR calls in constants are limited to constant functions
26+
= [0; Dim3::dim()];
27+
//~^ ERROR calls in constants are limited to constant functions
28+
}

src/test/compile-fail/issue-39559.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,7 @@ impl Dim for Dim3 {
2222

2323
pub struct Vector<T, D: Dim> {
2424
entries: [T; D::dim()]
25-
//~^ ERROR cannot use an outer type parameter in this context
25+
//~^ ERROR no associated item named `dim` found for type `D` in the current scope
2626
}
2727

28-
fn main() {
29-
let array: [usize; Dim3::dim()]
30-
//~^ ERROR calls in constants are limited to constant functions
31-
= [0; Dim3::dim()];
32-
//~^ ERROR calls in constants are limited to constant functions
33-
}
28+
fn main() {}

src/test/run-pass/associated-const-type-parameters.rs

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ fn sub<A: Foo, B: Foo>() -> i32 {
3737
A::X - B::X
3838
}
3939

40+
trait Bar: Foo {
41+
const Y: i32 = Self::X;
42+
}
43+
4044
fn main() {
4145
assert_eq!(11, Abc::X);
4246
assert_eq!(97, Def::X);

0 commit comments

Comments
 (0)