1 use super::{probe, MethodCallee}
;
3 use crate::{callee, FnCtxt}
;
5 use rustc_hir
::def_id
::DefId
;
6 use rustc_hir
::GenericArg
;
7 use rustc_hir_analysis
::astconv
::generics
::{
8 check_generic_arg_count_for_call
, create_substs_for_generic_args
,
10 use rustc_hir_analysis
::astconv
::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}
;
11 use rustc_infer
::infer
::{self, DefineOpaqueTypes, InferOk}
;
12 use rustc_middle
::traits
::{ObligationCauseCode, UnifyReceiverContext}
;
13 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, PointerCast}
;
14 use rustc_middle
::ty
::adjustment
::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}
;
15 use rustc_middle
::ty
::fold
::TypeFoldable
;
16 use rustc_middle
::ty
::subst
::{self, SubstsRef}
;
17 use rustc_middle
::ty
::{self, GenericParamDefKind, Ty, TyCtxt}
;
18 use rustc_middle
::ty
::{InternalSubsts, UserSubsts, UserType}
;
19 use rustc_span
::{Span, DUMMY_SP}
;
20 use rustc_trait_selection
::traits
;
24 struct ConfirmContext
<'a
, 'tcx
> {
25 fcx
: &'a FnCtxt
<'a
, 'tcx
>,
27 self_expr
: &'tcx hir
::Expr
<'tcx
>,
28 call_expr
: &'tcx hir
::Expr
<'tcx
>,
31 impl<'a
, 'tcx
> Deref
for ConfirmContext
<'a
, 'tcx
> {
32 type Target
= FnCtxt
<'a
, 'tcx
>;
33 fn deref(&self) -> &Self::Target
{
39 pub struct ConfirmResult
<'tcx
> {
40 pub callee
: MethodCallee
<'tcx
>,
41 pub illegal_sized_bound
: Option
<Span
>,
44 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
45 pub fn confirm_method(
48 self_expr
: &'tcx hir
::Expr
<'tcx
>,
49 call_expr
: &'tcx hir
::Expr
<'tcx
>,
50 unadjusted_self_ty
: Ty
<'tcx
>,
51 pick
: &probe
::Pick
<'tcx
>,
52 segment
: &hir
::PathSegment
<'_
>,
53 ) -> ConfirmResult
<'tcx
> {
55 "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
56 unadjusted_self_ty
, pick
, segment
.args
,
59 let mut confirm_cx
= ConfirmContext
::new(self, span
, self_expr
, call_expr
);
60 confirm_cx
.confirm(unadjusted_self_ty
, pick
, segment
)
64 impl<'a
, 'tcx
> ConfirmContext
<'a
, 'tcx
> {
66 fcx
: &'a FnCtxt
<'a
, 'tcx
>,
68 self_expr
: &'tcx hir
::Expr
<'tcx
>,
69 call_expr
: &'tcx hir
::Expr
<'tcx
>,
70 ) -> ConfirmContext
<'a
, 'tcx
> {
71 ConfirmContext { fcx, span, self_expr, call_expr }
76 unadjusted_self_ty
: Ty
<'tcx
>,
77 pick
: &probe
::Pick
<'tcx
>,
78 segment
: &hir
::PathSegment
<'_
>,
79 ) -> ConfirmResult
<'tcx
> {
80 // Adjust the self expression the user provided and obtain the adjusted type.
81 let self_ty
= self.adjust_self_ty(unadjusted_self_ty
, &pick
);
83 // Create substitutions for the method's type parameters.
84 let rcvr_substs
= self.fresh_receiver_substs(self_ty
, &pick
);
85 let all_substs
= self.instantiate_method_substs(&pick
, segment
, rcvr_substs
);
87 debug
!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}");
89 // Create the final signature for the method, replacing late-bound regions.
90 let (method_sig
, method_predicates
) = self.instantiate_method_sig(&pick
, all_substs
);
92 // If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
93 // something which derefs to `Self` actually implements the trait and the caller
94 // wanted to make a static dispatch on it but forgot to import the trait.
95 // See test `tests/ui/issue-35976.rs`.
97 // In that case, we'll error anyway, but we'll also re-run the search with all traits
98 // in scope, and if we find another method which can be used, we'll output an
99 // appropriate hint suggesting to import the trait.
100 let filler_substs
= rcvr_substs
101 .extend_to(self.tcx
, pick
.item
.def_id
, |def
, _
| self.tcx
.mk_param_from_def(def
));
102 let illegal_sized_bound
= self.predicates_require_illegal_sized_bound(
103 self.tcx
.predicates_of(pick
.item
.def_id
).instantiate(self.tcx
, filler_substs
),
106 // Unify the (adjusted) self type with what the method expects.
108 // SUBTLE: if we want good error messages, because of "guessing" while matching
109 // traits, no trait system method can be called before this point because they
110 // could alter our Self-type, except for normalizing the receiver from the
111 // signature (which is also done during probing).
112 let method_sig_rcvr
= self.normalize(self.span
, method_sig
.inputs()[0]);
114 "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
115 self_ty
, method_sig_rcvr
, method_sig
, method_predicates
117 self.unify_receivers(self_ty
, method_sig_rcvr
, &pick
, all_substs
);
119 let (method_sig
, method_predicates
) =
120 self.normalize(self.span
, (method_sig
, method_predicates
));
121 let method_sig
= ty
::Binder
::dummy(method_sig
);
123 // Make sure nobody calls `drop()` explicitly.
124 self.enforce_illegal_method_limitations(&pick
);
126 // Add any trait/regions obligations specified on the method's type parameters.
127 // We won't add these if we encountered an illegal sized bound, so that we can use
128 // a custom error in that case.
129 if illegal_sized_bound
.is_none() {
130 self.add_obligations(
131 self.tcx
.mk_fn_ptr(method_sig
),
138 // Create the final `MethodCallee`.
139 let callee
= MethodCallee
{
140 def_id
: pick
.item
.def_id
,
142 sig
: method_sig
.skip_binder(),
144 ConfirmResult { callee, illegal_sized_bound }
147 ///////////////////////////////////////////////////////////////////////////
152 unadjusted_self_ty
: Ty
<'tcx
>,
153 pick
: &probe
::Pick
<'tcx
>,
155 // Commit the autoderefs by calling `autoderef` again, but this
156 // time writing the results into the various typeck results.
157 let mut autoderef
= self.autoderef(self.call_expr
.span
, unadjusted_self_ty
);
158 let Some((ty
, n
)) = autoderef
.nth(pick
.autoderefs
) else {
159 return self.tcx
.ty_error_with_message(
160 rustc_span
::DUMMY_SP
,
161 format
!("failed autoderef {}", pick
.autoderefs
),
164 assert_eq
!(n
, pick
.autoderefs
);
166 let mut adjustments
= self.adjust_steps(&autoderef
);
167 let mut target
= self.structurally_resolved_type(autoderef
.span(), ty
);
169 match pick
.autoref_or_ptr_adjustment
{
170 Some(probe
::AutorefOrPtrAdjustment
::Autoref { mutbl, unsize }
) => {
171 let region
= self.next_region_var(infer
::Autoref(self.span
));
172 // Type we're wrapping in a reference, used later for unsizing
173 let base_ty
= target
;
175 target
= self.tcx
.mk_ref(region
, ty
::TypeAndMut { mutbl, ty: target }
);
177 // Method call receivers are the primary use case
178 // for two-phase borrows.
179 let mutbl
= AutoBorrowMutability
::new(mutbl
, AllowTwoPhase
::Yes
);
181 adjustments
.push(Adjustment
{
182 kind
: Adjust
::Borrow(AutoBorrow
::Ref(region
, mutbl
)),
187 let unsized_ty
= if let ty
::Array(elem_ty
, _
) = base_ty
.kind() {
188 self.tcx
.mk_slice(*elem_ty
)
191 "AutorefOrPtrAdjustment's unsize flag should only be set for array ty, found {}",
197 .mk_ref(region
, ty
::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty }
);
199 .push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target }
);
202 Some(probe
::AutorefOrPtrAdjustment
::ToConstPtr
) => {
203 target
= match target
.kind() {
204 &ty
::RawPtr(ty
::TypeAndMut { ty, mutbl }
) => {
205 assert
!(mutbl
.is_mut());
206 self.tcx
.mk_ptr(ty
::TypeAndMut { mutbl: hir::Mutability::Not, ty }
)
208 other
=> panic
!("Cannot adjust receiver type {:?} to const ptr", other
),
211 adjustments
.push(Adjustment
{
212 kind
: Adjust
::Pointer(PointerCast
::MutToConstPointer
),
219 self.register_predicates(autoderef
.into_obligations());
221 // Write out the final adjustments.
222 self.apply_adjustments(self.self_expr
, adjustments
);
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.
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.
233 fn fresh_receiver_substs(
236 pick
: &probe
::Pick
<'tcx
>,
237 ) -> SubstsRef
<'tcx
> {
239 probe
::InherentImplPick
=> {
240 let impl_def_id
= pick
.item
.container_id(self.tcx
);
242 self.tcx
.impl_trait_ref(impl_def_id
).is_none(),
243 "impl {:?} is not an inherent impl",
246 self.fresh_substs_for_item(self.span
, impl_def_id
)
249 probe
::ObjectPick
=> {
250 let trait_def_id
= pick
.item
.container_id(self.tcx
);
251 self.extract_existential_trait_ref(self_ty
, |this
, object_ty
, principal
| {
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
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
);
264 let upcast_trait_ref
=
265 this
.instantiate_binder_with_fresh_vars(upcast_poly_trait_ref
);
267 "original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
268 original_poly_trait_ref
, upcast_trait_ref
, trait_def_id
270 upcast_trait_ref
.substs
274 probe
::TraitPick
=> {
275 let trait_def_id
= pick
.item
.container_id(self.tcx
);
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.
282 self.fresh_substs_for_item(self.span
, trait_def_id
)
285 probe
::WhereClausePick(poly_trait_ref
) => {
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.
288 self.instantiate_binder_with_fresh_vars(poly_trait_ref
).substs
293 fn extract_existential_trait_ref
<R
, F
>(&mut self, self_ty
: Ty
<'tcx
>, mut closure
: F
) -> R
295 F
: FnMut(&mut ConfirmContext
<'a
, 'tcx
>, Ty
<'tcx
>, ty
::PolyExistentialTraitRef
<'tcx
>) -> R
,
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>`
302 // FIXME: this feels, like, super dubious
304 .autoderef(self.span
, self_ty
)
305 .include_raw_pointers()
306 .find_map(|(ty
, _
)| match ty
.kind() {
307 ty
::Dynamic(data
, ..) => Some(closure(
310 data
.principal().unwrap_or_else(|| {
311 span_bug
!(self.span
, "calling trait method on empty object?")
319 "self-type `{}` for ObjectPick never dereferenced to an object",
325 fn instantiate_method_substs(
327 pick
: &probe
::Pick
<'tcx
>,
328 seg
: &hir
::PathSegment
<'_
>,
329 parent_substs
: SubstsRef
<'tcx
>,
330 ) -> SubstsRef
<'tcx
> {
331 // Determine the values for the generic parameters of the method.
332 // If they were not explicitly supplied, just construct fresh
334 let generics
= self.tcx
.generics_of(pick
.item
.def_id
);
336 let arg_count_correct
= check_generic_arg_count_for_call(
345 // Create subst for early-bound lifetime parameters, combining
346 // parameters from the type and those from the method.
347 assert_eq
!(generics
.parent_count
, parent_substs
.len());
349 struct MethodSubstsCtxt
<'a
, 'tcx
> {
350 cfcx
: &'a ConfirmContext
<'a
, 'tcx
>,
351 pick
: &'a probe
::Pick
<'tcx
>,
352 seg
: &'a hir
::PathSegment
<'a
>,
354 impl<'a
, 'tcx
> CreateSubstsForGenericArgsCtxt
<'a
, 'tcx
> for MethodSubstsCtxt
<'a
, 'tcx
> {
358 ) -> (Option
<&'a hir
::GenericArgs
<'a
>>, bool
) {
359 if def_id
== self.pick
.item
.def_id
{
360 if let Some(data
) = self.seg
.args
{
361 return (Some(data
), false);
369 param
: &ty
::GenericParamDef
,
370 arg
: &GenericArg
<'_
>,
371 ) -> subst
::GenericArg
<'tcx
> {
372 match (¶m
.kind
, arg
) {
373 (GenericParamDefKind
::Lifetime
, GenericArg
::Lifetime(lt
)) => {
374 self.cfcx
.fcx
.astconv().ast_region_to_region(lt
, Some(param
)).into()
376 (GenericParamDefKind
::Type { .. }
, GenericArg
::Type(ty
)) => {
377 self.cfcx
.to_ty(ty
).raw
.into()
379 (GenericParamDefKind
::Const { .. }
, GenericArg
::Const(ct
)) => {
380 self.cfcx
.const_arg_to_const(&ct
.value
, param
.def_id
).into()
382 (GenericParamDefKind
::Type { .. }
, GenericArg
::Infer(inf
)) => {
383 self.cfcx
.ty_infer(Some(param
), inf
.span
).into()
385 (GenericParamDefKind
::Const { .. }
, GenericArg
::Infer(inf
)) => {
386 let tcx
= self.cfcx
.tcx();
389 tcx
.type_of(param
.def_id
)
391 .expect("const parameter types cannot be generic"),
403 _substs
: Option
<&[subst
::GenericArg
<'tcx
>]>,
404 param
: &ty
::GenericParamDef
,
406 ) -> subst
::GenericArg
<'tcx
> {
407 self.cfcx
.var_for_def(self.cfcx
.span
, param
)
411 let substs
= create_substs_for_generic_args(
418 &mut MethodSubstsCtxt { cfcx: self, pick, seg }
,
421 // When the method is confirmed, the `substs` includes
422 // parameters from not just the method, but also the impl of
423 // the method -- in particular, the `Self` type will be fully
424 // resolved. However, those are not something that the "user
425 // specified" -- i.e., those types come from the inferred type
426 // of the receiver, not something the user wrote. So when we
427 // create the user-substs, we want to replace those earlier
428 // types with just the types that the user actually wrote --
429 // that is, those that appear on the *method itself*.
431 // As an example, if the user wrote something like
432 // `foo.bar::<u32>(...)` -- the `Self` type here will be the
433 // type of `foo` (possibly adjusted), but we don't want to
434 // include that. We want just the `[_, u32]` part.
435 if !substs
.is_empty() && !generics
.params
.is_empty() {
436 let user_type_annotation
= self.probe(|_
| {
437 let user_substs
= UserSubsts
{
438 substs
: InternalSubsts
::for_item(self.tcx
, pick
.item
.def_id
, |param
, _
| {
439 let i
= param
.index
as usize;
440 if i
< generics
.parent_count
{
441 self.fcx
.var_for_def(DUMMY_SP
, param
)
446 user_self_ty
: None
, // not relevant here
449 self.fcx
.canonicalize_user_type_annotation(UserType
::TypeOf(
455 debug
!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation
);
456 self.fcx
.write_user_type_annotation(self.call_expr
.hir_id
, user_type_annotation
);
459 self.normalize(self.span
, substs
)
465 method_self_ty
: Ty
<'tcx
>,
466 pick
: &probe
::Pick
<'tcx
>,
467 substs
: SubstsRef
<'tcx
>,
470 "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
471 self_ty
, method_self_ty
, self.span
, pick
473 let cause
= self.cause(
475 ObligationCauseCode
::UnifyReceiver(Box
::new(UnifyReceiverContext
{
476 assoc_item
: pick
.item
,
477 param_env
: self.param_env
,
481 match self.at(&cause
, self.param_env
).sup(DefineOpaqueTypes
::No
, method_self_ty
, self_ty
) {
482 Ok(InferOk { obligations, value: () }
) => {
483 self.register_predicates(obligations
);
486 // FIXME(arbitrary_self_types): We probably should limit the
487 // situations where this can occur by adding additional restrictions
488 // to the feature, like the self type can't reference method substs.
489 if self.tcx
.features().arbitrary_self_types
{
491 .report_mismatched_types(&cause
, method_self_ty
, self_ty
, terr
)
496 "{} was a subtype of {} but now is not?",
505 // NOTE: this returns the *unnormalized* predicates and method sig. Because of
506 // inference guessing, the predicates and method signature can't be normalized
507 // until we unify the `Self` type.
508 fn instantiate_method_sig(
510 pick
: &probe
::Pick
<'tcx
>,
511 all_substs
: SubstsRef
<'tcx
>,
512 ) -> (ty
::FnSig
<'tcx
>, ty
::InstantiatedPredicates
<'tcx
>) {
513 debug
!("instantiate_method_sig(pick={:?}, all_substs={:?})", pick
, all_substs
);
515 // Instantiate the bounds on the method with the
516 // type/early-bound-regions substitutions performed. There can
517 // be no late-bound regions appearing here.
518 let def_id
= pick
.item
.def_id
;
519 let method_predicates
= self.tcx
.predicates_of(def_id
).instantiate(self.tcx
, all_substs
);
521 debug
!("method_predicates after subst = {:?}", method_predicates
);
523 let sig
= self.tcx
.fn_sig(def_id
).subst(self.tcx
, all_substs
);
524 debug
!("type scheme substituted, sig={:?}", sig
);
526 let sig
= self.instantiate_binder_with_fresh_vars(sig
);
527 debug
!("late-bound lifetimes from method instantiated, sig={:?}", sig
);
529 (sig
, method_predicates
)
535 all_substs
: SubstsRef
<'tcx
>,
536 method_predicates
: ty
::InstantiatedPredicates
<'tcx
>,
540 "add_obligations: fty={:?} all_substs={:?} method_predicates={:?} def_id={:?}",
541 fty
, all_substs
, method_predicates
, def_id
544 // FIXME: could replace with the following, but we already calculated `method_predicates`,
545 // so we just call `predicates_for_generics` directly to avoid redoing work.
546 // `self.add_required_obligations(self.span, def_id, &all_substs);`
547 for obligation
in traits
::predicates_for_generics(
549 let code
= if span
.is_dummy() {
550 ObligationCauseCode
::ExprItemObligation(def_id
, self.call_expr
.hir_id
, idx
)
552 ObligationCauseCode
::ExprBindingObligation(
555 self.call_expr
.hir_id
,
559 traits
::ObligationCause
::new(self.span
, self.body_id
, code
)
564 self.register_predicate(obligation
);
567 // this is a projection from a trait reference, so we have to
568 // make sure that the trait reference inputs are well-formed.
569 self.add_wf_bounds(all_substs
, self.call_expr
);
571 // the function type must also be well-formed (this is not
572 // implied by the substs being well-formed because of inherent
573 // impls and late-bound regions - see issue #28609).
574 self.register_wf_obligation(fty
.into(), self.span
, traits
::WellFormed(None
));
577 ///////////////////////////////////////////////////////////////////////////
580 fn predicates_require_illegal_sized_bound(
582 predicates
: ty
::InstantiatedPredicates
<'tcx
>,
584 let sized_def_id
= self.tcx
.lang_items().sized_trait()?
;
586 traits
::elaborate(self.tcx
, predicates
.predicates
.iter().copied())
587 // We don't care about regions here.
588 .filter_map(|pred
| match pred
.kind().skip_binder() {
589 ty
::PredicateKind
::Clause(ty
::Clause
::Trait(trait_pred
))
590 if trait_pred
.def_id() == sized_def_id
=>
592 let span
= predicates
594 .find_map(|(p
, span
)| if p
== pred { Some(span) }
else { None }
)
595 .unwrap_or(rustc_span
::DUMMY_SP
);
596 Some((trait_pred
, span
))
600 .find_map(|(trait_pred
, span
)| match trait_pred
.self_ty().kind() {
601 ty
::Dynamic(..) => Some(span
),
606 fn enforce_illegal_method_limitations(&self, pick
: &probe
::Pick
<'_
>) {
607 // Disallow calls to the method `drop` defined in the `Drop` trait.
608 if let Some(trait_def_id
) = pick
.item
.trait_container(self.tcx
) {
609 callee
::check_legal_trait_for_method_call(
612 Some(self.self_expr
.span
),
621 source_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
622 target_trait_def_id
: DefId
,
623 ) -> ty
::PolyTraitRef
<'tcx
> {
624 let upcast_trait_refs
=
625 traits
::upcast_choices(self.tcx
, source_trait_ref
, target_trait_def_id
);
627 // must be exactly one trait ref or we'd get an ambig error etc
628 if upcast_trait_refs
.len() != 1 {
631 "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
638 upcast_trait_refs
.into_iter().next().unwrap()
641 fn instantiate_binder_with_fresh_vars
<T
>(&self, value
: ty
::Binder
<'tcx
, T
>) -> T
643 T
: TypeFoldable
<TyCtxt
<'tcx
>> + Copy
,
645 self.fcx
.instantiate_binder_with_fresh_vars(self.span
, infer
::FnCall
, value
)