Auto merge of #133570 - adetaylor:receiver_trait_with_target_for_real… · rust-lang/rust@2277c63 (original) (raw)

`@@ -18,7 +18,6 @@ pub enum AutoderefKind {

`

18

18

`` /// A type which must dispatch to a Deref implementation.

``

19

19

`Overloaded,

`

20

20

`}

`

21

``

-

22

21

`struct AutoderefSnapshot<'tcx> {

`

23

22

`at_start: bool,

`

24

23

`reached_recursion_limit: bool,

`

`@@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> {

`

27

26

`obligations: PredicateObligations<'tcx>,

`

28

27

`}

`

29

28

``

``

29

`+

/// Recursively dereference a type, considering both built-in

`

``

30

`` +

/// dereferences (*) and the Deref trait.

``

``

31

`` +

/// Although called Autoderef it can be configured to use the

``

``

32

`` +

/// Receiver trait instead of the Deref trait.

``

30

33

`pub struct Autoderef<'a, 'tcx> {

`

31

34

`// Meta infos:

`

32

35

`infcx: &'a InferCtxt<'tcx>,

`

`@@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> {

`

39

42

``

40

43

`// Configurations:

`

41

44

`include_raw_pointers: bool,

`

``

45

`+

use_receiver_trait: bool,

`

42

46

`silence_errors: bool,

`

43

47

`}

`

44

48

``

`@@ -69,6 +73,10 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {

`

69

73

`}

`

70

74

``

71

75

`// Otherwise, deref if type is derefable:

`

``

76

`+

// NOTE: in the case of self.use_receiver_trait = true, you might think it would

`

``

77

`+

// be better to skip this clause and use the Overloaded case only, since &T

`

``

78

`+

// and &mut T implement Receiver. But built-in derefs apply equally to Receiver

`

``

79

`+

// and Deref, and this has benefits for const and the emitted MIR.

`

72

80

`let (kind, new_ty) =

`

73

81

`if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {

`

74

82

`debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));

`

`@@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

`

111

119

`body_def_id: LocalDefId,

`

112

120

`span: Span,

`

113

121

`base_ty: Ty<'tcx>,

`

114

``

`-

) -> Autoderef<'a, 'tcx> {

`

``

122

`+

) -> Self {

`

115

123

`Autoderef {

`

116

124

` infcx,

`

117

125

` span,

`

`@@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

`

125

133

`reached_recursion_limit: false,

`

126

134

`},

`

127

135

`include_raw_pointers: false,

`

``

136

`+

use_receiver_trait: false,

`

128

137

`silence_errors: false,

`

129

138

`}

`

130

139

`}

`

`@@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

`

137

146

`return None;

`

138

147

`}

`

139

148

``

140

``

`-

//

`

141

``

`-

let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);

`

``

149

`+

// , or whatever the equivalent trait is that we've been asked to walk.

`

``

150

`+

let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait {

`

``

151

`+

(tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?)

`

``

152

`+

} else {

`

``

153

`+

(tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?)

`

``

154

`+

};

`

``

155

`+

let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);

`

142

156

`let cause = traits::ObligationCause::misc(self.span, self.body_id);

`

143

157

`let obligation = traits::Obligation::new(

`

144

158

` tcx,

`

`@@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

`

151

165

`return None;

`

152

166

`}

`

153

167

``

154

``

`-

let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(

`

155

``

`-

tcx,

`

156

``

`-

tcx.lang_items().deref_target()?,

`

157

``

`-

[ty],

`

158

``

`-

))?;

`

``

168

`+

let (normalized_ty, obligations) =

`

``

169

`+

self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;

`

159

170

`debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);

`

160

171

`self.state.obligations.extend(obligations);

`

161

172

``

`@@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

`

234

245

`self

`

235

246

`}

`

236

247

``

``

248

`` +

/// Use core::ops::Receiver and core::ops::Receiver::Target as

``

``

249

`+

/// the trait and associated type to iterate, instead of

`

``

250

`` +

/// core::ops::Deref and core::ops::Deref::Target

``

``

251

`+

pub fn use_receiver_trait(mut self) -> Self {

`

``

252

`+

self.use_receiver_trait = true;

`

``

253

`+

self

`

``

254

`+

}

`

``

255

+

237

256

`pub fn silence_errors(mut self) -> Self {

`

238

257

`self.silence_errors = true;

`

239

258

`self

`