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