mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
Record method resolution for call expressions
This commit is contained in:
parent
9814d79841
commit
54da0bfbf0
@ -347,6 +347,7 @@ pub mod known {
|
||||
recursion_limit,
|
||||
feature,
|
||||
// known methods of lang items
|
||||
call_once,
|
||||
eq,
|
||||
ne,
|
||||
ge,
|
||||
|
@ -63,7 +63,7 @@ impl<D> TyBuilder<D> {
|
||||
}
|
||||
|
||||
fn build_internal(self) -> (D, Substitution) {
|
||||
assert_eq!(self.vec.len(), self.param_kinds.len());
|
||||
assert_eq!(self.vec.len(), self.param_kinds.len(), "{:?}", &self.param_kinds);
|
||||
for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
|
||||
self.assert_match_kind(a, e);
|
||||
}
|
||||
@ -282,6 +282,21 @@ impl TyBuilder<Tuple> {
|
||||
let (Tuple(size), subst) = self.build_internal();
|
||||
TyKind::Tuple(size, subst).intern(Interner)
|
||||
}
|
||||
|
||||
pub fn tuple_with<I>(elements: I) -> Ty
|
||||
where
|
||||
I: IntoIterator<Item = Ty>,
|
||||
<I as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
let elements = elements.into_iter();
|
||||
let len = elements.len();
|
||||
let mut b =
|
||||
TyBuilder::new(Tuple(len), iter::repeat(ParamKind::Type).take(len).collect(), None);
|
||||
for e in elements {
|
||||
b = b.push(e);
|
||||
}
|
||||
b.build()
|
||||
}
|
||||
}
|
||||
|
||||
impl TyBuilder<TraitId> {
|
||||
|
@ -331,11 +331,18 @@ impl<'a> InferenceContext<'a> {
|
||||
derefed_callee.callable_sig(self.db).map_or(false, |sig| sig.is_varargs)
|
||||
|| res.is_none();
|
||||
let (param_tys, ret_ty) = match res {
|
||||
Some(res) => {
|
||||
Some((func, params, ret_ty)) => {
|
||||
let adjustments = auto_deref_adjust_steps(&derefs);
|
||||
// FIXME: Handle call adjustments for Fn/FnMut
|
||||
self.write_expr_adj(*callee, adjustments);
|
||||
res
|
||||
if let Some((trait_, func)) = func {
|
||||
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
||||
.push(callee_ty.clone())
|
||||
.push(TyBuilder::tuple_with(params.iter().cloned()))
|
||||
.build();
|
||||
self.write_method_resolution(tgt_expr, func, subst.clone());
|
||||
}
|
||||
(params, ret_ty)
|
||||
}
|
||||
None => (Vec::new(), self.err_ty()), // FIXME diagnostic
|
||||
};
|
||||
@ -586,6 +593,7 @@ impl<'a> InferenceContext<'a> {
|
||||
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
|
||||
}
|
||||
Expr::Try { expr } => {
|
||||
// FIXME: Note down method resolution her
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
|
||||
}
|
||||
@ -626,6 +634,7 @@ impl<'a> InferenceContext<'a> {
|
||||
Expr::UnaryOp { expr, op } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
let inner_ty = self.resolve_ty_shallow(&inner_ty);
|
||||
// FIXME: Note down method resolution her
|
||||
match op {
|
||||
UnaryOp::Deref => {
|
||||
autoderef::deref(&mut self.table, inner_ty).unwrap_or_else(|| self.err_ty())
|
||||
@ -732,6 +741,7 @@ impl<'a> InferenceContext<'a> {
|
||||
}
|
||||
}
|
||||
Expr::Index { base, index } => {
|
||||
// FIXME: note down method resolution for the `index`/`index_mut` function
|
||||
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
||||
let index_ty = self.infer_expr(*index, &Expectation::none());
|
||||
|
||||
|
@ -8,6 +8,7 @@ use chalk_ir::{
|
||||
};
|
||||
use chalk_solve::infer::ParameterEnaVariableExt;
|
||||
use ena::unify::UnifyKey;
|
||||
use hir_def::{FunctionId, TraitId};
|
||||
use hir_expand::name;
|
||||
use stdx::never;
|
||||
|
||||
@ -626,18 +627,26 @@ impl<'a> InferenceTable<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
||||
pub(crate) fn callable_sig(
|
||||
&mut self,
|
||||
ty: &Ty,
|
||||
num_args: usize,
|
||||
) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
|
||||
match ty.callable_sig(self.db) {
|
||||
Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
|
||||
Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
|
||||
None => self.callable_sig_from_fn_trait(ty, num_args),
|
||||
}
|
||||
}
|
||||
|
||||
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
||||
fn callable_sig_from_fn_trait(
|
||||
&mut self,
|
||||
ty: &Ty,
|
||||
num_args: usize,
|
||||
) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
|
||||
let krate = self.trait_env.krate;
|
||||
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
||||
let output_assoc_type =
|
||||
self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
|
||||
let trait_data = self.db.trait_data(fn_once_trait);
|
||||
let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
|
||||
|
||||
let mut arg_tys = vec![];
|
||||
let arg_ty = TyBuilder::tuple(num_args)
|
||||
@ -675,7 +684,11 @@ impl<'a> InferenceTable<'a> {
|
||||
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
|
||||
self.register_obligation(obligation.goal);
|
||||
let return_ty = self.normalize_projection_ty(projection);
|
||||
Some((arg_tys, return_ty))
|
||||
Some((
|
||||
Some(fn_once_trait).zip(trait_data.method_by_name(&name!(call_once))),
|
||||
arg_tys,
|
||||
return_ty,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -986,14 +986,13 @@ fn main() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn method_resolution_encountering_fn_type() {
|
||||
fn explicit_fn_once_call_fn_item() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs
|
||||
//- minicore: fn
|
||||
fn foo() {}
|
||||
trait FnOnce { fn call(self); }
|
||||
fn test() { foo.call(); }
|
||||
//^^^^^^^^^^ {unknown}
|
||||
fn test() { foo.call_once(); }
|
||||
//^^^^^^^^^^^^^^^ ()
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -1757,25 +1757,19 @@ fn test() {
|
||||
fn fn_trait() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
trait FnOnce<Args> {
|
||||
type Output;
|
||||
|
||||
fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
|
||||
}
|
||||
//- minicore: fn
|
||||
|
||||
fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
|
||||
f.call_once((1, 2));
|
||||
}"#,
|
||||
expect![[r#"
|
||||
56..60 'self': Self
|
||||
62..66 'args': Args
|
||||
149..150 'f': F
|
||||
155..183 '{ ...2)); }': ()
|
||||
161..162 'f': F
|
||||
161..180 'f.call...1, 2))': u128
|
||||
173..179 '(1, 2)': (u32, u64)
|
||||
174..175 '1': u32
|
||||
177..178 '2': u64
|
||||
38..39 'f': F
|
||||
44..72 '{ ...2)); }': ()
|
||||
50..51 'f': F
|
||||
50..69 'f.call...1, 2))': u128
|
||||
62..68 '(1, 2)': (u32, u64)
|
||||
63..64 '1': u32
|
||||
66..67 '2': u64
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -1784,12 +1778,7 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
|
||||
fn fn_ptr_and_item() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang="fn_once"]
|
||||
trait FnOnce<Args> {
|
||||
type Output;
|
||||
|
||||
fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
//- minicore: fn
|
||||
|
||||
trait Foo<T> {
|
||||
fn foo(&self) -> T;
|
||||
@ -1815,27 +1804,25 @@ fn test() {
|
||||
opt.map(f);
|
||||
}"#,
|
||||
expect![[r#"
|
||||
74..78 'self': Self
|
||||
80..84 'args': Args
|
||||
139..143 'self': &Self
|
||||
243..247 'self': &Bar<F>
|
||||
260..271 '{ loop {} }': (A1, R)
|
||||
262..269 'loop {}': !
|
||||
267..269 '{}': ()
|
||||
355..359 'self': Opt<T>
|
||||
361..362 'f': F
|
||||
377..388 '{ loop {} }': Opt<U>
|
||||
379..386 'loop {}': !
|
||||
384..386 '{}': ()
|
||||
402..518 '{ ...(f); }': ()
|
||||
412..415 'bar': Bar<fn(u8) -> u32>
|
||||
441..444 'bar': Bar<fn(u8) -> u32>
|
||||
441..450 'bar.foo()': (u8, u32)
|
||||
461..464 'opt': Opt<u8>
|
||||
483..484 'f': fn(u8) -> u32
|
||||
505..508 'opt': Opt<u8>
|
||||
505..515 'opt.map(f)': Opt<u32>
|
||||
513..514 'f': fn(u8) -> u32
|
||||
28..32 'self': &Self
|
||||
132..136 'self': &Bar<F>
|
||||
149..160 '{ loop {} }': (A1, R)
|
||||
151..158 'loop {}': !
|
||||
156..158 '{}': ()
|
||||
244..248 'self': Opt<T>
|
||||
250..251 'f': F
|
||||
266..277 '{ loop {} }': Opt<U>
|
||||
268..275 'loop {}': !
|
||||
273..275 '{}': ()
|
||||
291..407 '{ ...(f); }': ()
|
||||
301..304 'bar': Bar<fn(u8) -> u32>
|
||||
330..333 'bar': Bar<fn(u8) -> u32>
|
||||
330..339 'bar.foo()': (u8, u32)
|
||||
350..353 'opt': Opt<u8>
|
||||
372..373 'f': fn(u8) -> u32
|
||||
394..397 'opt': Opt<u8>
|
||||
394..404 'opt.map(f)': Opt<u32>
|
||||
402..403 'f': fn(u8) -> u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -2411,7 +2411,7 @@ impl Local {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DeriveHelper {
|
||||
pub(crate) derive: MacroId,
|
||||
pub(crate) idx: usize,
|
||||
pub(crate) idx: u32,
|
||||
}
|
||||
|
||||
impl DeriveHelper {
|
||||
@ -2421,15 +2421,18 @@ impl DeriveHelper {
|
||||
|
||||
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
||||
match self.derive {
|
||||
MacroId::Macro2Id(it) => {
|
||||
db.macro2_data(it).helpers.as_deref().and_then(|it| it.get(self.idx)).cloned()
|
||||
}
|
||||
MacroId::Macro2Id(it) => db
|
||||
.macro2_data(it)
|
||||
.helpers
|
||||
.as_deref()
|
||||
.and_then(|it| it.get(self.idx as usize))
|
||||
.cloned(),
|
||||
MacroId::MacroRulesId(_) => None,
|
||||
MacroId::ProcMacroId(proc_macro) => db
|
||||
.proc_macro_data(proc_macro)
|
||||
.helpers
|
||||
.as_deref()
|
||||
.and_then(|it| it.get(self.idx))
|
||||
.and_then(|it| it.get(self.idx as usize))
|
||||
.cloned(),
|
||||
}
|
||||
.unwrap_or_else(|| Name::missing())
|
||||
@ -2440,7 +2443,7 @@ impl DeriveHelper {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct BuiltinAttr {
|
||||
krate: Option<CrateId>,
|
||||
idx: usize,
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
impl BuiltinAttr {
|
||||
@ -2449,7 +2452,8 @@ impl BuiltinAttr {
|
||||
if let builtin @ Some(_) = Self::builtin(name) {
|
||||
return builtin;
|
||||
}
|
||||
let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?;
|
||||
let idx =
|
||||
db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32;
|
||||
Some(BuiltinAttr { krate: Some(krate.id), idx })
|
||||
}
|
||||
|
||||
@ -2457,21 +2461,21 @@ impl BuiltinAttr {
|
||||
hir_def::builtin_attr::INERT_ATTRIBUTES
|
||||
.iter()
|
||||
.position(|tool| tool.name == name)
|
||||
.map(|idx| BuiltinAttr { krate: None, idx })
|
||||
.map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
|
||||
}
|
||||
|
||||
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
|
||||
// FIXME: Return a `Name` here
|
||||
match self.krate {
|
||||
Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(),
|
||||
None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name),
|
||||
Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
|
||||
None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx as usize].name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
|
||||
match self.krate {
|
||||
Some(_) => None,
|
||||
None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template),
|
||||
None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx as usize].template),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2479,7 +2483,7 @@ impl BuiltinAttr {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ToolModule {
|
||||
krate: Option<CrateId>,
|
||||
idx: usize,
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
impl ToolModule {
|
||||
@ -2488,7 +2492,8 @@ impl ToolModule {
|
||||
if let builtin @ Some(_) = Self::builtin(name) {
|
||||
return builtin;
|
||||
}
|
||||
let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?;
|
||||
let idx =
|
||||
db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
|
||||
Some(ToolModule { krate: Some(krate.id), idx })
|
||||
}
|
||||
|
||||
@ -2496,14 +2501,14 @@ impl ToolModule {
|
||||
hir_def::builtin_attr::TOOL_MODULES
|
||||
.iter()
|
||||
.position(|&tool| tool == name)
|
||||
.map(|idx| ToolModule { krate: None, idx })
|
||||
.map(|idx| ToolModule { krate: None, idx: idx as u32 })
|
||||
}
|
||||
|
||||
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
|
||||
// FIXME: Return a `Name` here
|
||||
match self.krate {
|
||||
Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(),
|
||||
None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]),
|
||||
Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
|
||||
None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx as usize]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2831,7 +2836,7 @@ impl Impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TraitRef {
|
||||
env: Arc<TraitEnvironment>,
|
||||
trait_ref: hir_ty::TraitRef,
|
||||
|
@ -628,7 +628,7 @@ impl SourceAnalyzer {
|
||||
{
|
||||
return Some(PathResolution::DeriveHelper(DeriveHelper {
|
||||
derive: *macro_id,
|
||||
idx,
|
||||
idx: idx as u32,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ pub enum Definition {
|
||||
TypeAlias(TypeAlias),
|
||||
BuiltinType(BuiltinType),
|
||||
SelfType(Impl),
|
||||
Local(Local),
|
||||
GenericParam(GenericParam),
|
||||
Local(Local),
|
||||
Label(Label),
|
||||
DeriveHelper(DeriveHelper),
|
||||
BuiltinAttr(BuiltinAttr),
|
||||
|
@ -106,6 +106,11 @@ pub mod marker {
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
}
|
||||
// endregion:copy
|
||||
|
||||
// region:fn
|
||||
#[lang = "tuple_trait"]
|
||||
pub trait Tuple {}
|
||||
// endregion:fn
|
||||
}
|
||||
|
||||
// region:default
|
||||
@ -329,19 +334,26 @@ pub mod ops {
|
||||
|
||||
// region:fn
|
||||
mod function {
|
||||
use crate::marker::Tuple;
|
||||
|
||||
#[lang = "fn"]
|
||||
#[fundamental]
|
||||
pub trait Fn<Args>: FnMut<Args> {}
|
||||
pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_mut"]
|
||||
#[fundamental]
|
||||
pub trait FnMut<Args>: FnOnce<Args> {}
|
||||
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[fundamental]
|
||||
pub trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args: Tuple> {
|
||||
#[lang = "fn_once_output"]
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
}
|
||||
pub use self::function::{Fn, FnMut, FnOnce};
|
||||
|
Loading…
Reference in New Issue
Block a user