Skip to content

Commit a5ba21d

Browse files
committed
Perform WF-check on types with no type parameters
Start performing a WF-check on `type`s to verify that they will be able to be constructed. Do *not* perform a `Sized` check, as `type T = dyn Trait;` should be allowed. Do *not* WF-check `type`s with type parameters because we currently lint *against* `type T<X: Trait> = K<X>;` because we do not propagate `X: Trait`, which means that we currently allow `type T<X> = <X as Trait>::Foo;`, which would be rejected if we WF-checked it because it would need to be written as `type T<X: Trait> = <X as Trait>::Foo;` to be correct. Instead, we simply don't check it at definition and only do so at use like we do currently. In the future, the alternatives would be to either automatically backpropagate the `X: Trait` obligation when WF-checking the `type` or (my preferred solution) properly propagate the explicit `X: Trait` obligation to the uses, which would likely be a breaking change. Fixes rust-lang#60980 by using a more appropriate span for the error.
1 parent 3e826bb commit a5ba21d

16 files changed

+150
-44
lines changed

compiler/rustc_typeck/src/check/wfcheck.rs

+17
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
163163
}
164164
}
165165
}
166+
hir::ItemKind::TyAlias(ref ty, hir::Generics { params: [], .. }) => {
167+
// We explicitely only check cases with *no* type parameters to avoid regressions on
168+
// existing incorrectly accepted code like `type T<X> = <X as Trait>::Foo;`.
169+
170+
// We don't use `check_item_type` to *not* emit `!Sized` errors.
171+
let ty_span = ty.span;
172+
for_id(tcx, item.hir_id(), ty_span).with_fcx(|fcx, tcx| {
173+
let ty = tcx.type_of(def_id);
174+
let item_ty = fcx.normalize_associated_types_in(ty_span, ty);
175+
fcx.register_wf_obligation(
176+
item_ty.into(),
177+
ty_span,
178+
ObligationCauseCode::MiscObligation,
179+
);
180+
vec![]
181+
});
182+
}
166183
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
167184
check_type_defn(tcx, item, false, |fcx| vec![fcx.non_enum_variant(struct_def)]);
168185

src/test/ui/conditional-compilation/cfg-generic-params.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK
77
type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
88
//~^ ERROR only lifetime parameters can be used in this context
99

10-
type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy; // OK
10+
type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy;
11+
//~^ ERROR the trait `Copy` cannot be made into an object
1112
type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
1213
//~^ ERROR only lifetime parameters can be used in this context
14+
//~| ERROR the trait `Copy` cannot be made into an object
1315

1416
struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(no)] T> u8: Copy; // OK
1517
struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
@@ -27,8 +29,10 @@ type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
2729
//~^ ERROR cannot find attribute `unknown` in this scope
2830

2931
type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
32+
//~^ ERROR the trait `Copy` cannot be made into an object
3033
type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
3134
//~^ ERROR cannot find attribute `unknown` in this scope
35+
//~| ERROR the trait `Copy` cannot be made into an object
3236

3337
struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
3438
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;

src/test/ui/conditional-compilation/cfg-generic-params.stderr

+45-8
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,83 @@ LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
55
| ^
66

77
error: only lifetime parameters can be used in this context
8-
--> $DIR/cfg-generic-params.rs:11:51
8+
--> $DIR/cfg-generic-params.rs:12:51
99
|
1010
LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
1111
| ^
1212

1313
error: only lifetime parameters can be used in this context
14-
--> $DIR/cfg-generic-params.rs:15:54
14+
--> $DIR/cfg-generic-params.rs:17:54
1515
|
1616
LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
1717
| ^
1818

1919
error: cannot find attribute `unknown` in this scope
20-
--> $DIR/cfg-generic-params.rs:19:29
20+
--> $DIR/cfg-generic-params.rs:21:29
2121
|
2222
LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
2323
| ^^^^^^^
2424

2525
error: cannot find attribute `unknown` in this scope
26-
--> $DIR/cfg-generic-params.rs:22:29
26+
--> $DIR/cfg-generic-params.rs:24:29
2727
|
2828
LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
2929
| ^^^^^^^
3030

3131
error: cannot find attribute `unknown` in this scope
32-
--> $DIR/cfg-generic-params.rs:26:34
32+
--> $DIR/cfg-generic-params.rs:28:34
3333
|
3434
LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
3535
| ^^^^^^^
3636

