Skip to content
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

Perform WF-check on types with no type parameters #69741

Closed
wants to merge 1 commit into from
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
17 changes: 17 additions & 0 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
}
}
hir::ItemKind::TyAlias(ref ty, hir::Generics { params: [], .. }) => {
// We explicitely only check cases with *no* type parameters to avoid regressions on
// existing incorrectly accepted code like `type T<X> = <X as Trait>::Foo;`.

// We don't use `check_item_type` to *not* emit `!Sized` errors.
let ty_span = ty.span;
for_id(tcx, item.hir_id(), ty_span).with_fcx(|fcx, tcx| {
let ty = tcx.type_of(def_id);
let item_ty = fcx.normalize_associated_types_in(ty_span, ty);
fcx.register_wf_obligation(
item_ty.into(),
ty_span,
ObligationCauseCode::MiscObligation,
);
vec![]
});
}
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
check_type_defn(tcx, item, false, |fcx| vec![fcx.non_enum_variant(struct_def)]);

Expand Down
6 changes: 5 additions & 1 deletion src/test/ui/conditional-compilation/cfg-generic-params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK
type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
//~^ ERROR only lifetime parameters can be used in this context

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

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

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

struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
Expand Down
53 changes: 45 additions & 8 deletions src/test/ui/conditional-compilation/cfg-generic-params.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,83 @@ LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
| ^

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

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

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

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

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

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

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

error: aborting due to 8 previous errors
error[E0038]: the trait `Copy` cannot be made into an object
--> $DIR/cfg-generic-params.rs:10:17
|
LL | type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
|
= note: the trait cannot be made into an object because it requires `Self: Sized`
= 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>

error[E0038]: the trait `Copy` cannot be made into an object
--> $DIR/cfg-generic-params.rs:12:16
|
LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
|
= note: the trait cannot be made into an object because it requires `Self: Sized`
= 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>

error[E0038]: the trait `Copy` cannot be made into an object
--> $DIR/cfg-generic-params.rs:31:15
|
LL | type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
|
= note: the trait cannot be made into an object because it requires `Self: Sized`
= 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>

error[E0038]: the trait `Copy` cannot be made into an object
--> $DIR/cfg-generic-params.rs:33:16
|
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
|
= note: the trait cannot be made into an object because it requires `Self: Sized`
= 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>

error: aborting due to 12 previous errors

For more information about this error, try `rustc --explain E0038`.
3 changes: 2 additions & 1 deletion src/test/ui/consts/const-eval/pub_const_err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pub const Z: u32 = 0 - 1;
//~^ WARN any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out

pub type Foo = [i32; 0 - 1];
//pub type Foo = [i32; 0 - 1];
//^ evaluation of constant value failed
Comment on lines +10 to +11
Copy link
Contributor

@oli-obk oli-obk Mar 29, 2021

Choose a reason for hiding this comment

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

Please turn these into error tests (see https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/erroneous.20constants.20in.20type.20alias/near/229492342 for "lang team sign off on making this a hard error since crater is clean")

3 changes: 2 additions & 1 deletion src/test/ui/consts/const-eval/pub_const_err_bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub const Z: u32 = 0 - 1;
//~^ WARN any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out

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

fn main() {}
7 changes: 0 additions & 7 deletions src/test/ui/consts/const_let_assign3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ const FOO: S = {
s
};

type Array = [u32; {
let mut x = 2;
let y = &mut x; //~ ERROR mutable reference
*y = 42;
*y
}];

fn main() {
assert_eq!(FOO.state, 3);
}
11 changes: 1 addition & 10 deletions src/test/ui/consts/const_let_assign3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ LL | s.foo(3);
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable

error[E0658]: mutable references are not allowed in constants
--> $DIR/const_let_assign3.rs:22:13
|
LL | let y = &mut x;
| ^^^^^^
|
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable

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

