mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 12:18:33 +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::{
|
use rustc_middle::ty::{
|
||||||
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, UserType,
|
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_session::lint;
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::hygiene::DesugaringKind;
|
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>) {
|
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_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
|
||||||
self.write_substs(hir_id, method.substs);
|
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>) {
|
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::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::subst::{self, SubstsRef};
|
use rustc_middle::ty::subst::{self, SubstsRef};
|
||||||
use rustc_middle::ty::{self, GenericParamDefKind, Ty};
|
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 rustc_trait_selection::traits;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@ -397,6 +398,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
self.cfcx.var_for_def(self.cfcx.span, param)
|
self.cfcx.var_for_def(self.cfcx.span, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
|
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
pick.item.def_id,
|
pick.item.def_id,
|
||||||
@ -406,7 +408,45 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
&arg_count_correct,
|
&arg_count_correct,
|
||||||
&mut MethodSubstsCtxt { cfcx: self, pick, seg },
|
&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)
|
self.normalize(self.span, substs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ fn test_variants<'a, 'b, 'c>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_method_call<'a>(x: MyTy<()>) {
|
fn test_method_call<'a>(x: MyTy<()>) {
|
||||||
// FIXME This should fail.
|
|
||||||
x.method2::<Ty<'a>>();
|
x.method2::<Ty<'a>>();
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_struct_path<'a, 'b, 'c, 'd>() {
|
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 `'b` with `'static`
|
||||||
= help: replace `'c` 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
|
error: lifetime may not live long enough
|
||||||
--> $DIR/normalization-2.rs:88:5
|
--> $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 `'b` with `'static`
|
||||||
= help: replace `'c` 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