mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
fix method substs
This commit is contained in:
parent
be5a45d392
commit
37b40e471a
@ -24,7 +24,7 @@ use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, UserType,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
|
||||
use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
@ -161,47 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
|
||||
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
|
||||
self.write_substs(hir_id, method.substs);
|
||||
|
||||
// When the method is confirmed, the `method.substs` includes
|
||||
// parameters from not just the method, but also the impl of
|
||||
// the method -- in particular, the `Self` type will be fully
|
||||
// resolved. However, those are not something that the "user
|
||||
// specified" -- i.e., those types come from the inferred type
|
||||
// of the receiver, not something the user wrote. So when we
|
||||
// create the user-substs, we want to replace those earlier
|
||||
// types with just the types that the user actually wrote --
|
||||
// that is, those that appear on the *method itself*.
|
||||
//
|
||||
// As an example, if the user wrote something like
|
||||
// `foo.bar::<u32>(...)` -- the `Self` type here will be the
|
||||
// type of `foo` (possibly adjusted), but we don't want to
|
||||
// include that. We want just the `[_, u32]` part.
|
||||
if !method.substs.is_empty() {
|
||||
let method_generics = self.tcx.generics_of(method.def_id);
|
||||
if !method_generics.params.is_empty() {
|
||||
let user_type_annotation = self.probe(|_| {
|
||||
let user_substs = UserSubsts {
|
||||
substs: InternalSubsts::for_item(self.tcx, method.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < method_generics.parent_count {
|
||||
self.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
method.substs[i]
|
||||
}
|
||||
}),
|
||||
user_self_ty: None, // not relevant here
|
||||
};
|
||||
|
||||
self.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
method.def_id,
|
||||
user_substs,
|
||||
))
|
||||
});
|
||||
|
||||
debug!("write_method_call: user_type_annotation={:?}", user_type_annotation);
|
||||
self.write_user_type_annotation(hir_id, user_type_annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_substs(&self, node_id: hir::HirId, substs: SubstsRef<'tcx>) {
|
||||
|
@ -12,7 +12,8 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::{self, SubstsRef};
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_middle::ty::{InternalSubsts, UserSubsts, UserType};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use std::iter;
|
||||
@ -397,6 +398,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
self.cfcx.var_for_def(self.cfcx.span, param)
|
||||
}
|
||||
}
|
||||
|
||||
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
pick.item.def_id,
|
||||
@ -406,7 +408,45 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
&arg_count_correct,
|
||||
&mut MethodSubstsCtxt { cfcx: self, pick, seg },
|
||||
);
|
||||
// FIXME(aliemjay): Type annotation should be registered before normalization.
|
||||
|
||||
// When the method is confirmed, the `substs` includes
|
||||
// parameters from not just the method, but also the impl of
|
||||
// the method -- in particular, the `Self` type will be fully
|
||||
// resolved. However, those are not something that the "user
|
||||
// specified" -- i.e., those types come from the inferred type
|
||||
// of the receiver, not something the user wrote. So when we
|
||||
// create the user-substs, we want to replace those earlier
|
||||
// types with just the types that the user actually wrote --
|
||||
// that is, those that appear on the *method itself*.
|
||||
//
|
||||
// As an example, if the user wrote something like
|
||||
// `foo.bar::<u32>(...)` -- the `Self` type here will be the
|
||||
// type of `foo` (possibly adjusted), but we don't want to
|
||||
// include that. We want just the `[_, u32]` part.
|
||||
if !substs.is_empty() && !generics.params.is_empty() {
|
||||
let user_type_annotation = self.probe(|_| {
|
||||
let user_substs = UserSubsts {
|
||||
substs: InternalSubsts::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < generics.parent_count {
|
||||
self.fcx.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
substs[i]
|
||||
}
|
||||
}),
|
||||
user_self_ty: None, // not relevant here
|
||||
};
|
||||
|
||||
self.fcx.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
pick.item.def_id,
|
||||
user_substs,
|
||||
))
|
||||
});
|
||||
|
||||
debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation);
|
||||
self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
|
||||
}
|
||||
|
||||
self.normalize(self.span, substs)
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,8 @@ fn test_variants<'a, 'b, 'c>() {
|
||||
}
|
||||
|
||||
fn test_method_call<'a>(x: MyTy<()>) {
|
||||
// FIXME This should fail.
|
||||
x.method2::<Ty<'a>>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
|
@ -114,6 +114,14 @@ help: the following changes may resolve your lifetime errors
|
||||
= help: replace `'b` with `'static`
|
||||
= help: replace `'c` with `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:71:7
|
||||
|
|
||||
LL | fn test_method_call<'a>(x: MyTy<()>) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | x.method2::<Ty<'a>>();
|
||||
| ^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:88:5
|
||||
|
|
||||
@ -190,5 +198,5 @@ help: the following changes may resolve your lifetime errors
|
||||
= help: replace `'b` with `'static`
|
||||
= help: replace `'c` with `'static`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user