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