Skip to content

Commit 02ee18f

Browse files
Add TyKind::TyAlias support in rustc_trait_selection
1 parent 71357dc commit 02ee18f

File tree

11 files changed

+311
-60
lines changed

11 files changed

+311
-60
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,8 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
735735
// that they implement, so we don't use this behavior.
736736
self.found_non_local_ty(ty)
737737
}
738+
739+
ty::TyAlias(..) => self.visit_ty(self.tcx.peel_off_ty_alias(ty)),
738740
};
739741
// A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
740742
// the first type we visit is always the self type.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
17521752
ty::Generator(..) => Some(16),
17531753
ty::Foreign(..) => Some(17),
17541754
ty::GeneratorWitness(..) => Some(18),
1755+
ty::TyAlias(..) => Some(19),
17551756
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
17561757
}
17571758
}

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
153153
infcx.tcx.def_path_str(def_id)
154154
);
155155

156+
let ty = infcx.tcx.peel_off_ty_alias(ty);
157+
156158
let trait_ref =
157159
ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) });
158160
let obligation = Obligation {

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rustc_hir::lang_items::LangItem;
3030
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
3131
use rustc_middle::traits::select::OverflowError;
3232
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
33+
use rustc_middle::ty::subst::{Subst, SubstsRef};
3334
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
3435
use rustc_middle::ty::DefIdTree;
3536
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
@@ -459,6 +460,23 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
459460
value.fold_with(self)
460461
}
461462
}
463+
464+
fn fold_reveal(&mut self, ty: Ty<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
465+
let recursion_limit = self.tcx().recursion_limit();
466+
if !recursion_limit.value_within_limit(self.depth) {
467+
let obligation =
468+
Obligation::with_depth(self.cause.clone(), recursion_limit.0, self.param_env, ty);
469+
self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true);
470+
}
471+
472+
let substs = substs.fold_with(self);
473+
let generic_ty = self.tcx().bound_type_of(def_id);
474+
let concrete_ty = generic_ty.subst(self.tcx(), substs);
475+
self.depth += 1;
476+
let folded_ty = self.fold_ty(concrete_ty);
477+
self.depth -= 1;
478+
folded_ty
479+
}
462480
}
463481

464482
impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
@@ -512,30 +530,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
512530
// Only normalize `impl Trait` outside of type inference, usually in codegen.
513531
match self.param_env.reveal() {
514532
Reveal::UserFacing => ty.super_fold_with(self),
515-
516-
Reveal::All => {
517-
let recursion_limit = self.tcx().recursion_limit();
518-
if !recursion_limit.value_within_limit(self.depth) {
519-
let obligation = Obligation::with_depth(
520-
self.cause.clone(),
521-
recursion_limit.0,
522-
self.param_env,
523-
ty,
524-
);
525-
self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true);
526-
}
527-
528-
let substs = substs.fold_with(self);
529-
let generic_ty = self.tcx().bound_type_of(def_id);
530-
let concrete_ty = generic_ty.subst(self.tcx(), substs);
531-
self.depth += 1;
532-
let folded_ty = self.fold_ty(concrete_ty);
533-
self.depth -= 1;
534-
folded_ty
535-
}
533+
Reveal::All => self.fold_reveal(ty, def_id, substs),
536534
}
537535
}
538536