For more information about this error, try `rustc --explain E0658`.
31 changes: 31 additions & 0 deletions src/test/ui/consts/const_let_assign4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#![feature(const_fn)]

struct S {
state: u32,
}

impl S {
const fn foo(&mut self, x: u32) {
self.state = x;
}
}

const FOO: S = {
let mut s = S { state: 42 };
s.foo(3);
s
};
// The `impl` and `const` would error out if the following `type` was correct.
// See `const_let_assignment3.rs`.

type Array = [u32; {
let mut x = 2;
let y = &mut x;
//~^ ERROR mutable references are not allowed in constants
*y = 42;
*y
}];

fn main() {
assert_eq!(FOO.state, 3);
}
12 changes: 12 additions & 0 deletions src/test/ui/consts/const_let_assign4.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0658]: mutable references are not allowed in constants
--> $DIR/const_let_assign4.rs:23:13
|
LL | let y = &mut x;
| ^^^^^^
|
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
2 changes: 1 addition & 1 deletion src/test/ui/feature-gates/feature-gate-trivial_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ trait T where i32: Foo {} //~ ERROR

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

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

impl Foo for () where i32: Foo { //~ ERROR
fn test(&self) {
Expand Down
11 changes: 10 additions & 1 deletion src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ LL | union U where i32: Foo { f: i32 }
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable

error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:18:25
|
LL | type Y where i32: Foo = ();
| ^^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable

error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:20:1
|
Expand Down Expand Up @@ -123,6 +132,6 @@ LL | | }
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable

error: aborting due to 11 previous errors
error: aborting due to 12 previous errors

For more information about this error, try `rustc --explain E0277`.
8 changes: 4 additions & 4 deletions src/test/ui/hygiene/assoc_ty_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

trait Base {
type AssocTy;
fn f();
fn f(&self);
}
trait Derived: Base {
fn g();
fn g(&self);
}

macro mac() {
Expand All @@ -17,12 +17,12 @@ macro mac() {

impl Base for u8 {
type AssocTy = u8;
fn f() {
fn f(&self) {
let _: Self::AssocTy;
}
}
impl Derived for u8 {
fn g() {
fn g(&self) {
let _: Self::AssocTy;
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/resolve/issue-3907-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

extern crate issue_3907;

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

struct S {
name: isize
}

fn bar(_x: Foo) {}
//~^ ERROR E0038
fn bar(_x: Foo) {} //~ ERROR E0038

fn main() {}
14 changes: 13 additions & 1 deletion src/test/ui/resolve/issue-3907-2.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
--> $DIR/issue-3907-2.rs:5:12
|
LL | type Foo = dyn issue_3907::Foo + 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_3907::Foo` cannot be made into an object
|
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>
--> $DIR/auxiliary/issue-3907.rs:2:8
|
LL | fn bar();
| ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter

error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
--> $DIR/issue-3907-2.rs:11:12
|
Expand All @@ -10,6 +22,6 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
LL | fn bar();
| ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter

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

For more information about this error, try `rustc --explain E0038`.
3 changes: 1 addition & 2 deletions src/test/ui/structs/struct-path-alias-bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
struct S<T: Clone> { a: T }

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

fn main() {
let s = A { a: NoClone };
//~^ ERROR the trait bound `NoClone: Clone` is not satisfied
}
8 changes: 4 additions & 4 deletions src/test/ui/structs/struct-path-alias-bounds.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0277]: the trait bound `NoClone: Clone` is not satisfied
--> $DIR/struct-path-alias-bounds.rs:9:13
--> $DIR/struct-path-alias-bounds.rs:6:10
|
LL | struct S<T: Clone> { a: T }
| ------------------ required by `S`
| ----- required by this bound in `S`
...
LL | let s = A { a: NoClone };
| ^ the trait `Clone` is not implemented for `NoClone`
LL | type A = S<NoClone>;
| ^^^^^^^^^^ the trait `Clone` is not implemented for `NoClone`

error: aborting due to previous error

Expand Down