Skip to content
Merged
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
83 changes: 43 additions & 40 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,47 +903,50 @@ where
if goal.predicate.polarity != ty::ClausePolarity::Positive {
return Err(NoSolution.into());
}
if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
&& let Some(FieldInfo { base, ty, .. }) =
def.field_representing_type_info(ecx.cx(), args)
&& {
let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
// FIXME: add better support for builtin impls of traits that check for the bounds
// on the trait definition in std.

// NOTE: these bounds have to be kept in sync with the definition of the `Field`
// trait in `library/core/src/field.rs` as well as the old trait solver `fn
// assemble_candidates_for_field_trait` in
// `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`.
ecx.add_goal(
GoalSource::ImplWhereBound,
Goal {
param_env: goal.param_env,
predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
},
)?;
ecx.add_goal(
GoalSource::ImplWhereBound,
Goal {
param_env: goal.param_env,
predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
},
)?;
// FIXME(field_projections): This function does some questionable incomplete stuff by
// returning `Err(NoSolution)` on ambiguity.
ecx.try_evaluate_added_goals()? == Certainty::Yes
}
&& match base.kind() {
ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
ty::Tuple(..) => true,
_ => false,
}
{
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
} else {
Err(NoSolution.into())

let ty::Adt(def, args) = goal.predicate.self_ty().kind() else {
return Err(NoSolution.into());
};

let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
else {
return Err(NoSolution.into());
};

match base.kind() {
ty::Adt(def, _) if def.is_struct() && !def.is_packed() => {}
ty::Adt(..) => return Err(NoSolution.into()),
ty::Tuple(..) => {}
_ => unreachable!(),
}

ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);

// FIXME: add better support for builtin impls of traits that check for the bounds
// on the trait definition in std.
//
// NOTE: these bounds have to be kept in sync with the definition of the `Field`
// trait in `library/core/src/field.rs` as well as the old trait solver `fn
// assemble_candidates_for_field_trait` in
// `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`.
ecx.add_goal(
GoalSource::ImplWhereBound,
Goal {
param_env: goal.param_env,
predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
},
)?;
ecx.add_goal(
GoalSource::ImplWhereBound,
Goal {
param_env: goal.param_env,
predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
},
)?;

ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//@ edition: 2021
//@ compile-flags: -Znext-solver -Arecursion_depth_exceeding_limit

#![forbid(unsafe_code)]
#![feature(field_projections)]
#![allow(incomplete_features)]

use core::field::{Field, field_of};

trait Chain {
type A;
}

impl Chain for () {
type A = u8;
}

struct Link<T>(T);

impl<T: Chain> Chain for Link<T> {
type A = <T as Chain>::A;
}

type L4<T> = Link<Link<Link<Link<T>>>>;
type L16<T> = L4<L4<L4<L4<T>>>>;
type L64<T> = L16<L16<L16<L16<T>>>>;
type Deep = L64<L64<L64<()>>>; // 192 links

struct S<Y: Chain> {
f: <Y as Chain>::A,
}

trait Tr {
type Out;
}

impl<Y: Chain> Tr for S<Y>
where
field_of!(S<Y>, f): Field,
{
type Out = u8;
}

impl Tr for S<Deep> { //~ ERROR conflicting implementations of trait `Tr`
type Out = [u8; 16];
}

fn poly<Y: Chain>() -> <S<Y> as Tr>::Out {
0
}

fn main() {
let v = poly::<Deep>();
println!("{:?}", v);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0119]: conflicting implementations of trait `Tr` for type `S<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/field-projection-overflow-coherence.rs:44:1
|
LL | / impl<Y: Chain> Tr for S<Y>
LL | | where
LL | | field_of!(S<Y>, f): Field,
| |______________________________- first implementation here
...
LL | impl Tr for S<Deep> {
| ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
|
= note: overflow evaluating the requirement `Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Chain`
= note: overflow evaluating the requirement `field_of!(S<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<Link<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, f): Field`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`field_projection_overflow_coherence`)

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
24 changes: 20 additions & 4 deletions tests/ui/field_representing_types/not-field-if-unsized.next.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/not-field-if-unsized.rs:17:20
|
LL | assert_field::<field_of!(MyStruct, 0)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)`
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `field_of!(MyStruct, 0)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
note: required because it appears within the type `MyStruct`
--> $DIR/not-field-if-unsized.rs:10:28
|
LL | pub struct MyStruct(usize, dyn Trait);
| ^^^^^^^^^ required by this field
note: required because it appears within the type `field_of!(MyStruct, 0)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `assert_field`
--> $DIR/not-field-if-unsized.rs:12:20
|
LL | fn assert_field<F: Field>() {}
| ^^^^^ required by this bound in `assert_field`

