Skip to content

Commit 9cb805e

Browse files
Instantiate binder for Copy/Clone/Sized eagerly
1 parent f2d8d79 commit 9cb805e

File tree

3 files changed

+221
-196
lines changed

3 files changed

+221
-196
lines changed

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

Lines changed: 148 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::{bug, span_bug};
1919
use tracing::{debug, instrument, trace};
2020

2121
use super::SelectionCandidate::*;
22-
use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
22+
use super::{SelectionCandidateSet, SelectionContext, TraitObligationStack};
2323
use crate::traits::util;
2424

2525
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
@@ -75,8 +75,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
7575
self.assemble_candidates_from_impls(obligation, &mut candidates);
7676

7777
// For other types, we'll use the builtin rules.
78-
let copy_conditions = self.copy_clone_conditions(obligation);
79-
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
78+
self.assemble_builtin_copy_clone_candidate(
79+
obligation.predicate.self_ty().skip_binder(),
80+
&mut candidates,
81+
);
8082
}
8183
Some(LangItem::DiscriminantKind) => {
8284
// `DiscriminantKind` is automatically implemented for every type.
@@ -88,14 +90,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
8890
}
8991
Some(LangItem::Sized) => {
9092
self.assemble_builtin_sized_candidate(
91-
obligation,
93+
obligation.predicate.self_ty().skip_binder(),
9294
&mut candidates,
9395
SizedTraitKind::Sized,
9496
);
9597
}
9698
Some(LangItem::MetaSized) => {
9799
self.assemble_builtin_sized_candidate(
98-
obligation,
100+
obligation.predicate.self_ty().skip_binder(),
99101
&mut candidates,
100102
SizedTraitKind::MetaSized,
101103
);
@@ -357,14 +359,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
357359
obligation: &PolyTraitObligation<'tcx>,
358360
candidates: &mut SelectionCandidateSet<'tcx>,
359361
) {
360-
let self_ty = obligation.self_ty().skip_binder();
361-
// gen constructs get lowered to a special kind of coroutine that
362-
// should directly `impl FusedIterator`.
363-
if let ty::Coroutine(did, ..) = self_ty.kind()
364-
&& self.tcx().coroutine_is_gen(*did)
365-
{
366-
debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
367-
362+
if self.coroutine_is_gen(obligation.self_ty().skip_binder()) {
368363
candidates.vec.push(BuiltinCandidate);
369364
}
370365
}
@@ -1113,41 +1108,163 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11131108
}
11141109
}
11151110

