Skip to content

Commit d0e4c67

Browse files
Built-in implementation of Tuple trait
1 parent 6b2eab2 commit d0e4c67

File tree

8 files changed

+72
-8
lines changed

8 files changed

+72
-8
lines changed

compiler/rustc_middle/src/traits/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,10 @@ pub enum ImplSource<'tcx, N> {
634634

635635
/// ImplSource for a `const Drop` implementation.
636636
ConstDestruct(ImplSourceConstDestructData<N>),
637+
638+
/// ImplSource for a `std::marker::Tuple` implementation.
639+
/// This has no nested predicates ever, so no data.
640+
Tuple,
637641
}
638642

639643
impl<'tcx, N> ImplSource<'tcx, N> {
@@ -648,7 +652,8 @@ impl<'tcx, N> ImplSource<'tcx, N> {
648652
ImplSource::Object(d) => d.nested,
649653
ImplSource::FnPointer(d) => d.nested,
650654
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
651-
| ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
655+
| ImplSource::Pointee(ImplSourcePointeeData)
656+
| ImplSource::Tuple => Vec::new(),
652657
ImplSource::TraitAlias(d) => d.nested,
653658
ImplSource::TraitUpcasting(d) => d.nested,
654659
ImplSource::ConstDestruct(i) => i.nested,
@@ -666,7 +671,8 @@ impl<'tcx, N> ImplSource<'tcx, N> {
666671
ImplSource::Object(d) => &d.nested,
667672
ImplSource::FnPointer(d) => &d.nested,
668673
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
669-
| ImplSource::Pointee(ImplSourcePointeeData) => &[],
674+
| ImplSource::Pointee(ImplSourcePointeeData)
675+
| ImplSource::Tuple => &[],
670676
ImplSource::TraitAlias(d) => &d.nested,
671677
ImplSource::TraitUpcasting(d) => &d.nested,
672678
ImplSource::ConstDestruct(i) => &i.nested,
@@ -733,6 +739,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
733739
nested: i.nested.into_iter().map(f).collect(),
734740
})
735741
}
742+
ImplSource::Tuple => ImplSource::Tuple,
736743
}
737744
}
738745
}

compiler/rustc_middle/src/traits/select.rs

+3
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ pub enum SelectionCandidate<'tcx> {
160160

161161
/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
162162
ConstDestructCandidate(Option<DefId>),
163+
164+
/// Witnesses the fact that a type is a tuple.
165+
TupleCandidate,
163166
}
164167

165168
/// The result of trait evaluation. The order is important

compiler/rustc_middle/src/traits/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
3434
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
3535

3636
super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d),
37+
38+
super::ImplSource::Tuple => write!(f, "ImplSource::Tuple"),
3739
}
3840
}
3941
}