537+
ty::TyAlias(def_id, substs) => self.fold_reveal(ty, def_id, substs),
538+
539539
ty::Projection(data) if !data.has_escaping_bound_vars() => {
540540
// This branch is *mostly* just an optimization: when we don't
541541
// have escaping bound vars, we don't need to replace them with
@@ -1414,6 +1414,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
14141414
let bounds = match *obligation.predicate.self_ty().kind() {
14151415
ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
14161416
ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
1417+
ty::TyAlias(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
14171418
ty::Infer(ty::TyVar(_)) => {
14181419
// If the self-type is an inference variable, then it MAY wind up
14191420
// being a projected type, so induce an ambiguity.
@@ -1650,6 +1651,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
16501651
| ty::Bound(..)
16511652
| ty::Placeholder(..)
16521653
| ty::Infer(..)
1654+
| ty::TyAlias(..)
16531655
| ty::Error(_) => false,
16541656
}
16551657
}
@@ -1735,6 +1737,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
17351737
}
17361738
false
17371739
}
1740+
1741+
ty::TyAlias(..) => unreachable!(),
17381742
}
17391743
}
17401744
super::ImplSource::Param(..) => {

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
6868
| ty::Placeholder(..)
6969
| ty::Infer(_)
7070
| ty::Bound(..)
71-
| ty::Generator(..) => false,
71+
| ty::Generator(..)
72+
| ty::TyAlias(..) => false,
7273
}
7374
}

compiler/rustc_trait_selection/src/traits/query/normalize.rs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderR
1010
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
1111
use rustc_data_structures::sso::SsoHashMap;
1212
use rustc_data_structures::stack::ensure_sufficient_stack;
13+
use rustc_hir::def_id::DefId;
1314
use rustc_infer::traits::Normalized;
1415
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
16+
use rustc_middle::ty::subst::{Subst, SubstsRef};
1517
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
1618
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
1719
use rustc_span::DUMMY_SP;
@@ -163,6 +165,40 @@ struct QueryNormalizer<'cx, 'tcx> {
163165
universes: Vec<Option<ty::UniverseIndex>>,
164166
}
165167

