Skip to content

Commit 1c3429f

Browse files
authored
Rollup merge of #153738 - fmease:dyn-ace-gingerly-care, r=BoxyUwU
Don't look for non-type-level assoc consts when checking trait object types On main, when looking for assoc items that weren't specified in a given trait object type (via binding), we comb through all (eligible) assoc consts whether type-level or not even though you're not allowed to bind non-type-level assoc consts. That's usually fine because traits containing (eligible) non-type-level assoc consts are dyn incompatible, so the trait object type is ~already considered ill-formed. Therefore, in PR #150843, I saved myself the extra effort, esp. since back then it was more annoying to check if the const item was declared type-level. <sub>(More concretely: In bodies, we check for all dyn compatibility violations when lowering the trait object type, so we will bail out early with an error; in contrast, item signatures / non-bodies get wfchecked (`WellFormed` obligation) after lowering which includes dyn compatiblity checking (`DynCompatible` obligation); however to reduce the amount of diags, during lowering if there are any unspecified assoc items, we'll check them for dyn compatibility and bail out early if any of them tests negative.)</sub> Now, we obviously don't wfcheck the defsite of (eager) type aliases which breaks the assumption that such trait object types get rejected. This led to the regression found in #153731: The ill-formed trait object type doesn't get rejected (as is expected) but we now require the single (non-type-level) assoc const to be bound in the dyn-Trait which we didn't do before. The actual error talks about dyn incompatibility due to the aforementioned extra check that's usually there to contain the number of diags. Fixes [after beta backport] #153731.
2 parents fec951b + f8bce56 commit 1c3429f

10 files changed

Lines changed: 82 additions & 15 deletions

File tree

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
231231
ordered_associated_items.extend(
232232
tcx.associated_items(pred.trait_ref.def_id)
233233
.in_definition_order()
234-
// Only associated types & consts can possibly be constrained via a binding.
235-
.filter(|item| item.is_type() || item.is_const())
234+
// Only associated types & type consts can possibly be
235+
// constrained in a trait object type via a binding.
236+
.filter(|item| item.is_type() || item.is_type_const())
236237
// Traits with RPITITs are simply not dyn compatible (for now).
237238
.filter(|item| !item.is_impl_trait_in_trait())
238239
.map(|item| (item.def_id, trait_ref)),

compiler/rustc_middle/src/ty/assoc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ impl AssocItem {
137137
self.kind.as_def_kind()
138138
}
139139

140-
pub fn is_const(&self) -> bool {
141-
matches!(self.kind, ty::AssocKind::Const { .. })
140+
pub fn is_type_const(&self) -> bool {
141+
matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. })
142142
}
143143