compiler/rustc_trait_selection/src/traits/project.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
16251625
super::ImplSource::AutoImpl(..)
16261626
| super::ImplSource::Builtin(..)
16271627
| super::ImplSource::TraitUpcasting(_)
1628-
| super::ImplSource::ConstDestruct(_) => {
1628+
| super::ImplSource::ConstDestruct(_)
1629+
| super::ImplSource::Tuple => {
16291630
// These traits have no associated types.
16301631
selcx.tcx().sess.delay_span_bug(
16311632
obligation.cause.span,
@@ -1700,7 +1701,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
17001701
| super::ImplSource::Builtin(..)
17011702
| super::ImplSource::TraitUpcasting(_)
17021703
| super::ImplSource::TraitAlias(..)
1703-
| super::ImplSource::ConstDestruct(_) => {
1704+
| super::ImplSource::ConstDestruct(_)
1705+
| super::ImplSource::Tuple => {
17041706
// we don't create Select candidates with this kind of resolution
17051707
span_bug!(
17061708
obligation.cause.span,

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

+44
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
309309
// User-defined transmutability impls are permitted.
310310
self.assemble_candidates_from_impls(obligation, &mut candidates);
311311
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
312+
} else if lang_items.tuple_trait() == Some(def_id) {
313+
self.assemble_candidate_for_tuple(obligation, &mut candidates);
312314
} else {
313315
if lang_items.clone_trait() == Some(def_id) {
314316
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -1009,4 +1011,46 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10091011
}
10101012
}
10111013
}
1014+
1015+
fn assemble_candidate_for_tuple(
1016+
&mut self,
1017+
obligation: &TraitObligation<'tcx>,
1018+
candidates: &mut SelectionCandidateSet<'tcx>,
1019+
) {
1020+
let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder());
1021+
match self_ty.kind() {
1022+
ty::Tuple(_) => {
1023+
candidates.vec.push(TupleCandidate);
1024+
}
1025+
ty::Infer(ty::TyVar(_)) => {
1026+
candidates.ambiguous = true;
1027+
}
1028+
ty::Bool
1029+
| ty::Char
1030+
| ty::Int(_)
1031+
| ty::Uint(_)
1032+
| ty::Float(_)
1033+
| ty::Adt(_, _)
1034+
| ty::Foreign(_)
1035+
| ty::Str
1036+
| ty::Array(_, _)
1037+
| ty::Slice(_)
1038+
| ty::RawPtr(_)
1039+
| ty::Ref(_, _, _)
1040+
| ty::FnDef(_, _)
1041+
| ty::FnPtr(_)
1042+
| ty::Dynamic(_, _)
1043+
| ty::Closure(_, _)
1044+
| ty::Generator(_, _, _)
1045+
| ty::GeneratorWitness(_)
1046+
| ty::Never
1047+
| ty::Projection(_)
1048+
| ty::Opaque(_, _)
1049+
| ty::Param(_)
1050+
| ty::Bound(_, _)
1051+
| ty::Error(_)
1052+
| ty::Infer(_)
1053+
| ty::Placeholder(_) => {}
1054+
}
1055+
}
10121056
}

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

+2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
126126
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
127127
ImplSource::ConstDestruct(data)
128128
}
129+
130+
TupleCandidate => ImplSource::Tuple,
129131
};
130132

131133
if !obligation.predicate.is_const_if_const() {

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16181618
};
16191619

16201620
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
1621-
// `DiscriminantKindCandidate`, and `ConstDestructCandidate` to anything else.
1621+
// `DiscriminantKindCandidate`, `ConstDestructCandidate`, and `TupleCandidate`
1622+
// to anything else.
16221623
//
16231624
// This is a fix for #53123 and prevents winnowing from accidentally extending the
16241625
// lifetime of a variable.
@@ -1638,15 +1639,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16381639
BuiltinCandidate { has_nested: false }
16391640
| DiscriminantKindCandidate
16401641
| PointeeCandidate
1641-
| ConstDestructCandidate(_),
1642+
| ConstDestructCandidate(_)
1643+
| TupleCandidate,
16421644
_,
16431645
) => true,
16441646
(
16451647
_,
16461648
BuiltinCandidate { has_nested: false }
16471649
| DiscriminantKindCandidate
16481650
| PointeeCandidate
1649-
| ConstDestructCandidate(_),
1651+
| ConstDestructCandidate(_)
1652+
| TupleCandidate,
16501653
) => false,
16511654

16521655
(ParamCandidate(other), ParamCandidate(victim)) => {

compiler/rustc_ty_utils/src/instance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,8 @@ fn resolve_associated_item<'tcx>(
397397
| traits::ImplSource::DiscriminantKind(..)
398398
| traits::ImplSource::Pointee(..)
399399
| traits::ImplSource::TraitUpcasting(_)
400-
| traits::ImplSource::ConstDestruct(_) => None,
400+
| traits::ImplSource::ConstDestruct(_)
401+
| traits::ImplSource::Tuple => None,
401402
})
402403
}
403404

0 commit comments

Comments
 (0)