168+
impl<'cx, 'tcx> QueryNormalizer<'cx, 'tcx> {
169+
fn fold_reveal(
170+
&mut self,
171+
ty: Ty<'tcx>,
172+
def_id: DefId,
173+
substs: SubstsRef<'tcx>,
174+
) -> Result<Ty<'tcx>, <Self as FallibleTypeFolder<'tcx>>::Error> {
175+
let substs = substs.try_fold_with(self)?;
176+
let recursion_limit = self.tcx().recursion_limit();
177+
if !recursion_limit.value_within_limit(self.anon_depth) {
178+
let obligation =
179+
Obligation::with_depth(self.cause.clone(), recursion_limit.0, self.param_env, ty);
180+
self.infcx.err_ctxt().report_overflow_error(&obligation, true);
181+
}
182+
183+
let generic_ty = self.tcx().bound_type_of(def_id);
184+
let concrete_ty = generic_ty.subst(self.tcx(), substs);
185+
self.anon_depth += 1;
186+
if concrete_ty == ty {
187+
bug!(
188+
"infinite recursion generic_ty: {:#?}, substs: {:#?}, \
189+
concrete_ty: {:#?}, ty: {:#?}",
190+
generic_ty,
191+
substs,
192+
concrete_ty,
193+
ty
194+
);
195+
}
196+
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
197+
self.anon_depth -= 1;
198+
folded_ty
199+
}
200+
}
201+
166202
impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
167203
type Error = NoSolution;
168204

@@ -202,40 +238,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
202238
// Only normalize `impl Trait` outside of type inference, usually in codegen.
203239
match self.param_env.reveal() {
204240
Reveal::UserFacing => ty.try_super_fold_with(self),
205-
206-
Reveal::All => {
207-
let substs = substs.try_fold_with(self)?;
208-
let recursion_limit = self.tcx().recursion_limit();
209-
if !recursion_limit.value_within_limit(self.anon_depth) {
210-
let obligation = Obligation::with_depth(
211-
self.cause.clone(),
212-
recursion_limit.0,
213-
self.param_env,
214-
ty,
215-
);
216-
self.infcx.err_ctxt().report_overflow_error(&obligation, true);
217-
}
218-
219-
let generic_ty = self.tcx().bound_type_of(def_id);
220-
let concrete_ty = generic_ty.subst(self.tcx(), substs);
221-
self.anon_depth += 1;
222-
if concrete_ty == ty {
223-
bug!(
224-
"infinite recursion generic_ty: {:#?}, substs: {:#?}, \
225-
concrete_ty: {:#?}, ty: {:#?}",
226-
generic_ty,
227-
substs,
228-
concrete_ty,
229-
ty
230-
);
231-
}
232-
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
233-
self.anon_depth -= 1;
234-
folded_ty
235-
}
241+
Reveal::All => self.fold_reveal(ty, def_id, substs),
236242
}
237243
}
238244

245+
ty::TyAlias(def_id, substs) => self.fold_reveal(ty, def_id, substs),
246+
239247
ty::Projection(data) if !data.has_escaping_bound_vars() => {
240248
// This branch is just an optimization: when we don't have escaping bound vars,
241249
// we don't need to replace them with placeholders (see branch below).

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
959959
| ty::Bound(..)
960960
| ty::Param(_)
961961
| ty::Placeholder(_)
962-
| ty::Projection(_) => {
962+
| ty::Projection(_)
963+
| ty::TyAlias(..) => {
963964
// We don't know if these are `~const Destruct`, at least
964965
// not structurally... so don't push a candidate.
965966
}
@@ -1018,7 +1019,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10181019
obligation: &TraitObligation<'tcx>,
10191020
candidates: &mut SelectionCandidateSet<'tcx>,
10201021
) {
1021-
let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder());
1022+
let infcx = self.infcx();
1023+
let self_ty = infcx.shallow_resolve(obligation.self_ty().skip_binder());
1024+
let self_ty = infcx.tcx.peel_off_ty_alias(self_ty);
10221025
match self_ty.kind() {
10231026
ty::Tuple(_) => {
10241027
candidates.vec.push(BuiltinCandidate { has_nested: false });
@@ -1052,6 +1055,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10521055
| ty::Error(_)
10531056
| ty::Infer(_)
10541057
| ty::Placeholder(_) => {}
1058+
ty::TyAlias(..) => unreachable!(),
10551059
}
10561060
}
10571061
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12491249

12501250
// If we have a projection type, make sure to normalize it so we replace it
12511251
// with a fresh infer variable
1252-
ty::Projection(..) => {
1252+
ty::Projection(..) | ty::TyAlias(..) => {
12531253
let predicate = normalize_with_depth_to(
12541254
self,
12551255
obligation.param_env,

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,7 +1842,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18421842
}))
18431843
}
18441844

1845-
ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
1845+
ty::Projection(_) | ty::Param(_) | ty::Opaque(..) | ty::TyAlias(..) => None,
18461846
ty::Infer(ty::TyVar(_)) => Ambiguous,
18471847

18481848
ty::Placeholder(..)
@@ -1942,7 +1942,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19421942
}
19431943
}
19441944

1945-
ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
1945+
ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) | ty::TyAlias(..) => {
19461946
// Fallback to whatever user-defined impls exist in this case.
19471947
None
19481948
}
@@ -2034,8 +2034,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20342034
t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
20352035
}
20362036

2037-
ty::Opaque(def_id, substs) => {
2038-
// We can resolve the `impl Trait` to its concrete type,
2037+
ty::Opaque(def_id, substs) | ty::TyAlias(def_id, substs) => {
2038+
// We can resolve the `impl Trait` and the type alias to its concrete type,
20392039
// which enforces a DAG between the functions requiring
20402040
// the auto trait bounds in question.
20412041
t.rebind(vec![self.tcx().bound_type_of(def_id).subst(self.tcx(), substs)])

compiler/rustc_trait_selection/src/traits/structural_match.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
209209
}
210210
}
211211

212+
ty::TyAlias(..) => {
213+
// Type aliases are transparent and should never be seen by structural match checking.
214+
bug!("unexpected TyAlias in TypeVisitor::visit_ty");
215+
}
216+
212217
ty::Float(_) => {
213218
if !self.adt_const_param {
214219
return ControlFlow::CONTINUE;

0 commit comments

Comments
 (0)