Skip to content

Commit 18fd892

Browse files
Auto merge of #143538 - compiler-errors:instantiate-auto-trait, r=<try>
Instantiate auto trait before computing higher-ranked constituent types This makes the binder logic w.r.t. auto traits and coroutines a bit simpler. r? lcnr
2 parents 2f8eeb2 + 9cb805e commit 18fd892

File tree

4 files changed

+284
-264
lines changed

4 files changed

+284
-264
lines changed

compiler/rustc_middle/src/traits/select.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,15 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>),
9797
pub enum SelectionCandidate<'tcx> {
9898
/// A built-in implementation for the `Sized` trait. This is preferred
9999
/// over all other candidates.
100-
SizedCandidate {
101-
has_nested: bool,
102-
},
100+
SizedCandidate,
103101

104102
/// A builtin implementation for some specific traits, used in cases
105103
/// where we cannot rely an ordinary library implementations.
106104
///
107105
/// The most notable examples are `Copy` and `Clone`. This is also
108106
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
109107
/// an associated type.
110-
BuiltinCandidate {
111-
/// `false` if there are no *further* obligations.
112-
has_nested: bool,
113-
},
108+
BuiltinCandidate,
114109

115110
/// Implementation of transmutability trait.
116111
TransmutabilityCandidate,

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

Lines changed: 155 additions & 42 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,27 +75,29 @@ 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.
83-
candidates.vec.push(BuiltinCandidate { has_nested: false });
85+
candidates.vec.push(BuiltinCandidate);
8486
}
8587
Some(LangItem::PointeeTrait) => {
8688
// `Pointee` is automatically implemented for every type.
87-
candidates.vec.push(BuiltinCandidate { has_nested: false });
89+
candidates.vec.push(BuiltinCandidate);
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,15 +359,8 @@ 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-
368-
candidates.vec.push(BuiltinCandidate { has_nested: false });
362+
if self.coroutine_is_gen(obligation.self_ty().skip_binder()) {
363+
candidates.vec.push(BuiltinCandidate);
369364
}
370365
}
371366

@@ -810,7 +805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
810805
hir::Movability::Movable => {
811806
// Movable coroutines are always `Unpin`, so add an
812807
// unconditional builtin candidate.
813-
candidates.vec.push(BuiltinCandidate { has_nested: false });
808+
candidates.vec.push(BuiltinCandidate);
814809
}
815810
}
816811
}
@@ -1113,45 +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
1127-
.vec
1128-
.push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
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+
}
1172+
}
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+
}
11291183
}
1130-
BuiltinImplConditions::None => {}
1131-
BuiltinImplConditions::Ambiguous => {
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(_)) => {
11321200
candidates.ambiguous = true;
11331201
}
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+
}
11341208
}
11351209
}
11361210

1137-
/// Assembles the trait which are built-in to the language itself:
1138-
/// e.g. `Copy` and `Clone`.
1211+
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
11391212
#[instrument(level = "debug", skip(self, candidates))]
1140-
fn assemble_builtin_bound_candidates(
1213+
fn assemble_builtin_sized_candidate(
11411214
&mut self,
1142-
conditions: BuiltinImplConditions<'tcx>,
1215+
self_ty: Ty<'tcx>,
11431216
candidates: &mut SelectionCandidateSet<'tcx>,
1217+
sizedness: SizedTraitKind,
11441218
) {
1145-
match conditions {
1146-
BuiltinImplConditions::Where(nested) => {
1147-
candidates
1148-
.vec
1149-
.push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
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);
11501244
}
1151-
BuiltinImplConditions::None => {}
1152-
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(_)) => {
11531260
candidates.ambiguous = true;
11541261
}
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+
}
11551268
}
11561269
}
11571270

@@ -1160,7 +1273,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11601273
_obligation: &PolyTraitObligation<'tcx>,
11611274
candidates: &mut SelectionCandidateSet<'tcx>,
11621275
) {
1163-
candidates.vec.push(BuiltinCandidate { has_nested: false });
1276+
candidates.vec.push(BuiltinCandidate);
11641277
}
11651278

11661279
fn assemble_candidate_for_tuple(
@@ -1171,7 +1284,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11711284
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
11721285
match self_ty.kind() {
11731286
ty::Tuple(_) => {
1174-
candidates.vec.push(BuiltinCandidate { has_nested: false });
1287+
candidates.vec.push(BuiltinCandidate);
11751288
}
11761289
ty::Infer(ty::TyVar(_)) => {
11771290
candidates.ambiguous = true;
@@ -1215,7 +1328,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12151328
let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
12161329

12171330
match self_ty.skip_binder().kind() {
1218-
ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
1331+
ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate),
12191332
ty::Bool
12201333
| ty::Char
12211334
| ty::Int(_)

0 commit comments

Comments
 (0)