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

`