3737
error: cannot find attribute `unknown` in this scope
38-
--> $DIR/cfg-generic-params.rs:30:40
38+
--> $DIR/cfg-generic-params.rs:33:40
3939
|
4040
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
4141
| ^^^^^^^
4242

4343
error: cannot find attribute `unknown` in this scope
44-
--> $DIR/cfg-generic-params.rs:34:43
44+
--> $DIR/cfg-generic-params.rs:38:43
4545
|
4646
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
4747
| ^^^^^^^
4848

49-
error: aborting due to 8 previous errors
49+
error[E0038]: the trait `Copy` cannot be made into an object
50+
--> $DIR/cfg-generic-params.rs:10:17
51+
|
52+
LL | type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy;
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
54+
|
55+
= note: the trait cannot be made into an object because it requires `Self: Sized`
56+
= note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
57+
58+
error[E0038]: the trait `Copy` cannot be made into an object
59+
--> $DIR/cfg-generic-params.rs:12:16
60+
|
61+
LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
63+
|
64+
= note: the trait cannot be made into an object because it requires `Self: Sized`
65+
= note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
66+
67+
error[E0038]: the trait `Copy` cannot be made into an object
68+
--> $DIR/cfg-generic-params.rs:31:15
69+
|
70+
LL | type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
72+
|
73+
= note: the trait cannot be made into an object because it requires `Self: Sized`
74+
= note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
75+
76+
error[E0038]: the trait `Copy` cannot be made into an object
77+
--> $DIR/cfg-generic-params.rs:33:16
78+
|
79+
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
80+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
81+
|
82+
= note: the trait cannot be made into an object because it requires `Self: Sized`
83+
= note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
84+
85+
error: aborting due to 12 previous errors
5086

87+
For more information about this error, try `rustc --explain E0038`.

src/test/ui/consts/const-eval/pub_const_err.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ pub const Z: u32 = 0 - 1;
77
//~^ WARN any use of this value will cause an error
88
//~| WARN this was previously accepted by the compiler but is being phased out
99

10-
pub type Foo = [i32; 0 - 1];
10+
//pub type Foo = [i32; 0 - 1];
11+
//^ evaluation of constant value failed

src/test/ui/consts/const-eval/pub_const_err_bin.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub const Z: u32 = 0 - 1;
55
//~^ WARN any use of this value will cause an error
66
//~| WARN this was previously accepted by the compiler but is being phased out
77

8-
pub type Foo = [i32; 0 - 1];
8+
// pub type Foo = [i32; 0 - 1];
9+
//^ evaluation of constant value failed
910

1011
fn main() {}

src/test/ui/consts/const_let_assign3.rs

-7
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,6 @@ const FOO: S = {
1717
s
1818
};
1919

20-
type Array = [u32; {
21-
let mut x = 2;
22-
let y = &mut x; //~ ERROR mutable reference
23-
*y = 42;
24-
*y
25-
}];
26-
2720
fn main() {
2821
assert_eq!(FOO.state, 3);
2922
}

src/test/ui/consts/const_let_assign3.stderr

+1-10
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@ LL | s.foo(3);
1616
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
1717
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
1818

19-
error[E0658]: mutable references are not allowed in constants
20-
--> $DIR/const_let_assign3.rs:22:13
21-
|
22-
LL | let y = &mut x;
23-
| ^^^^^^
24-
|
25-
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
26-
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
27-
28-
error: aborting due to 3 previous errors
19+
error: aborting due to 2 previous errors
2920

