Check supertraits and gen args when resolving anon consts in assoc co… · rust-lang/rust@4c0addc (original) (raw)
`@@ -8,9 +8,10 @@ use rustc_middle::ty::util::IntTypeExt;
`
8
8
`use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
`
9
9
`use rustc_span::symbol::Ident;
`
10
10
`use rustc_span::{Span, DUMMY_SP};
`
``
11
`+
use rustc_trait_selection::traits;
`
11
12
``
12
``
`-
use super::ItemCtxt;
`
13
13
`use super::{bad_placeholder, is_suggestable_infer_ty};
`
``
14
`+
use super::{AstConv, ItemCtxt};
`
14
15
`pub use opaque::test_opaque_hidden_types;
`
15
16
``
16
17
`mod opaque;
`
`@@ -60,35 +61,78 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
`
60
61
`.expect("const parameter types cannot be generic");
`
61
62
`}
`
62
63
``
63
``
`-
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
`
64
``
`-
if let Node::TraitRef(trait_ref) = tcx.hir().get(tcx.hir().parent_id(binding_id)) =>
`
65
``
`-
{
`
``
64
`+
Node::TypeBinding(
`
``
65
`+
binding @ &TypeBinding { hir_id: binding_id, ident, gen_args, span, .. },
`
``
66
`+
) if let Node::TraitRef(trait_ref) = tcx.hir().get(tcx.hir().parent_id(binding_id)) => {
`
66
67
`let Some(trait_def_id) = trait_ref.trait_def_id() else {
`
67
68
`return Ty::new_error_with_message(
`
68
69
` tcx,
`
69
70
` tcx.def_span(def_id),
`
70
``
`-
"Could not find trait",
`
``
71
`+
"could not find trait",
`
71
72
`);
`
72
73
`};
`
73
``
`-
let assoc_items = tcx.associated_items(trait_def_id);
`
74
``
`-
let assoc_item = assoc_items.find_by_name_and_kind(
`
75
``
`-
tcx,
`
76
``
`-
binding.ident,
`
77
``
`-
ty::AssocKind::Const,
`
78
``
`-
def_id.to_def_id(),
`
``
74
+
``
75
`+
// FIXME(associated_const_equality): We're now performing a full but ad-hoc type-based
`
``
76
`+
// resolution of the associated constant. Doing all this work here isn't great.
`
``
77
`+
// Ideally, we would've computed this already somewhere else (in a query?).
`
``
78
+
``
79
`+
let icx = ItemCtxt::new(tcx, def_id);
`
``
80
`+
let trait_segment = trait_ref.path.segments.last().unwrap();
`
``
81
`+
let (trait_args, _) = icx.astconv().create_args_for_ast_path(
`
``
82
`+
trait_ref.path.span,
`
``
83
`+
trait_def_id,
`
``
84
`+
&[],
`
``
85
`+
trait_segment,
`
``
86
`+
trait_segment.args(),
`
``
87
`+
trait_segment.infer_args,
`
``
88
`+
// FIXME(associated_const_equality): This isn't correct, it should be the concrete /
`
``
89
`+
// instantiated self type. Theoretically, we could search for it in the HIR of the
`
``
90
`+
// parent item but that's super fragile and hairy.
`
``
91
`+
Some(tcx.types.self_param),
`
``
92
`+
ty::BoundConstness::NotConst,
`
79
93
`);
`
80
``
`-
return if let Some(assoc_item) = assoc_item {
`
81
``
`-
tcx.type_of(assoc_item.def_id)
`
82
``
`-
.no_bound_vars()
`
83
``
`-
.expect("const parameter types cannot be generic")
`
84
``
`-
} else {
`
85
``
`-
// FIXME(associated_const_equality): add a useful error message here.
`
86
``
`-
Ty::new_error_with_message(
`
``
94
`+
let trait_ref = ty::Binder::bind_with_vars(
`
``
95
`+
ty::TraitRef::new(tcx, trait_def_id, trait_args),
`
``
96
`+
tcx.late_bound_vars(trait_ref.hir_ref_id),
`
``
97
`+
);
`
``
98
+
``
99
`` +
// We shouldn't need to deal with ambiguity since add_predicates_for_ast_type_binding
``
``
100
`+
// should've already bailed out early in such case.
`
``
101
`+
let Some((assoc_item, parent_args)) =
`
``
102
`+
traits::supertraits(tcx, trait_ref).find_map(|trait_ref| {
`
``
103
`+
tcx.associated_items(trait_ref.def_id())
`
``
104
`+
.find_by_name_and_kind(
`
``
105
`+
tcx,
`
``
106
`+
binding.ident,
`
``
107
`+
ty::AssocKind::Const,
`
``
108
`+
trait_ref.def_id(),
`
``
109
`+
)
`
``
110
`` +
// FIXME(fmease): skip_binder
is fishy!
``
``
111
`+
.map(|item| (item, trait_ref.skip_binder().args))
`
``
112
`+
})
`
``
113
`+
else {
`
``
114
`+
return Ty::new_error_with_message(
`
87
115
` tcx,
`
88
116
` tcx.def_span(def_id),
`
89
``
`-
"Could not find associated const on trait",
`
90
``
`-
)
`
``
117
`+
"could not find associated const on trait",
`
``
118
`+
);
`
91
119
`};
`
``
120
+
``
121
`+
let args = icx.astconv().create_args_for_associated_item(
`
``
122
`+
span,
`
``
123
`+
assoc_item.def_id,
`
``
124
`+
// FIXME(fmease): This is gross as hell!
`
``
125
`+
&hir::PathSegment {
`
``
126
`+
ident,
`
``
127
`+
hir_id,
`
``
128
`+
res: def::Res::Def(def::DefKind::AssocConst, assoc_item.def_id),
`
``
129
`+
args: Some(gen_args),
`
``
130
`+
infer_args: false,
`
``
131
`+
},
`
``
132
`+
parent_args,
`
``
133
`+
);
`
``
134
+
``
135
`+
return tcx.type_of(assoc_item.def_id).instantiate(tcx, args);
`
92
136
`}
`
93
137
``
94
138
`// This match arm is for when the def_id appears in a GAT whose
`
`@@ -120,8 +164,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
`
120
164
`.unwrap()
`
121
165
`.0
`
122
166
`.def_id;
`
123
``
`-
let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>;
`
124
``
`-
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
`
``
167
`+
let ty = ItemCtxt::new(tcx, item_def_id).to_ty(hir_ty);
`
125
168
``
126
169
`// Iterate through the generics of the projection to find the one that corresponds to
`
127
170
`// the def_id that this query was called with. We filter to only type and const args here
`