error[E0277]: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/not-field-if-unsized.rs:21:20
|
LL | assert_field::<field_of!(MyStruct, 1)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)`
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `field_of!(MyStruct, 1)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
note: required because it appears within the type `MyStruct`
--> $DIR/not-field-if-unsized.rs:10:28
|
LL | pub struct MyStruct(usize, dyn Trait);
| ^^^^^^^^^ required by this field
note: required because it appears within the type `field_of!(MyStruct, 1)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `assert_field`
--> $DIR/not-field-if-unsized.rs:12:20
|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied
--> $DIR/not-field-if-unsized.rs:17:20
|
LL | assert_field::<field_of!(MyStruct, 0)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)`
LL | ..._field::<field_of!(MyStruct, 0)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)`
|
note: required by a bound in `assert_field`
--> $DIR/not-field-if-unsized.rs:12:20
Expand All @@ -13,8 +13,8 @@ LL | fn assert_field<F: Field>() {}
error[E0277]: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied
--> $DIR/not-field-if-unsized.rs:21:20
|
LL | assert_field::<field_of!(MyStruct, 1)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)`
LL | ..._field::<field_of!(MyStruct, 1)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)`
|
note: required by a bound in `assert_field`
--> $DIR/not-field-if-unsized.rs:12:20
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/field_representing_types/not-field-if-unsized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ fn assert_field<F: Field>() {}
fn main() {
// FIXME(FRTs): this requires relaxing the `Base: ?Sized` bound in the
// `Field` trait & compiler changes.
assert_field::<field_of!(MyStruct, 0)>();
//~^ ERROR: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied [E0277]
assert_field::<field_of!(MyStruct, 0)>(); //[next]~ ERROR: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time [E0277]
//[old]~^ ERROR: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied [E0277]

// FIXME(FRTs): improve this error message, point to the `dyn Trait` span.
assert_field::<field_of!(MyStruct, 1)>();
//~^ ERROR: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied [E0277]
assert_field::<field_of!(MyStruct, 1)>(); //[next]~ ERROR: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time [E0277]
//[old]~^ ERROR: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied [E0277]
}
69 changes: 61 additions & 8 deletions tests/ui/field_representing_types/sized.next.stderr
Original file line number Diff line number Diff line change
@@ -1,45 +1,98 @@
error[E0277]: the trait bound `field_of!(Generic<T>, count): Field` is not satisfied
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/sized.rs:20:19
|
LL | fn generic<T: ?Sized>() {
| - this type parameter needs to be `Sized`
LL | impls_field::<field_of!(Generic<T>, count)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic<T>, count)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required because it appears within the type `Generic<T>`
--> $DIR/sized.rs:16:5
|
LL | pub struct Generic<T: ?Sized> {
LL | count: usize,
LL | last: T,
| ^^^^^^^ required by this field
note: required because it appears within the type `field_of!(Generic<T>, count)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `impls_field`
--> $DIR/sized.rs:38:19
|
LL | fn impls_field<F: Field>() {}
| ^^^^^ required by this bound in `impls_field`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn generic<T: ?Sized>() {
LL + fn generic<T>() {
|

error[E0277]: the trait bound `field_of!(Generic<T>, last): Field` is not satisfied
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/sized.rs:22:19
|
LL | fn generic<T: ?Sized>() {
| - this type parameter needs to be `Sized`
...
LL | impls_field::<field_of!(Generic<T>, last)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic<T>, last)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required because it appears within the type `Generic<T>`
--> $DIR/sized.rs:16:5
|
LL | pub struct Generic<T: ?Sized> {
LL | count: usize,
LL | last: T,
| ^^^^^^^ required by this field
note: required because it appears within the type `field_of!(Generic<T>, last)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `impls_field`
--> $DIR/sized.rs:38:19
|
LL | fn impls_field<F: Field>() {}
| ^^^^^ required by this bound in `impls_field`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn generic<T: ?Sized>() {
LL + fn generic<T>() {
|

error[E0277]: the trait bound `field_of!(MyDST, count): Field` is not satisfied
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
--> $DIR/sized.rs:32:19
|
LL | impls_field::<field_of!(MyDST, count)>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, count)`
| ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `field_of!(MyDST, count)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)`
note: required because it appears within the type `MyDST`
--> $DIR/sized.rs:11:5
|
LL | pub struct MyDST {
LL | count: usize,
LL | last: dyn Debug,
| ^^^^^^^^^^^^^^^ required by this field
note: required because it appears within the type `field_of!(MyDST, count)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `impls_field`
--> $DIR/sized.rs:38:19
|
LL | fn impls_field<F: Field>() {}
| ^^^^^ required by this bound in `impls_field`

error[E0277]: the trait bound `field_of!(MyDST, last): Field` is not satisfied
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
--> $DIR/sized.rs:34:19
|
LL | impls_field::<field_of!(MyDST, last)>();
| ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, last)`
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `field_of!(MyDST, last)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)`
note: required because it appears within the type `MyDST`
--> $DIR/sized.rs:11:5
|
LL | pub struct MyDST {
LL | count: usize,
LL | last: dyn Debug,
| ^^^^^^^^^^^^^^^ required by this field
note: required because it appears within the type `field_of!(MyDST, last)`
--> $SRC_DIR/core/src/field.rs:LL:COL
note: required by a bound in `impls_field`
--> $DIR/sized.rs:38:19
|
Expand Down
Loading
Loading