1 use super::{probe, MethodCallee}
;
3 use crate::astconv
::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}
;
4 use crate::check
::{callee, FnCtxt}
;
5 use crate::hir
::def_id
::DefId
;
6 use crate::hir
::GenericArg
;
8 use rustc_infer
::infer
::{self, InferOk}
;
9 use rustc_middle
::traits
::{ObligationCauseCode, UnifyReceiverContext}
;
10 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, PointerCast}
;
11 use rustc_middle
::ty
::adjustment
::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}
;
12 use rustc_middle
::ty
::fold
::TypeFoldable
;
13 use rustc_middle
::ty
::subst
::{self, Subst, SubstsRef}
;
14 use rustc_middle
::ty
::{self, GenericParamDefKind, Ty}
;
16 use rustc_trait_selection
::traits
;
21 struct ConfirmContext
<'a
, 'tcx
> {
22 fcx
: &'a FnCtxt
<'a
, 'tcx
>,
24 self_expr
: &'tcx hir
::Expr
<'tcx
>,
25 call_expr
: &'tcx hir
::Expr
<'tcx
>,
28 impl<'a
, 'tcx
> Deref
for ConfirmContext
<'a
, 'tcx
> {
29 type Target
= FnCtxt
<'a
, 'tcx
>;
30 fn deref(&self) -> &Self::Target
{
36 pub struct ConfirmResult
<'tcx
> {
37 pub callee
: MethodCallee
<'tcx
>,
38 pub illegal_sized_bound
: Option
<Span
>,
41 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
42 pub fn confirm_method(
45 self_expr
: &'tcx hir
::Expr
<'tcx
>,
46 call_expr
: &'tcx hir
::Expr
<'tcx
>,
47 unadjusted_self_ty
: Ty
<'tcx
>,
48 pick
: probe
::Pick
<'tcx
>,
49 segment
: &hir
::PathSegment
<'_
>,
50 ) -> ConfirmResult
<'tcx
> {
52 "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
53 unadjusted_self_ty
, pick
, segment
.args
,
56 let mut confirm_cx
= ConfirmContext
::new(self, span
, self_expr
, call_expr
);
57 confirm_cx
.confirm(unadjusted_self_ty
, pick
, segment
)
61 impl<'a
, 'tcx
> ConfirmContext
<'a
, 'tcx
> {
63 fcx
: &'a FnCtxt
<'a
, 'tcx
>,
65 self_expr
: &'tcx hir
::Expr
<'tcx
>,
66 call_expr
: &'tcx hir
::Expr
<'tcx
>,
67 ) -> ConfirmContext
<'a
, 'tcx
> {
68 ConfirmContext { fcx, span, self_expr, call_expr }
73 unadjusted_self_ty
: Ty
<'tcx
>,
74 pick
: probe
::Pick
<'tcx
>,
75 segment
: &hir
::PathSegment
<'_
>,
76 ) -> ConfirmResult
<'tcx
> {
77 // Adjust the self expression the user provided and obtain the adjusted type.
78 let self_ty
= self.adjust_self_ty(unadjusted_self_ty
, &pick
);
80 // Create substitutions for the method's type parameters.
81 let rcvr_substs
= self.fresh_receiver_substs(self_ty
, &pick
);
82 let all_substs
= self.instantiate_method_substs(&pick
, segment
, rcvr_substs
);
84 debug
!("all_substs={:?}", all_substs
);
86 // Create the final signature for the method, replacing late-bound regions.
87 let (method_sig
, method_predicates
) = self.instantiate_method_sig(&pick
, all_substs
);
89 // Unify the (adjusted) self type with what the method expects.
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).
95 let method_sig_rcvr
= self.normalize_associated_types_in(self.span
, method_sig
.inputs()[0]);
97 "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
98 self_ty
, method_sig_rcvr
, method_sig
, method_predicates
100 self.unify_receivers(self_ty
, method_sig_rcvr
, &pick
, all_substs
);
102 let (method_sig
, method_predicates
) =
103 self.normalize_associated_types_in(self.span
, (method_sig
, method_predicates
));
104 let method_sig
= ty
::Binder
::dummy(method_sig
);
106 // Make sure nobody calls `drop()` explicitly.
107 self.enforce_illegal_method_limitations(&pick
);
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`.
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
);
119 // Add any trait/regions obligations specified on the method's type parameters.
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.
122 if illegal_sized_bound
.is_none() {
123 self.add_obligations(self.tcx
.mk_fn_ptr(method_sig
), all_substs
, method_predicates
);
126 // Create the final `MethodCallee`.
127 let callee
= MethodCallee
{
128 def_id
: pick
.item
.def_id
,
130 sig
: method_sig
.skip_binder(),
132 ConfirmResult { callee, illegal_sized_bound }
135 ///////////////////////////////////////////////////////////////////////////
140 unadjusted_self_ty
: Ty
<'tcx
>,
141 pick
: &probe
::Pick
<'tcx
>,
143 // Commit the autoderefs by calling `autoderef` again, but this
144 // time writing the results into the various typeck results.
146 self.autoderef_overloaded_span(self.span
, unadjusted_self_ty
, self.call_expr
.span
);
147 let (_
, n
) = match autoderef
.nth(pick
.autoderefs
) {
150 return self.tcx
.ty_error_with_message(
151 rustc_span
::DUMMY_SP
,
152 &format
!("failed autoderef {}", pick
.autoderefs
),
156 assert_eq
!(n
, pick
.autoderefs
);
158 let mut adjustments
= self.adjust_steps(&autoderef
);
161 self.structurally_resolved_type(autoderef
.span(), autoderef
.final_ty(false));
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
,
175 adjustments
.push(Adjustment
{
176 kind
: Adjust
::Borrow(AutoBorrow
::Ref(region
, mutbl
)),
180 if let Some(unsize_target
) = unsize
{
183 .mk_ref(region
, ty
::TypeAndMut { mutbl: mutbl.into(), ty: unsize_target }
);
185 .push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target }
);
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 }
)
194 other
=> panic
!("Cannot adjust receiver type {:?} to const ptr", other
),
197 adjustments
.push(Adjustment
{
198 kind
: Adjust
::Pointer(PointerCast
::MutToConstPointer
),
205 self.register_predicates(autoderef
.into_obligations());
207 // Write out the final adjustments.
208 self.apply_adjustments(self.self_expr
, adjustments
);
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.
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.
219 fn fresh_receiver_substs(
222 pick
: &probe
::Pick
<'tcx
>,
223 ) -> SubstsRef
<'tcx
> {
225 probe
::InherentImplPick
=> {
226 let impl_def_id
= pick
.item
.container
.id();
228 self.tcx
.impl_trait_ref(impl_def_id
).is_none(),
229 "impl {:?} is not an inherent impl",
232 self.fresh_substs_for_item(self.span
, impl_def_id
)
235 probe
::ObjectPick
=> {
236 let trait_def_id
= pick
.item
.container
.id();
237 self.extract_existential_trait_ref(self_ty
, |this
, object_ty
, principal
| {
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
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
);
250 let upcast_trait_ref
=
251 this
.replace_bound_vars_with_fresh_vars(upcast_poly_trait_ref
);
253 "original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
254 original_poly_trait_ref
, upcast_trait_ref
, trait_def_id
256 upcast_trait_ref
.substs
260 probe
::TraitPick
=> {
261 let trait_def_id
= pick
.item
.container
.id();
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.
268 self.fresh_substs_for_item(self.span
, trait_def_id
)
271 probe
::WhereClausePick(poly_trait_ref
) => {
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.
274 self.replace_bound_vars_with_fresh_vars(poly_trait_ref
).substs
279 fn extract_existential_trait_ref
<R
, F
>(&mut self, self_ty
: Ty
<'tcx
>, mut closure
: F
) -> R
281 F
: FnMut(&mut ConfirmContext
<'a
, 'tcx
>, Ty
<'tcx
>, ty
::PolyExistentialTraitRef
<'tcx
>) -> R
,
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>`
288 // FIXME: this feels, like, super dubious
290 .autoderef(self.span
, self_ty
)
291 .include_raw_pointers()
292 .find_map(|(ty
, _
)| match ty
.kind() {
293 ty
::Dynamic(ref data
, ..) => Some(closure(
296 data
.principal().unwrap_or_else(|| {
297 span_bug
!(self.span
, "calling trait method on empty object?")
305 "self-type `{}` for ObjectPick never dereferenced to an object",
311 fn instantiate_method_substs(
313 pick
: &probe
::Pick
<'tcx
>,
314 seg
: &hir
::PathSegment
<'_
>,
315 parent_substs
: SubstsRef
<'tcx
>,
316 ) -> SubstsRef
<'tcx
> {
317 // Determine the values for the generic parameters of the method.
318 // If they were not explicitly supplied, just construct fresh
320 let generics
= self.tcx
.generics_of(pick
.item
.def_id
);
322 let arg_count_correct
= <dyn AstConv
<'_
>>::check_generic_arg_count_for_call(
331 // Create subst for early-bound lifetime parameters, combining
332 // parameters from the type and those from the method.
333 assert_eq
!(generics
.parent_count
, parent_substs
.len());
335 struct MethodSubstsCtxt
<'a
, 'tcx
> {
336 cfcx
: &'a ConfirmContext
<'a
, 'tcx
>,
337 pick
: &'a probe
::Pick
<'tcx
>,
338 seg
: &'a hir
::PathSegment
<'a
>,
340 impl<'a
, 'tcx
> CreateSubstsForGenericArgsCtxt
<'a
, 'tcx
> for MethodSubstsCtxt
<'a
, 'tcx
> {
344 ) -> (Option
<&'a hir
::GenericArgs
<'a
>>, bool
) {
345 if def_id
== self.pick
.item
.def_id
{
346 if let Some(ref data
) = self.seg
.args
{
347 return (Some(data
), false);
355 param
: &ty
::GenericParamDef
,
356 arg
: &GenericArg
<'_
>,
357 ) -> subst
::GenericArg
<'tcx
> {
358 match (¶m
.kind
, arg
) {
359 (GenericParamDefKind
::Lifetime
, GenericArg
::Lifetime(lt
)) => {
360 <dyn AstConv
<'_
>>::ast_region_to_region(self.cfcx
.fcx
, lt
, Some(param
))
363 (GenericParamDefKind
::Type { .. }
, GenericArg
::Type(ty
)) => {
364 self.cfcx
.to_ty(ty
).into()
366 (GenericParamDefKind
::Const { .. }
, GenericArg
::Const(ct
)) => {
367 self.cfcx
.const_arg_to_const(&ct
.value
, param
.def_id
).into()
375 _substs
: Option
<&[subst
::GenericArg
<'tcx
>]>,
376 param
: &ty
::GenericParamDef
,
378 ) -> subst
::GenericArg
<'tcx
> {
379 self.cfcx
.var_for_def(self.cfcx
.span
, param
)
382 <dyn AstConv
<'_
>>::create_substs_for_generic_args(
389 &mut MethodSubstsCtxt { cfcx: self, pick, seg }
,
396 method_self_ty
: Ty
<'tcx
>,
397 pick
: &probe
::Pick
<'tcx
>,
398 substs
: SubstsRef
<'tcx
>,
401 "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
402 self_ty
, method_self_ty
, self.span
, pick
404 let cause
= self.cause(
406 ObligationCauseCode
::UnifyReceiver(Box
::new(UnifyReceiverContext
{
407 assoc_item
: pick
.item
,
408 param_env
: self.param_env
,
412 match self.at(&cause
, self.param_env
).sup(method_self_ty
, self_ty
) {
413 Ok(InferOk { obligations, value: () }
) => {
414 self.register_predicates(obligations
);
419 "{} was a subtype of {} but now is not?",
427 // NOTE: this returns the *unnormalized* predicates and method sig. Because of
428 // inference guessing, the predicates and method signature can't be normalized
429 // until we unify the `Self` type.
430 fn instantiate_method_sig(
432 pick
: &probe
::Pick
<'tcx
>,
433 all_substs
: SubstsRef
<'tcx
>,
434 ) -> (ty
::FnSig
<'tcx
>, ty
::InstantiatedPredicates
<'tcx
>) {
435 debug
!("instantiate_method_sig(pick={:?}, all_substs={:?})", pick
, all_substs
);
437 // Instantiate the bounds on the method with the
438 // type/early-bound-regions substitutions performed. There can
439 // be no late-bound regions appearing here.
440 let def_id
= pick
.item
.def_id
;
441 let method_predicates
= self.tcx
.predicates_of(def_id
).instantiate(self.tcx
, all_substs
);
443 debug
!("method_predicates after subst = {:?}", method_predicates
);
445 let sig
= self.tcx
.fn_sig(def_id
);
447 // Instantiate late-bound regions and substitute the trait
448 // parameters into the method type to get the actual method type.
450 // N.B., instantiate late-bound regions first so that
451 // `instantiate_type_scheme` can normalize associated types that
452 // may reference those regions.
453 let method_sig
= self.replace_bound_vars_with_fresh_vars(sig
);
454 debug
!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig
);
456 let method_sig
= method_sig
.subst(self.tcx
, all_substs
);
457 debug
!("type scheme substituted, method_sig={:?}", method_sig
);
459 (method_sig
, method_predicates
)
465 all_substs
: SubstsRef
<'tcx
>,
466 method_predicates
: ty
::InstantiatedPredicates
<'tcx
>,
469 "add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
470 fty
, all_substs
, method_predicates
473 self.add_obligations_for_parameters(
474 traits
::ObligationCause
::misc(self.span
, self.body_id
),
478 // this is a projection from a trait reference, so we have to
479 // make sure that the trait reference inputs are well-formed.
480 self.add_wf_bounds(all_substs
, self.call_expr
);
482 // the function type must also be well-formed (this is not
483 // implied by the substs being well-formed because of inherent
484 // impls and late-bound regions - see issue #28609).
485 self.register_wf_obligation(fty
.into(), self.span
, traits
::MiscObligation
);
488 ///////////////////////////////////////////////////////////////////////////
491 fn predicates_require_illegal_sized_bound(
493 predicates
: &ty
::InstantiatedPredicates
<'tcx
>,
495 let sized_def_id
= match self.tcx
.lang_items().sized_trait() {
496 Some(def_id
) => def_id
,
500 traits
::elaborate_predicates(self.tcx
, predicates
.predicates
.iter().copied())
501 // We don't care about regions here.
502 .filter_map(|obligation
| match obligation
.predicate
.kind().skip_binder() {
503 ty
::PredicateKind
::Trait(trait_pred
, _
) if trait_pred
.def_id() == sized_def_id
=> {
504 let span
= iter
::zip(&predicates
.predicates
, &predicates
.spans
)
507 if *p
== obligation
.predicate { Some(*span) }
else { None }
510 .unwrap_or(rustc_span
::DUMMY_SP
);
511 Some((trait_pred
, span
))
515 .find_map(|(trait_pred
, span
)| match trait_pred
.self_ty().kind() {
516 ty
::Dynamic(..) => Some(span
),
521 fn enforce_illegal_method_limitations(&self, pick
: &probe
::Pick
<'_
>) {
522 // Disallow calls to the method `drop` defined in the `Drop` trait.
523 match pick
.item
.container
{
524 ty
::TraitContainer(trait_def_id
) => callee
::check_legal_trait_for_method_call(
527 Some(self.self_expr
.span
),
531 ty
::ImplContainer(..) => {}
537 source_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
538 target_trait_def_id
: DefId
,
539 ) -> ty
::PolyTraitRef
<'tcx
> {
540 let upcast_trait_refs
=
541 traits
::upcast_choices(self.tcx
, source_trait_ref
, target_trait_def_id
);
543 // must be exactly one trait ref or we'd get an ambig error etc
544 if upcast_trait_refs
.len() != 1 {
547 "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
554 upcast_trait_refs
.into_iter().next().unwrap()
557 fn replace_bound_vars_with_fresh_vars
<T
>(&self, value
: ty
::Binder
<'tcx
, T
>) -> T
559 T
: TypeFoldable
<'tcx
>,
561 self.fcx
.replace_bound_vars_with_fresh_vars(self.span
, infer
::FnCall
, value
).0