Skip to content

Commit da2cf9b

Browse files
committed
substitutions in trait predicates
1 parent 760a665 commit da2cf9b

File tree

1 file changed

+104
-62
lines changed
  • compiler/rustc_typeck/src/astconv

1 file changed

+104
-62
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

+104-62
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,15 @@ pub enum SizedByDefault {
112112
No,
113113
}
114114

115+
#[derive(Debug)]
115116
struct ConvertedBinding<'a, 'tcx> {
116117
item_name: Ident,
117118
kind: ConvertedBindingKind<'a, 'tcx>,
119+
gen_args: &'a GenericArgs<'a>,
118120
span: Span,
119121
}
120122

123+
#[derive(Debug)]
121124
enum ConvertedBindingKind<'a, 'tcx> {
122125
Equality(Ty<'tcx>),
123126
Constraint(&'a [hir::GenericBound<'a>]),
@@ -323,6 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
323326

324327
let tcx = self.tcx();
325328
let generics = tcx.generics_of(def_id);
329+
debug!("generics: {:?}", generics);
326330

327331
if generics.has_self {
328332
if generics.parent.is_some() {
@@ -557,7 +561,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
557561
ConvertedBindingKind::Constraint(bounds)
558562
}
559563
};
560-
ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
564+
ConvertedBinding {
565+
item_name: binding.ident,
566+
kind,
567+
gen_args: binding.gen_args,
568+
span: binding.span,
569+
}
561570
})
562571
.collect();
563572

@@ -918,60 +927,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
918927
dup_bindings: &mut FxHashMap<DefId, Span>,
919928
path_span: Span,
920929
) -> Result<(), ErrorReported> {
921-
let tcx = self.tcx();
922-
923-
if !speculative {
924-
// Given something like `U: SomeTrait<T = X>`, we want to produce a
925-
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
926-
// subtle in the event that `T` is defined in a supertrait of
927-
// `SomeTrait`, because in that case we need to upcast.
928-
//
929-
// That is, consider this case:
930-
//
931-
// ```
932-
// trait SubTrait: SuperTrait<i32> { }
933-
// trait SuperTrait<A> { type T; }
934-
//
935-
// ... B: SubTrait<T = foo> ...
936-
// ```
937-
//
938-
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
939-
940-
// Find any late-bound regions declared in `ty` that are not
941-
// declared in the trait-ref. These are not well-formed.
942-
//
943-
// Example:
944-
//
945-
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
946-
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
947-
if let ConvertedBindingKind::Equality(ty) = binding.kind {
948-
let late_bound_in_trait_ref =
949-
tcx.collect_constrained_late_bound_regions(&trait_ref);
950-
let late_bound_in_ty =
951-
tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
952-
debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
953-
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
930+
// Given something like `U: SomeTrait<T = X>`, we want to produce a
931+
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
932+
// subtle in the event that `T` is defined in a supertrait of
933+
// `SomeTrait`, because in that case we need to upcast.
934+
//
935+
// That is, consider this case:
936+
//
937+
// ```
938+
// trait SubTrait: SuperTrait<i32> { }
939+
// trait SuperTrait<A> { type T; }
940+
//
941+
// ... B: SubTrait<T = foo> ...
942+
// ```
943+
//
944+
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
954945

955-
// FIXME: point at the type params that don't have appropriate lifetimes:
956-
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
957-
// ---- ---- ^^^^^^^
958-
self.validate_late_bound_regions(
959-
late_bound_in_trait_ref,
960-
late_bound_in_ty,
961-
|br_name| {
962-
struct_span_err!(
963-
tcx.sess,
964-
binding.span,
965-
E0582,
966-
"binding for associated type `{}` references {}, \
967-
which does not appear in the trait input types",
968-
binding.item_name,
969-
br_name
970-
)
971-
},
972-
);
973-
}
974-
}
946+
debug!(
947+
"add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}",
948+
hir_ref_id, trait_ref, binding, bounds
949+
);
950+
let tcx = self.tcx();
975951

976952
let candidate =
977953
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
@@ -1030,20 +1006,85 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10301006
.or_insert(binding.span);
10311007
}
10321008

1009+
// Include substitutions for generic parameters of associated types
1010+
let projection_ty = candidate.map_bound(|trait_ref| {
1011+
let item_segment = hir::PathSegment {
1012+
ident: assoc_ty.ident,
1013+
hir_id: None,
1014+
res: None,
1015+
args: Some(binding.gen_args),
1016+
infer_args: false,
1017+
};
1018+
1019+
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
1020+
tcx,
1021+
path_span,
1022+
assoc_ty.def_id,
1023+
&item_segment,
1024+
trait_ref.substs,
1025+
);
1026+
1027+
debug!(
1028+
"add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
1029+
substs_trait_ref_and_assoc_item
1030+
);
1031+
1032+
ty::ProjectionTy {
1033+
item_def_id: assoc_ty.def_id,
1034+
substs: substs_trait_ref_and_assoc_item,
1035+
}
1036+
});
1037+
1038+
if !speculative {
1039+
// Find any late-bound regions declared in `ty` that are not
1040+
// declared in the trait-ref or assoc_ty. These are not well-formed.
1041+
//
1042+
// Example:
1043+
//
1044+
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
1045+
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
1046+
if let ConvertedBindingKind::Equality(ty) = binding.kind {
1047+
let late_bound_in_trait_ref =
1048+
tcx.collect_constrained_late_bound_regions(&projection_ty);
1049+
let late_bound_in_ty =
1050+
tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
1051+
debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
1052+
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
1053+
1054+
// FIXME: point at the type params that don't have appropriate lifetimes:
1055+
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
1056+
// ---- ---- ^^^^^^^
1057+
self.validate_late_bound_regions(
1058+
late_bound_in_trait_ref,
1059+
late_bound_in_ty,
1060+
|br_name| {
1061+
struct_span_err!(
1062+
tcx.sess,
1063+
binding.span,
1064+
E0582,
1065+
"binding for associated type `{}` references {}, \
1066+
which does not appear in the trait input types",
1067+
binding.item_name,
1068+
br_name
1069+
)
1070+
},
1071+
);
1072+
}
1073+
}
1074+
10331075
match binding.kind {
10341076
ConvertedBindingKind::Equality(ref ty) => {
10351077
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
10361078
// the "projection predicate" for:
10371079
//
10381080
// `<T as Iterator>::Item = u32`
10391081
bounds.projection_bounds.push((
1040-
candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
1041-
projection_ty: ty::ProjectionTy::from_ref_and_name(
1042-
tcx,
1043-
trait_ref,
1044-
binding.item_name,
1045-
),
1046-
ty,
1082+
projection_ty.map_bound(|projection_ty| {
1083+
debug!(
1084+
"add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}",
1085+
projection_ty, projection_ty.substs
1086+
);
1087+
ty::ProjectionPredicate { projection_ty, ty }
10471088
}),
10481089
binding.span,
10491090
));
@@ -1055,7 +1096,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10551096
//
10561097
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
10571098
// parameter to have a skipped binder.
1058-
let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
1099+
let param_ty =
1100+
tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
10591101
self.add_bounds(param_ty, ast_bounds, bounds);
10601102
}
10611103
}

0 commit comments

Comments
 (0)