]>
Commit | Line | Data |
---|---|---|
7cac9316 | 1 | use super::{probe, MethodCallee}; |
1a4d82fc | 2 | |
5869c6ff | 3 | use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; |
f035d41b | 4 | use crate::check::{callee, FnCtxt}; |
dfeec247 | 5 | use rustc_hir as hir; |
5e7ed085 FG |
6 | use rustc_hir::def_id::DefId; |
7 | use rustc_hir::GenericArg; | |
74b04a01 | 8 | use rustc_infer::infer::{self, InferOk}; |
3dfed10e | 9 | use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; |
f035d41b | 10 | use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; |
ba9703b0 XL |
11 | use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; |
12 | use rustc_middle::ty::fold::TypeFoldable; | |
fc512014 | 13 | use rustc_middle::ty::subst::{self, Subst, SubstsRef}; |
ba9703b0 | 14 | use rustc_middle::ty::{self, GenericParamDefKind, Ty}; |
dfeec247 | 15 | use rustc_span::Span; |
ba9703b0 | 16 | use rustc_trait_selection::traits; |
1a4d82fc | 17 | |
cdc7bbd5 | 18 | use std::iter; |
a7813a04 XL |
19 | use std::ops::Deref; |
20 | ||
dc9dc135 XL |
21 | struct ConfirmContext<'a, 'tcx> { |
22 | fcx: &'a FnCtxt<'a, 'tcx>, | |
1a4d82fc | 23 | span: Span, |
dfeec247 XL |
24 | self_expr: &'tcx hir::Expr<'tcx>, |
25 | call_expr: &'tcx hir::Expr<'tcx>, | |
a7813a04 XL |
26 | } |
27 | ||
dc9dc135 XL |
28 | impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { |
29 | type Target = FnCtxt<'a, 'tcx>; | |
a7813a04 | 30 | fn deref(&self) -> &Self::Target { |
c295e0f8 | 31 | self.fcx |
a7813a04 | 32 | } |
1a4d82fc JJ |
33 | } |
34 | ||
5869c6ff | 35 | #[derive(Debug)] |
3b2f2976 XL |
36 | pub struct ConfirmResult<'tcx> { |
37 | pub callee: MethodCallee<'tcx>, | |
74b04a01 | 38 | pub illegal_sized_bound: Option<Span>, |
3b2f2976 XL |
39 | } |
40 | ||
dc9dc135 | 41 | impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
564c78a2 XL |
42 | pub fn confirm_method( |
43 | &self, | |
44 | span: Span, | |
dfeec247 XL |
45 | self_expr: &'tcx hir::Expr<'tcx>, |
46 | call_expr: &'tcx hir::Expr<'tcx>, | |
564c78a2 XL |
47 | unadjusted_self_ty: Ty<'tcx>, |
48 | pick: probe::Pick<'tcx>, | |
dfeec247 | 49 | segment: &hir::PathSegment<'_>, |
564c78a2 XL |
50 | ) -> ConfirmResult<'tcx> { |
51 | debug!( | |
52 | "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", | |
dfeec247 | 53 | unadjusted_self_ty, pick, segment.args, |
564c78a2 | 54 | ); |
a7813a04 XL |
55 | |
56 | let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); | |
041b39d2 | 57 | confirm_cx.confirm(unadjusted_self_ty, pick, segment) |
a7813a04 | 58 | } |
1a4d82fc JJ |
59 | } |
60 | ||
dc9dc135 XL |
61 | impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { |
62 | fn new( | |
63 | fcx: &'a FnCtxt<'a, 'tcx>, | |
64 | span: Span, | |
dfeec247 XL |
65 | self_expr: &'tcx hir::Expr<'tcx>, |
66 | call_expr: &'tcx hir::Expr<'tcx>, | |
dc9dc135 | 67 | ) -> ConfirmContext<'a, 'tcx> { |
dfeec247 | 68 | ConfirmContext { fcx, span, self_expr, call_expr } |
1a4d82fc JJ |
69 | } |
70 | ||
564c78a2 XL |
71 | fn confirm( |
72 | &mut self, | |
73 | unadjusted_self_ty: Ty<'tcx>, | |
74 | pick: probe::Pick<'tcx>, | |
dfeec247 | 75 | segment: &hir::PathSegment<'_>, |
564c78a2 | 76 | ) -> ConfirmResult<'tcx> { |
1a4d82fc | 77 | // Adjust the self expression the user provided and obtain the adjusted type. |
9346a6ac | 78 | let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick); |
1a4d82fc | 79 | |
1a4d82fc | 80 | // Create substitutions for the method's type parameters. |
c1a9b12d | 81 | let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick); |
041b39d2 | 82 | let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs); |
c1a9b12d | 83 | |
064997fb | 84 | debug!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}"); |
1a4d82fc JJ |
85 | |
86 | // Create the final signature for the method, replacing late-bound regions. | |
7cac9316 | 87 | let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs); |
1a4d82fc | 88 | |
064997fb FG |
89 | // If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that |
90 | // something which derefs to `Self` actually implements the trait and the caller | |
91 | // wanted to make a static dispatch on it but forgot to import the trait. | |
92 | // See test `src/test/ui/issue-35976.rs`. | |
93 | // | |
94 | // In that case, we'll error anyway, but we'll also re-run the search with all traits | |
95 | // in scope, and if we find another method which can be used, we'll output an | |
96 | // appropriate hint suggesting to import the trait. | |
97 | let filler_substs = rcvr_substs | |
98 | .extend_to(self.tcx, pick.item.def_id, |def, _| self.tcx.mk_param_from_def(def)); | |
99 | let illegal_sized_bound = self.predicates_require_illegal_sized_bound( | |
100 | &self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs), | |
101 | ); | |
102 | ||
ea8adc8c XL |
103 | // Unify the (adjusted) self type with what the method expects. |
104 | // | |
105 | // SUBTLE: if we want good error messages, because of "guessing" while matching | |
106 | // traits, no trait system method can be called before this point because they | |
107 | // could alter our Self-type, except for normalizing the receiver from the | |
108 | // signature (which is also done during probing). | |
fc512014 | 109 | let method_sig_rcvr = self.normalize_associated_types_in(self.span, method_sig.inputs()[0]); |
3dfed10e XL |
110 | debug!( |
111 | "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", | |
112 | self_ty, method_sig_rcvr, method_sig, method_predicates | |
113 | ); | |
114 | self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); | |
ea8adc8c XL |
115 | |
116 | let (method_sig, method_predicates) = | |
fc512014 | 117 | self.normalize_associated_types_in(self.span, (method_sig, method_predicates)); |
136023e0 | 118 | let method_sig = ty::Binder::dummy(method_sig); |
ea8adc8c XL |
119 | |
120 | // Make sure nobody calls `drop()` explicitly. | |
121 | self.enforce_illegal_method_limitations(&pick); | |
122 | ||
b039eaaf | 123 | // Add any trait/regions obligations specified on the method's type parameters. |
3b2f2976 XL |
124 | // We won't add these if we encountered an illegal sized bound, so that we can use |
125 | // a custom error in that case. | |
74b04a01 | 126 | if illegal_sized_bound.is_none() { |
3c0e092e XL |
127 | self.add_obligations( |
128 | self.tcx.mk_fn_ptr(method_sig), | |
129 | all_substs, | |
130 | method_predicates, | |
131 | pick.item.def_id, | |
132 | ); | |
3b2f2976 | 133 | } |
b039eaaf SL |
134 | |
135 | // Create the final `MethodCallee`. | |
136023e0 XL |
136 | let callee = MethodCallee { |
137 | def_id: pick.item.def_id, | |
138 | substs: all_substs, | |
139 | sig: method_sig.skip_binder(), | |
140 | }; | |
3b2f2976 | 141 | ConfirmResult { callee, illegal_sized_bound } |
1a4d82fc JJ |
142 | } |
143 | ||
144 | /////////////////////////////////////////////////////////////////////////// | |
145 | // ADJUSTMENTS | |
146 | ||
e1599b0c XL |
147 | fn adjust_self_ty( |
148 | &mut self, | |
149 | unadjusted_self_ty: Ty<'tcx>, | |
150 | pick: &probe::Pick<'tcx>, | |
151 | ) -> Ty<'tcx> { | |
7cac9316 | 152 | // Commit the autoderefs by calling `autoderef` again, but this |
3dfed10e | 153 | // time writing the results into the various typeck results. |
1b1a35ee XL |
154 | let mut autoderef = |
155 | self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span); | |
5e7ed085 FG |
156 | let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { |
157 | return self.tcx.ty_error_with_message( | |
158 | rustc_span::DUMMY_SP, | |
159 | &format!("failed autoderef {}", pick.autoderefs), | |
160 | ); | |
e1599b0c | 161 | }; |
7cac9316 XL |
162 | assert_eq!(n, pick.autoderefs); |
163 | ||
f035d41b | 164 | let mut adjustments = self.adjust_steps(&autoderef); |
5099ac24 | 165 | let mut target = self.structurally_resolved_type(autoderef.span(), ty); |
7cac9316 | 166 | |
5099ac24 | 167 | match pick.autoref_or_ptr_adjustment { |
6a06907d | 168 | Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => { |
3c0e092e | 169 | let region = self.next_region_var(infer::Autoref(self.span)); |
5099ac24 FG |
170 | // Type we're wrapping in a reference, used later for unsizing |
171 | let base_ty = target; | |
172 | ||
173 | target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target }); | |
6a06907d XL |
174 | let mutbl = match mutbl { |
175 | hir::Mutability::Not => AutoBorrowMutability::Not, | |
176 | hir::Mutability::Mut => AutoBorrowMutability::Mut { | |
177 | // Method call receivers are the primary use case | |
178 | // for two-phase borrows. | |
179 | allow_two_phase_borrow: AllowTwoPhase::Yes, | |
180 | }, | |
181 | }; | |
182 | adjustments.push(Adjustment { | |
183 | kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), | |
184 | target, | |
185 | }); | |
186 | ||
5099ac24 FG |
187 | if unsize { |
188 | let unsized_ty = if let ty::Array(elem_ty, _) = base_ty.kind() { | |
189 | self.tcx.mk_slice(*elem_ty) | |
190 | } else { | |
191 | bug!( | |
192 | "AutorefOrPtrAdjustment's unsize flag should only be set for array ty, found {}", | |
193 | base_ty | |
194 | ) | |
195 | }; | |
6a06907d XL |
196 | target = self |
197 | .tcx | |
5099ac24 | 198 | .mk_ref(region, ty::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty }); |
6a06907d XL |
199 | adjustments |
200 | .push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target }); | |
201 | } | |
202 | } | |
203 | Some(probe::AutorefOrPtrAdjustment::ToConstPtr) => { | |
204 | target = match target.kind() { | |
5099ac24 FG |
205 | &ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { |
206 | assert_eq!(mutbl, hir::Mutability::Mut); | |
6a06907d XL |
207 | self.tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty }) |
208 | } | |
209 | other => panic!("Cannot adjust receiver type {:?} to const ptr", other), | |
210 | }; | |
211 | ||
212 | adjustments.push(Adjustment { | |
213 | kind: Adjust::Pointer(PointerCast::MutToConstPointer), | |
214 | target, | |
215 | }); | |
7cac9316 | 216 | } |
6a06907d | 217 | None => {} |
7cac9316 | 218 | } |
1a4d82fc | 219 | |
f035d41b | 220 | self.register_predicates(autoderef.into_obligations()); |
c30ab7b3 | 221 | |
7cac9316 XL |
222 | // Write out the final adjustments. |
223 | self.apply_adjustments(self.self_expr, adjustments); | |
c30ab7b3 SL |
224 | |
225 | target | |
1a4d82fc JJ |
226 | } |
227 | ||
1a4d82fc JJ |
228 | /// Returns a set of substitutions for the method *receiver* where all type and region |
229 | /// parameters are instantiated with fresh variables. This substitution does not include any | |
230 | /// parameters declared on the method itself. | |
231 | /// | |
232 | /// Note that this substitution may include late-bound regions from the impl level. If so, | |
233 | /// these are instantiated later in the `instantiate_method_sig` routine. | |
dfeec247 XL |
234 | fn fresh_receiver_substs( |
235 | &mut self, | |
236 | self_ty: Ty<'tcx>, | |
237 | pick: &probe::Pick<'tcx>, | |
238 | ) -> SubstsRef<'tcx> { | |
1a4d82fc | 239 | match pick.kind { |
c1a9b12d | 240 | probe::InherentImplPick => { |
064997fb | 241 | let impl_def_id = pick.item.container_id(self.tcx); |
dfeec247 XL |
242 | assert!( |
243 | self.tcx.impl_trait_ref(impl_def_id).is_none(), | |
244 | "impl {:?} is not an inherent impl", | |
245 | impl_def_id | |
246 | ); | |
ba9703b0 | 247 | self.fresh_substs_for_item(self.span, impl_def_id) |
1a4d82fc JJ |
248 | } |
249 | ||
c1a9b12d | 250 | probe::ObjectPick => { |
064997fb | 251 | let trait_def_id = pick.item.container_id(self.tcx); |
9e0c209e | 252 | self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { |
1a4d82fc JJ |
253 | // The object data has no entry for the Self |
254 | // Type. For the purposes of this method call, we | |
255 | // substitute the object type itself. This | |
256 | // wouldn't be a sound substitution in all cases, | |
257 | // since each instance of the object type is a | |
258 | // different existential and hence could match | |
259 | // distinct types (e.g., if `Self` appeared as an | |
260 | // argument type), but those cases have already | |
261 | // been ruled out when we deemed the trait to be | |
262 | // "object safe". | |
c30ab7b3 SL |
263 | let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty); |
264 | let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id); | |
1a4d82fc | 265 | let upcast_trait_ref = |
fc512014 | 266 | this.replace_bound_vars_with_fresh_vars(upcast_poly_trait_ref); |
dfeec247 XL |
267 | debug!( |
268 | "original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}", | |
269 | original_poly_trait_ref, upcast_trait_ref, trait_def_id | |
270 | ); | |
9e0c209e | 271 | upcast_trait_ref.substs |
1a4d82fc JJ |
272 | }) |
273 | } | |
274 | ||
c1a9b12d | 275 | probe::TraitPick => { |
064997fb | 276 | let trait_def_id = pick.item.container_id(self.tcx); |
1a4d82fc JJ |
277 | |
278 | // Make a trait reference `$0 : Trait<$1...$n>` | |
279 | // consisting entirely of type variables. Later on in | |
280 | // the process we will unify the transformed-self-type | |
281 | // of the method with the actual type in order to | |
282 | // unify some of these variables. | |
9e0c209e | 283 | self.fresh_substs_for_item(self.span, trait_def_id) |
1a4d82fc JJ |
284 | } |
285 | ||
fc512014 | 286 | probe::WhereClausePick(poly_trait_ref) => { |
1a4d82fc JJ |
287 | // Where clauses can have bound regions in them. We need to instantiate |
288 | // those to convert from a poly-trait-ref to a trait-ref. | |
fc512014 | 289 | self.replace_bound_vars_with_fresh_vars(poly_trait_ref).substs |
1a4d82fc JJ |
290 | } |
291 | } | |
292 | } | |
293 | ||
c30ab7b3 | 294 | fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R |
dc9dc135 XL |
295 | where |
296 | F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>) -> R, | |
1a4d82fc JJ |
297 | { |
298 | // If we specified that this is an object method, then the | |
299 | // self-type ought to be something that can be dereferenced to | |
300 | // yield an object-type (e.g., `&Object` or `Box<Object>` | |
301 | // etc). | |
302 | ||
3157f602 | 303 | // FIXME: this feels, like, super dubious |
c30ab7b3 SL |
304 | self.fcx |
305 | .autoderef(self.span, self_ty) | |
ff7c6d11 | 306 | .include_raw_pointers() |
1b1a35ee | 307 | .find_map(|(ty, _)| match ty.kind() { |
c295e0f8 | 308 | ty::Dynamic(data, ..) => Some(closure( |
dfeec247 XL |
309 | self, |
310 | ty, | |
311 | data.principal().unwrap_or_else(|| { | |
312 | span_bug!(self.span, "calling trait method on empty object?") | |
313 | }), | |
314 | )), | |
315 | _ => None, | |
316 | }) | |
dfeec247 XL |
317 | .unwrap_or_else(|| { |
318 | span_bug!( | |
319 | self.span, | |
320 | "self-type `{}` for ObjectPick never dereferenced to an object", | |
321 | self_ty | |
322 | ) | |
323 | }) | |
1a4d82fc JJ |
324 | } |
325 | ||
564c78a2 XL |
326 | fn instantiate_method_substs( |
327 | &mut self, | |
328 | pick: &probe::Pick<'tcx>, | |
dfeec247 | 329 | seg: &hir::PathSegment<'_>, |
532ac7d7 XL |
330 | parent_substs: SubstsRef<'tcx>, |
331 | ) -> SubstsRef<'tcx> { | |
1a4d82fc JJ |
332 | // Determine the values for the generic parameters of the method. |
333 | // If they were not explicitly supplied, just construct fresh | |
334 | // variables. | |
b7449926 | 335 | let generics = self.tcx.generics_of(pick.item.def_id); |
5869c6ff | 336 | |
6a06907d | 337 | let arg_count_correct = <dyn AstConv<'_>>::check_generic_arg_count_for_call( |
5869c6ff XL |
338 | self.tcx, |
339 | self.span, | |
340 | pick.item.def_id, | |
c295e0f8 | 341 | generics, |
5869c6ff XL |
342 | seg, |
343 | IsMethodCall::Yes, | |
b7449926 | 344 | ); |
1a4d82fc JJ |
345 | |
346 | // Create subst for early-bound lifetime parameters, combining | |
347 | // parameters from the type and those from the method. | |
b7449926 XL |
348 | assert_eq!(generics.parent_count, parent_substs.len()); |
349 | ||
fc512014 XL |
350 | struct MethodSubstsCtxt<'a, 'tcx> { |
351 | cfcx: &'a ConfirmContext<'a, 'tcx>, | |
352 | pick: &'a probe::Pick<'tcx>, | |
353 | seg: &'a hir::PathSegment<'a>, | |
354 | } | |
355 | impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> { | |
356 | fn args_for_def_id( | |
357 | &mut self, | |
358 | def_id: DefId, | |
359 | ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { | |
360 | if def_id == self.pick.item.def_id { | |
c295e0f8 | 361 | if let Some(data) = self.seg.args { |
fc512014 XL |
362 | return (Some(data), false); |
363 | } | |
364 | } | |
365 | (None, false) | |
366 | } | |
367 | ||
368 | fn provided_kind( | |
369 | &mut self, | |
370 | param: &ty::GenericParamDef, | |
371 | arg: &GenericArg<'_>, | |
372 | ) -> subst::GenericArg<'tcx> { | |
373 | match (¶m.kind, arg) { | |
374 | (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { | |
6a06907d XL |
375 | <dyn AstConv<'_>>::ast_region_to_region(self.cfcx.fcx, lt, Some(param)) |
376 | .into() | |
fc512014 XL |
377 | } |
378 | (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { | |
379 | self.cfcx.to_ty(ty).into() | |
380 | } | |
cdc7bbd5 | 381 | (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { |
fc512014 XL |
382 | self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() |
383 | } | |
94222f64 XL |
384 | (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { |
385 | self.cfcx.ty_infer(Some(param), inf.span).into() | |
386 | } | |
387 | (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { | |
388 | let tcx = self.cfcx.tcx(); | |
389 | self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into() | |
390 | } | |
fc512014 XL |
391 | _ => unreachable!(), |
392 | } | |
393 | } | |
394 | ||
395 | fn inferred_kind( | |
396 | &mut self, | |
397 | _substs: Option<&[subst::GenericArg<'tcx>]>, | |
398 | param: &ty::GenericParamDef, | |
399 | _infer_args: bool, | |
400 | ) -> subst::GenericArg<'tcx> { | |
401 | self.cfcx.var_for_def(self.cfcx.span, param) | |
402 | } | |
403 | } | |
6a06907d | 404 | <dyn AstConv<'_>>::create_substs_for_generic_args( |
b7449926 XL |
405 | self.tcx, |
406 | pick.item.def_id, | |
407 | parent_substs, | |
408 | false, | |
409 | None, | |
cdc7bbd5 | 410 | &arg_count_correct, |
fc512014 | 411 | &mut MethodSubstsCtxt { cfcx: self, pick, seg }, |
b7449926 | 412 | ) |
1a4d82fc JJ |
413 | } |
414 | ||
3dfed10e XL |
415 | fn unify_receivers( |
416 | &mut self, | |
417 | self_ty: Ty<'tcx>, | |
418 | method_self_ty: Ty<'tcx>, | |
419 | pick: &probe::Pick<'tcx>, | |
420 | substs: SubstsRef<'tcx>, | |
421 | ) { | |
422 | debug!( | |
423 | "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}", | |
424 | self_ty, method_self_ty, self.span, pick | |
425 | ); | |
426 | let cause = self.cause( | |
427 | self.span, | |
428 | ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext { | |
429 | assoc_item: pick.item, | |
430 | param_env: self.param_env, | |
431 | substs, | |
432 | })), | |
433 | ); | |
434 | match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { | |
476ff2be SL |
435 | Ok(InferOk { obligations, value: () }) => { |
436 | self.register_predicates(obligations); | |
a7813a04 | 437 | } |
1a4d82fc | 438 | Err(_) => { |
dfeec247 XL |
439 | span_bug!( |
440 | self.span, | |
441 | "{} was a subtype of {} but now is not?", | |
442 | self_ty, | |
443 | method_self_ty | |
444 | ); | |
1a4d82fc JJ |
445 | } |
446 | } | |
447 | } | |
448 | ||
ea8adc8c XL |
449 | // NOTE: this returns the *unnormalized* predicates and method sig. Because of |
450 | // inference guessing, the predicates and method signature can't be normalized | |
451 | // until we unify the `Self` type. | |
dfeec247 XL |
452 | fn instantiate_method_sig( |
453 | &mut self, | |
454 | pick: &probe::Pick<'tcx>, | |
455 | all_substs: SubstsRef<'tcx>, | |
456 | ) -> (ty::FnSig<'tcx>, ty::InstantiatedPredicates<'tcx>) { | |
457 | debug!("instantiate_method_sig(pick={:?}, all_substs={:?})", pick, all_substs); | |
1a4d82fc JJ |
458 | |
459 | // Instantiate the bounds on the method with the | |
c34b1796 AL |
460 | // type/early-bound-regions substitutions performed. There can |
461 | // be no late-bound regions appearing here. | |
476ff2be | 462 | let def_id = pick.item.def_id; |
dfeec247 | 463 | let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_substs); |
1a4d82fc | 464 | |
c30ab7b3 | 465 | debug!("method_predicates after subst = {:?}", method_predicates); |
1a4d82fc | 466 | |
04454e1e | 467 | let sig = self.tcx.bound_fn_sig(def_id); |
476ff2be | 468 | |
04454e1e FG |
469 | let sig = sig.subst(self.tcx, all_substs); |
470 | debug!("type scheme substituted, sig={:?}", sig); | |
1a4d82fc | 471 | |
04454e1e FG |
472 | let sig = self.replace_bound_vars_with_fresh_vars(sig); |
473 | debug!("late-bound lifetimes from method instantiated, sig={:?}", sig); | |
1a4d82fc | 474 | |
04454e1e | 475 | (sig, method_predicates) |
1a4d82fc JJ |
476 | } |
477 | ||
dfeec247 XL |
478 | fn add_obligations( |
479 | &mut self, | |
480 | fty: Ty<'tcx>, | |
481 | all_substs: SubstsRef<'tcx>, | |
ba9703b0 | 482 | method_predicates: ty::InstantiatedPredicates<'tcx>, |
3c0e092e | 483 | def_id: DefId, |
dfeec247 XL |
484 | ) { |
485 | debug!( | |
3c0e092e XL |
486 | "add_obligations: fty={:?} all_substs={:?} method_predicates={:?} def_id={:?}", |
487 | fty, all_substs, method_predicates, def_id | |
dfeec247 | 488 | ); |
1a4d82fc | 489 | |
3c0e092e XL |
490 | // FIXME: could replace with the following, but we already calculated `method_predicates`, |
491 | // so we just call `predicates_for_generics` directly to avoid redoing work. | |
492 | // `self.add_required_obligations(self.span, def_id, &all_substs);` | |
493 | for obligation in traits::predicates_for_generics( | |
494 | traits::ObligationCause::new(self.span, self.body_id, traits::ItemObligation(def_id)), | |
495 | self.param_env, | |
dfeec247 | 496 | method_predicates, |
3c0e092e XL |
497 | ) { |
498 | self.register_predicate(obligation); | |
499 | } | |
1a4d82fc | 500 | |
e9174d1e SL |
501 | // this is a projection from a trait reference, so we have to |
502 | // make sure that the trait reference inputs are well-formed. | |
a7813a04 | 503 | self.add_wf_bounds(all_substs, self.call_expr); |
b039eaaf SL |
504 | |
505 | // the function type must also be well-formed (this is not | |
506 | // implied by the substs being well-formed because of inherent | |
507 | // impls and late-bound regions - see issue #28609). | |
064997fb | 508 | self.register_wf_obligation(fty.into(), self.span, traits::WellFormed(None)); |
cc61c64b XL |
509 | } |
510 | ||
1a4d82fc JJ |
511 | /////////////////////////////////////////////////////////////////////////// |
512 | // MISCELLANY | |
513 | ||
dfeec247 XL |
514 | fn predicates_require_illegal_sized_bound( |
515 | &self, | |
516 | predicates: &ty::InstantiatedPredicates<'tcx>, | |
74b04a01 | 517 | ) -> Option<Span> { |
5e7ed085 | 518 | let sized_def_id = self.tcx.lang_items().sized_trait()?; |
3b2f2976 | 519 | |
ba9703b0 | 520 | traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied()) |
3dfed10e | 521 | // We don't care about regions here. |
5869c6ff | 522 | .filter_map(|obligation| match obligation.predicate.kind().skip_binder() { |
94222f64 | 523 | ty::PredicateKind::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => { |
cdc7bbd5 | 524 | let span = iter::zip(&predicates.predicates, &predicates.spans) |
f9f354fc | 525 | .find_map( |
3dfed10e XL |
526 | |(p, span)| { |
527 | if *p == obligation.predicate { Some(*span) } else { None } | |
528 | }, | |
ba9703b0 | 529 | ) |
74b04a01 XL |
530 | .unwrap_or(rustc_span::DUMMY_SP); |
531 | Some((trait_pred, span)) | |
3b2f2976 | 532 | } |
dfeec247 | 533 | _ => None, |
3b2f2976 | 534 | }) |
1b1a35ee | 535 | .find_map(|(trait_pred, span)| match trait_pred.self_ty().kind() { |
74b04a01 XL |
536 | ty::Dynamic(..) => Some(span), |
537 | _ => None, | |
3b2f2976 XL |
538 | }) |
539 | } | |
540 | ||
9fa01778 | 541 | fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { |
1a4d82fc | 542 | // Disallow calls to the method `drop` defined in the `Drop` trait. |
064997fb FG |
543 | if let Some(trait_def_id) = pick.item.trait_container(self.tcx) { |
544 | callee::check_legal_trait_for_method_call( | |
f9f354fc XL |
545 | self.tcx, |
546 | self.span, | |
547 | Some(self.self_expr.span), | |
5869c6ff | 548 | self.call_expr.span, |
f9f354fc | 549 | trait_def_id, |
064997fb | 550 | ) |
1a4d82fc JJ |
551 | } |
552 | } | |
553 | ||
dfeec247 XL |
554 | fn upcast( |
555 | &mut self, | |
556 | source_trait_ref: ty::PolyTraitRef<'tcx>, | |
557 | target_trait_def_id: DefId, | |
558 | ) -> ty::PolyTraitRef<'tcx> { | |
559 | let upcast_trait_refs = | |
560 | traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id); | |
c34b1796 AL |
561 | |
562 | // must be exactly one trait ref or we'd get an ambig error etc | |
563 | if upcast_trait_refs.len() != 1 { | |
dfeec247 XL |
564 | span_bug!( |
565 | self.span, | |
566 | "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`", | |
567 | source_trait_ref, | |
568 | target_trait_def_id, | |
569 | upcast_trait_refs | |
570 | ); | |
1a4d82fc | 571 | } |
c34b1796 AL |
572 | |
573 | upcast_trait_refs.into_iter().next().unwrap() | |
1a4d82fc JJ |
574 | } |
575 | ||
cdc7bbd5 | 576 | fn replace_bound_vars_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T |
dfeec247 | 577 | where |
923072b8 | 578 | T: TypeFoldable<'tcx> + Copy, |
1a4d82fc | 579 | { |
923072b8 | 580 | self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value) |
1a4d82fc JJ |
581 | } |
582 | } |