2020-06-20 18:29:13 +08:00
|
|
|
//! Some helper functions for `AutoDeref`
|
2017-05-20 20:03:04 +03:00
|
|
|
use super::method::MethodCallee;
|
2020-06-15 21:59:09 +01:00
|
|
|
use super::{FnCtxt, PlaceOp};
|
2016-05-24 14:37:11 +03:00
|
|
|
|
2020-06-20 18:29:13 +08:00
|
|
|
use rustc_infer::infer::InferOk;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
2020-06-20 18:29:13 +08:00
|
|
|
use rustc_middle::ty::{self, Ty};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_span::Span;
|
2020-06-20 18:29:13 +08:00
|
|
|
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
|
2016-05-24 14:37:11 +03:00
|
|
|
|
2017-05-27 10:29:24 +03:00
|
|
|
use std::iter;
|
|
|
|
|
|
2020-06-20 18:29:13 +08:00
|
|
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|
|
|
|
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
2020-07-25 07:04:13 -04:00
|
|
|
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Like `autoderef`, but provides a custom `Span` to use for calls to
|
|
|
|
|
/// an overloaded `Deref` operator
|
|
|
|
|
pub fn autoderef_overloaded_span(
|
|
|
|
|
&'a self,
|
|
|
|
|
span: Span,
|
|
|
|
|
base_ty: Ty<'tcx>,
|
|
|
|
|
overloaded_span: Span,
|
|
|
|
|
) -> Autoderef<'a, 'tcx> {
|
|
|
|
|
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
|
2016-05-24 14:37:11 +03:00
|
|
|
}
|
|
|
|
|
|
2020-06-20 18:29:13 +08:00
|
|
|
pub fn try_overloaded_deref(
|
|
|
|
|
&self,
|
2019-06-14 01:32:15 +03:00
|
|
|
span: Span,
|
|
|
|
|
base_ty: Ty<'tcx>,
|
2020-06-20 18:29:13 +08:00
|
|
|
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
|
|
|
|
|
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
|
2017-05-17 00:54:04 +03:00
|
|
|
}
|
|
|
|
|
|
2017-05-27 10:29:24 +03:00
|
|
|
/// Returns the adjustment steps.
|
2020-06-20 18:29:13 +08:00
|
|
|
pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
|
|
|
|
|
self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef))
|
2017-03-08 14:36:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-14 01:32:15 +03:00
|
|
|
pub fn adjust_steps_as_infer_ok(
|
|
|
|
|
&self,
|
2020-06-20 18:29:13 +08:00
|
|
|
autoderef: &Autoderef<'a, 'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
|
2017-05-17 00:54:04 +03:00
|
|
|
let mut obligations = vec![];
|
2020-06-20 18:29:13 +08:00
|
|
|
let steps = autoderef.steps();
|
|
|
|
|
let targets =
|
|
|
|
|
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
|
|
|
|
|
let steps: Vec<_> = steps
|
2017-05-20 20:03:04 +03:00
|
|
|
.iter()
|
|
|
|
|
.map(|&(source, kind)| {
|
2017-05-17 00:54:04 +03:00
|
|
|
if let AutoderefKind::Overloaded = kind {
|
2020-06-20 18:29:13 +08:00
|
|
|
self.try_overloaded_deref(autoderef.span(), source).and_then(
|
2017-05-27 10:29:24 +03:00
|
|
|
|InferOk { value: method, obligations: o }| {
|
2017-05-17 00:54:04 +03:00
|
|
|
obligations.extend(o);
|
2020-08-03 00:49:11 +02:00
|
|
|
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
|
2020-07-25 07:04:13 -04:00
|
|
|
Some(OverloadedDeref {
|
|
|
|
|
region,
|
|
|
|
|
mutbl,
|
|
|
|
|
span: autoderef.overloaded_span(),
|
|
|
|
|
})
|
2017-05-20 20:03:04 +03:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2017-05-17 00:54:04 +03:00
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
2016-05-24 14:37:11 +03:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
2017-05-27 10:29:24 +03:00
|
|
|
.zip(targets)
|
|
|
|
|
.map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
|
2017-05-17 00:54:04 +03:00
|
|
|
.collect();
|
2019-12-22 17:42:04 -05:00
|
|
|
|
2017-05-17 00:54:04 +03:00
|
|
|
InferOk { obligations, value: steps }
|
2016-05-24 14:37:11 +03:00
|
|
|
}
|
|
|
|
|
}
|