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