Skip to content

Commit b273c2b

Browse files
committed
add builtin impls of Field and UnalignedField for FRTs
1 parent c0ca97f commit b273c2b

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
128128
&mut candidates,
129129
);
130130
}
131+
Some(LangItem::Field) => {
132+
self.assemble_builtin_candidates_for_field(obligation, &mut candidates);
133+
}
134+
Some(LangItem::UnalignedField) => {
135+
self.assemble_builtin_candidates_for_unaligned_field(
136+
obligation,
137+
&mut candidates,
138+
);
139+
}
131140
_ => {
132141
// We re-match here for traits that can have both builtin impls and user written impls.
133142
// After the builtin impls we need to also add user written impls, which we do not want to
@@ -1439,4 +1448,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14391448
}
14401449
}
14411450
}
1451+
1452+
fn assemble_builtin_candidates_for_field(
1453+
&mut self,
1454+
obligation: &PolyTraitObligation<'tcx>,
1455+
candidates: &mut SelectionCandidateSet<'tcx>,
1456+
) {
1457+
match obligation.predicate.self_ty().skip_binder().kind() {
1458+
ty::Field(container, field_path) => {
1459+
if field_path
1460+
.walk(self.infcx.tcx, *container, |base, _, _, _| {
1461+
if let ty::Adt(def, _) = base.kind()
1462+
&& def.repr().packed()
1463+
{
1464+
ControlFlow::Break(())
1465+
} else {
1466+
ControlFlow::Continue(())
1467+
}
1468+
})
1469+
.is_none()
1470+
{
1471+
// we only implement `Field` if all base types are not `repr(packed)`
1472+
candidates.vec.push(BuiltinCandidate)
1473+
}
1474+
}
1475+
1476+
_ => {}
1477+
}
1478+
}
1479+
1480+
fn assemble_builtin_candidates_for_unaligned_field(
1481+
&mut self,
1482+
obligation: &PolyTraitObligation<'tcx>,
1483+
candidates: &mut SelectionCandidateSet<'tcx>,
1484+
) {
1485+
match obligation.predicate.self_ty().skip_binder().kind() {
1486+
ty::Field(_, _) => candidates.vec.push(BuiltinCandidate),
1487+
_ => {}
1488+
}
1489+
}
14421490
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![allow(incomplete_features)]
2+
#![feature(field_projections)]
3+
4+
use std::field::{Field, field_of};
5+
6+
#[repr(packed)]
7+
pub struct MyStruct(usize);
8+
9+
fn assert_field<F: Field>() {}
10+
11+
fn main() {
12+
assert_field::<field_of!(MyStruct, 0)>(); //~ ERROR: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied [E0277]
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied
2+
--> $DIR/not-field-if-packed.rs:12:20
3+
|
4+
LL | assert_field::<field_of!(MyStruct, 0)>();
5+
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Field` is not implemented for `field_of!(MyStruct, 0)`
6+
|
7+
note: required by a bound in `assert_field`
8+
--> $DIR/not-field-if-packed.rs:9:20
9+
|
10+
LL | fn assert_field<F: Field>() {}
11+
| ^^^^^ required by this bound in `assert_field`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)