3021
For more information about this error, try `rustc --explain E0658`.
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![feature(const_fn)]
2+
3+
struct S {
4+
state: u32,
5+
}
6+
7+
impl S {
8+
const fn foo(&mut self, x: u32) {
9+
self.state = x;
10+
}
11+
}
12+
13+
const FOO: S = {
14+
let mut s = S { state: 42 };
15+
s.foo(3);
16+
s
17+
};
18+
// The `impl` and `const` would error out if the following `type` was correct.
19+
// See `const_let_assignment3.rs`.
20+
21+
type Array = [u32; {
22+
let mut x = 2;
23+
let y = &mut x;
24+
//~^ ERROR mutable references are not allowed in constants
25+
*y = 42;
26+
*y
27+
}];
28+
29+
fn main() {
30+
assert_eq!(FOO.state, 3);
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: mutable references are not allowed in constants
2+
--> $DIR/const_let_assign4.rs:23:13
3+
|
4+
LL | let y = &mut x;
5+
| ^^^^^^
6+
|
7+
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
8+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/feature-gates/feature-gate-trivial_bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ trait T where i32: Foo {} //~ ERROR
1515

1616
union U where i32: Foo { f: i32 } //~ ERROR
1717

18-
type Y where i32: Foo = (); // OK - bound is ignored
18+
type Y where i32: Foo = (); //~ ERROR
1919

2020
impl Foo for () where i32: Foo { //~ ERROR
2121
fn test(&self) {

src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ LL | union U where i32: Foo { f: i32 }
3434
= help: see issue #48214
3535
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
3636

37+
error[E0277]: the trait bound `i32: Foo` is not satisfied
38+
--> $DIR/feature-gate-trivial_bounds.rs:18:25
39+
|
40+
LL | type Y where i32: Foo = ();
41+
| ^^ the trait `Foo` is not implemented for `i32`
42+
|
43+
= help: see issue #48214
44+
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
45+
3746
error[E0277]: the trait bound `i32: Foo` is not satisfied
3847
--> $DIR/feature-gate-trivial_bounds.rs:20:1
3948
|
@@ -123,6 +132,6 @@ LL | | }
123132
= help: see issue #48214
124133
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
125134

126-
error: aborting due to 11 previous errors
135+
error: aborting due to 12 previous errors
127136

128137
For more information about this error, try `rustc --explain E0277`.

src/test/ui/hygiene/assoc_ty_bindings.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
trait Base {
77
type AssocTy;
8-
fn f();
8+
fn f(&self);
99
}
1010
trait Derived: Base {
11-
fn g();
11+
fn g(&self);
1212
}
1313

1414
macro mac() {
@@ -17,12 +17,12 @@ macro mac() {
1717

1818
impl Base for u8 {
1919
type AssocTy = u8;
20-
fn f() {
20+
fn f(&self) {
2121
let _: Self::AssocTy;
2222
}
2323
}
2424
impl Derived for u8 {
25-
fn g() {
25+
fn g(&self) {
2626
let _: Self::AssocTy;
2727
}
2828
}

src/test/ui/resolve/issue-3907-2.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
extern crate issue_3907;
44

5-
type Foo = dyn issue_3907::Foo + 'static;
5+
type Foo = dyn issue_3907::Foo + 'static; //~ ERROR E0038
66

77
struct S {
88
name: isize
99
}
1010

11-
fn bar(_x: Foo) {}
12-
//~^ ERROR E0038
11+
fn bar(_x: Foo) {} //~ ERROR E0038
1312

1413
fn main() {}

src/test/ui/resolve/issue-3907-2.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
2+
--> $DIR/issue-3907-2.rs:5:12
3+
|
4+
LL | type Foo = dyn issue_3907::Foo + 'static;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_3907::Foo` cannot be made into an object
6+
|
7+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
8+
--> $DIR/auxiliary/issue-3907.rs:2:8
9+
|
10+
LL | fn bar();
11+
| ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter
12+
113
error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
214
--> $DIR/issue-3907-2.rs:11:12
315
|
@@ -10,6 +22,6 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
1022
LL | fn bar();
1123
| ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter
1224

13-
error: aborting due to previous error
25+
error: aborting due to 2 previous errors
1426

1527
For more information about this error, try `rustc --explain E0038`.

src/test/ui/structs/struct-path-alias-bounds.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
struct S<T: Clone> { a: T }
44

55
struct NoClone;
6-
type A = S<NoClone>;
6+
type A = S<NoClone>; //~ ERROR the trait bound `NoClone: Clone` is not satisfied
77

88
fn main() {
99
let s = A { a: NoClone };
10-
//~^ ERROR the trait bound `NoClone: Clone` is not satisfied
1110
}

src/test/ui/structs/struct-path-alias-bounds.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `NoClone: Clone` is not satisfied
2-
--> $DIR/struct-path-alias-bounds.rs:9:13
2+
--> $DIR/struct-path-alias-bounds.rs:6:10
33
|
44
LL | struct S<T: Clone> { a: T }
5-
| ------------------ required by `S`
5+
| ----- required by this bound in `S`
66
...
7-
LL | let s = A { a: NoClone };
8-
| ^ the trait `Clone` is not implemented for `NoClone`
7+
LL | type A = S<NoClone>;
8+
| ^^^^^^^^^^ the trait `Clone` is not implemented for `NoClone`
99

1010
error: aborting due to previous error
1111

0 commit comments

Comments
 (0)