144144
pub fn is_fn(&self) -> bool {

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ impl<'tcx> Ty<'tcx> {
753753
.map(|principal| {
754754
tcx.associated_items(principal.def_id())
755755
.in_definition_order()
756-
.filter(|item| item.is_type() || item.is_const())
756+
.filter(|item| item.is_type() || item.is_type_const())
757757
.filter(|item| !item.is_impl_trait_in_trait())
758758
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
759759
.count()

compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
239239
.flat_map(|super_poly_trait_ref| {
240240
tcx.associated_items(super_poly_trait_ref.def_id())
241241
.in_definition_order()
242-
.filter(|item| item.is_type() || item.is_const())
242+
.filter(|item| item.is_type() || item.is_type_const())
243243
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
244244
.map(move |assoc_item| {
245245
super_poly_trait_ref.map_bound(|super_trait_ref| {

tests/ui/associated-consts/associated-const-in-trait.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ trait Trait {
77
impl dyn Trait {
88
//~^ ERROR the trait `Trait` is not dyn compatible [E0038]
99
const fn n() -> usize { Self::N }
10+
//~^ ERROR the trait `Trait` is not dyn compatible [E0038]
11+
//~| ERROR the trait `Trait` is not dyn compatible [E0038]
1012
}
1113

1214
fn main() {}

tests/ui/associated-consts/associated-const-in-trait.stderr

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `Trait` is not dyn compatible
2-
--> $DIR/associated-const-in-trait.rs:7:10
2+
--> $DIR/associated-const-in-trait.rs:7:6
33
|
44
LL | impl dyn Trait {
5-
| ^^^^^ `Trait` is not dyn compatible
5+
| ^^^^^^^^^ `Trait` is not dyn compatible
66
|
77
note: for a trait to be dyn compatible it needs to allow building a vtable
88
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -14,6 +14,38 @@ LL | const N: usize;
1414
| ^ ...because it contains associated const `N`
1515
= help: consider moving `N` to another trait
1616

17-
error: aborting due to 1 previous error
17+
error[E0038]: the trait `Trait` is not dyn compatible
18+
--> $DIR/associated-const-in-trait.rs:9:29
19+
|
20+
LL | const fn n() -> usize { Self::N }
21+
| ^^^^ `Trait` is not dyn compatible
22+
|
23+
note: for a trait to be dyn compatible it needs to allow building a vtable
24+
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
25+
--> $DIR/associated-const-in-trait.rs:4:11
26+
|
27+
LL | trait Trait {
28+
| ----- this trait is not dyn compatible...
29+
LL | const N: usize;
30+
| ^ ...because it contains associated const `N`
31+
= help: consider moving `N` to another trait
32+
33+
error[E0038]: the trait `Trait` is not dyn compatible
34+
--> $DIR/associated-const-in-trait.rs:9:29
35+
|
36+
LL | const fn n() -> usize { Self::N }
37+
| ^^^^^^^ `Trait` is not dyn compatible
38+
|
39+
note: for a trait to be dyn compatible it needs to allow building a vtable
40+
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
41+
--> $DIR/associated-const-in-trait.rs:4:11
42+
|
43+
LL | trait Trait {
44+
| ----- this trait is not dyn compatible...
45+
LL | const N: usize;
46+
| ^ ...because it contains associated const `N`
47+
= help: consider moving `N` to another trait
48+
49+
error: aborting due to 3 previous errors
1850

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

tests/ui/associated-item/issue-48027.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `Bar` is not dyn compatible
2-
--> $DIR/issue-48027.rs:6:10
2+
--> $DIR/issue-48027.rs:6:6
33
|
44
LL | impl dyn Bar {}
5-
| ^^^ `Bar` is not dyn compatible
5+
| ^^^^^^^ `Bar` is not dyn compatible
66
|
77
note: for a trait to be dyn compatible it needs to allow building a vtable
88
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/dyn-compatibility/associated-consts.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `Bar` is not dyn compatible
2-
--> $DIR/associated-consts.rs:8:35
2+
--> $DIR/associated-consts.rs:8:31
33
|
44
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
5-
| ^^^ `Bar` is not dyn compatible
5+
| ^^^^^^^ `Bar` is not dyn compatible
66
|
77
note: for a trait to be dyn compatible it needs to allow building a vtable
88
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Demonstrate that we don't check the definition site of (eager) type aliases for well-formedness.
2+
//
3+
// Listed below are ill-formed type system entities which we don't reject since they appear inside
4+
// the definition of (eager) type aliases. These type aliases are intentionally not referenced from
5+
// anywhere to prevent the eagerly expanded / instantiated aliased types from getting wfchecked
6+
// since that's not what we're testing here.
7+
8+
//@ check-pass
9+
10+
type UnsatTraitBound0 = [str]; // `str: Sized` unsatisfied
11+
type UnsatTraitBound1<T = Vec<str>> = T; // `str: Sized` unsatisfied
12+
type UnsatOutlivesBound<'a> = &'static &'a (); // `'a: 'static` unsatisfied
13+
14+
type Diverging = [(); panic!()]; // `panic!()` diverging
15+
16+
type DynIncompat0 = dyn Sized; // `Sized` axiomatically dyn incompatible
17+
// issue: <https://github.com/rust-lang/rust/issues/153731>
18+
type DynIncompat1 = dyn HasAssocConst; // dyn incompatible due to (non-type-level) assoc const
19+
20+
// * dyn incompatible due to GAT
21+
// * `'a: 'static`, `String: Copy` and `[u8]: Sized` unsatisfied, `loop {}` diverging
22+
type Several<'a> = dyn HasGenericAssocType<Type<'a, String, { loop {} }> = [u8]>;
23+
24+
trait HasAssocConst { const N: usize; }
25+
trait HasGenericAssocType { type Type<'a: 'static, T: Copy, const N: usize>; }
26+
27+
fn main() {}

tests/ui/wf/issue-87495.stderr

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `T` is not dyn compatible
2-
--> $DIR/issue-87495.rs:4:29
2+
--> $DIR/issue-87495.rs:4:25
33
|
44
LL | const CONST: (bool, dyn T);
5-
| ^ `T` is not dyn compatible
5+
| ^^^^^ `T` is not dyn compatible
66
|
77
note: for a trait to be dyn compatible it needs to allow building a vtable
88
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -13,6 +13,11 @@ LL | trait T {
1313
LL | const CONST: (bool, dyn T);
1414
| ^^^^^ ...because it contains associated const `CONST`
1515
= help: consider moving `CONST` to another trait
16+
help: you might have meant to use `Self` to refer to the implementing type
17+
|
18+
LL - const CONST: (bool, dyn T);
19+
LL + const CONST: (bool, Self);
20+
|
1621

1722
error: aborting due to 1 previous error
1823

0 commit comments

Comments
 (0)