1116-
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
1111+
/// Assembles `Copy` and `Clone` candidates for built-in types with no libcore-defined
1112+
/// `Copy` or `Clone` impls.
11171113
#[instrument(level = "debug", skip(self, candidates))]
1118-
fn assemble_builtin_sized_candidate(
1114+
fn assemble_builtin_copy_clone_candidate(
11191115
&mut self,
1120-
obligation: &PolyTraitObligation<'tcx>,
1116+
self_ty: Ty<'tcx>,
11211117
candidates: &mut SelectionCandidateSet<'tcx>,
1122-
sizedness: SizedTraitKind,
11231118
) {
1124-
match self.sizedness_conditions(obligation, sizedness) {
1125-
BuiltinImplConditions::Where(_nested) => {
1126-
candidates.vec.push(SizedCandidate);
1119+
match *self_ty.kind() {
1120+
// These impls exist because we cannot express sufficiently
1121+
// generic impls in libcore.
1122+
ty::FnDef(..)
1123+
| ty::FnPtr(..)
1124+
| ty::Error(_)
1125+
| ty::Tuple(..)
1126+
| ty::CoroutineWitness(..)
1127+
| ty::Pat(..) => {
1128+
candidates.vec.push(BuiltinCandidate);
1129+
}
1130+
1131+
// Implementations provided in libcore.
1132+
ty::Uint(_)
1133+
| ty::Int(_)
1134+
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1135+
| ty::Bool
1136+
| ty::Float(_)
1137+
| ty::Char
1138+
| ty::RawPtr(..)
1139+
| ty::Never
1140+
| ty::Ref(_, _, hir::Mutability::Not)
1141+
| ty::Array(..) => {}
1142+
1143+
// FIXME(unsafe_binder): Should we conditionally
1144+
// (i.e. universally) implement copy/clone?
1145+
ty::UnsafeBinder(_) => {}
1146+
1147+
// Not `Sized`, which is a supertrait of `Copy`/`Clone`.
1148+
ty::Dynamic(..)
1149+
| ty::Str
1150+
| ty::Slice(..)
1151+
| ty::Foreign(..)
1152+
| ty::Ref(_, _, hir::Mutability::Mut) => {}
1153+
1154+
ty::Coroutine(coroutine_def_id, args) => {
1155+
match self.tcx().coroutine_movability(coroutine_def_id) {
1156+
hir::Movability::Static => {}
1157+
hir::Movability::Movable => {
1158+
if self.tcx().features().coroutine_clone() {
1159+
let resolved_upvars =
1160+
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
1161+
let resolved_witness =
1162+
self.infcx.shallow_resolve(args.as_coroutine().witness());
1163+
if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
1164+
// Not yet resolved.
1165+
candidates.ambiguous = true;
1166+
} else {
1167+
candidates.vec.push(BuiltinCandidate);
1168+
}
1169+
}
1170+
}
1171+
}
11271172
}
1128-
BuiltinImplConditions::None => {}
1129-
BuiltinImplConditions::Ambiguous => {
1173+
1174+
ty::Closure(_, args) => {
1175+
let resolved_upvars =
1176+
self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
1177+
if resolved_upvars.is_ty_var() {
1178+
// Not yet resolved.
1179+
candidates.ambiguous = true;
1180+
} else {
1181+
candidates.vec.push(BuiltinCandidate);
1182+
}
1183+
}
1184+
1185+
ty::CoroutineClosure(_, args) => {
1186+
let resolved_upvars =
1187+
self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
1188+
if resolved_upvars.is_ty_var() {
1189+
// Not yet resolved.
1190+
candidates.ambiguous = true;
1191+
} else {
1192+
candidates.vec.push(BuiltinCandidate);
1193+
}
1194+
}
1195+
1196+
// Fallback to whatever user-defined impls or param-env clauses exist in this case.
1197+
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {}
1198+
1199+
ty::Infer(ty::TyVar(_)) => {
11301200
candidates.ambiguous = true;
11311201
}
1202+
1203+
ty::Bound(..) => {}
1204+
1205+
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1206+
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1207+
}
11321208
}
11331209
}
11341210

1135-
/// Assembles the trait which are built-in to the language itself:
1136-
/// e.g. `Copy` and `Clone`.
1211+
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
11371212
#[instrument(level = "debug", skip(self, candidates))]
1138-
fn assemble_builtin_bound_candidates(
1213+
fn assemble_builtin_sized_candidate(
11391214
&mut self,
1140-
conditions: BuiltinImplConditions<'tcx>,
1215+
self_ty: Ty<'tcx>,
11411216
candidates: &mut SelectionCandidateSet<'tcx>,
1217+
sizedness: SizedTraitKind,
11421218
) {
1143-
match conditions {
1144-
BuiltinImplConditions::Where(_) => {
1145-
candidates.vec.push(BuiltinCandidate);
1219+
match *self_ty.kind() {
1220+
// Always sized.
1221+
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1222+
| ty::Uint(_)
1223+
| ty::Int(_)
1224+
| ty::Bool
1225+
| ty::Float(_)
1226+
| ty::FnDef(..)
1227+
| ty::FnPtr(..)
1228+
| ty::RawPtr(..)
1229+
| ty::Char
1230+
| ty::Ref(..)
1231+
| ty::Coroutine(..)
1232+
| ty::CoroutineWitness(..)
1233+
| ty::Array(..)
1234+
| ty::Closure(..)
1235+
| ty::CoroutineClosure(..)
1236+
| ty::Never
1237+
| ty::Error(_) => {
1238+
candidates.vec.push(SizedCandidate);
1239+
}
1240+
1241+
// Conditionally `Sized`.
1242+
ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
1243+
candidates.vec.push(SizedCandidate);
11461244
}
1147-
BuiltinImplConditions::None => {}
1148-
BuiltinImplConditions::Ambiguous => {
1245+
1246+
// `MetaSized` but not `Sized`.
1247+
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
1248+
SizedTraitKind::Sized => {}
1249+
SizedTraitKind::MetaSized => {
1250+
candidates.vec.push(SizedCandidate);
1251+
}
1252+
},
1253+
1254+
// Not `MetaSized` or `Sized`.
1255+
ty::Foreign(..) => {}
1256+
1257+
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => {}
1258+
1259+
ty::Infer(ty::TyVar(_)) => {
11491260
candidates.ambiguous = true;
11501261
}
1262+
1263+
ty::Bound(..) => {}
1264+
1265+
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1266+
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1267+
}
11511268
}
11521269
}
11531270

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use thin_vec::thin_vec;
2121
use tracing::{debug, instrument};
2222

2323
use super::SelectionCandidate::{self, *};
24-
use super::{BuiltinImplConditions, PredicateObligations, SelectionContext};
24+
use super::{PredicateObligations, SelectionContext};
2525
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
2626
use crate::traits::util::{self, closure_trait_ref_and_return_type};
2727
use crate::traits::{
@@ -257,29 +257,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
257257
debug!(?obligation, "confirm_builtin_candidate");
258258
let tcx = self.tcx();
259259
let trait_def = obligation.predicate.def_id();
260-
let conditions = match tcx.as_lang_item(trait_def) {
261-
Some(LangItem::Sized) => self.sizedness_conditions(obligation, SizedTraitKind::Sized),
260+
let self_ty = self.infcx.shallow_resolve(
261+
self.infcx.enter_forall_and_leak_universe(obligation.predicate.self_ty()),
262+
);
263+
let types = match tcx.as_lang_item(trait_def) {
264+
Some(LangItem::Sized) => self.sizedness_conditions(self_ty, SizedTraitKind::Sized),
262265
Some(LangItem::MetaSized) => {
263-
self.sizedness_conditions(obligation, SizedTraitKind::MetaSized)
266+
self.sizedness_conditions(self_ty, SizedTraitKind::MetaSized)
264267
}
265268
Some(LangItem::PointeeSized) => {
266269
bug!("`PointeeSized` is removing during lowering");
267270
}
268-
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
269-
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
271+
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(self_ty),
272+
Some(LangItem::FusedIterator) => {
273+
if self.coroutine_is_gen(self_ty) {
274+
ty::Binder::dummy(vec![])
275+
} else {
276+
unreachable!("tried to assemble `FusedIterator` for non-gen coroutine");
277+
}
278+
}
270279
Some(
271280
LangItem::Destruct
272281
| LangItem::DiscriminantKind
273282
| LangItem::FnPtrTrait
274283
| LangItem::PointeeTrait
275284
| LangItem::Tuple
276285
| LangItem::Unpin,
277-
) => BuiltinImplConditions::Where(ty::Binder::dummy(vec![])),
286+
) => ty::Binder::dummy(vec![]),
278287
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),
279288
};
280-
let BuiltinImplConditions::Where(types) = conditions else {
281-
bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
282-
};
283289
let types = self.infcx.enter_forall_and_leak_universe(types);
284290

285291
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);

0 commit comments

Comments
 (0)