Skip to content

Commit efc4575

Browse files
author
Ariel Ben-Yehuda
committed
rewrite the method-receiver matching code
the old code was *so terrible*.
1 parent 2ced149 commit efc4575

File tree

14 files changed

+164
-359
lines changed

14 files changed

+164
-359
lines changed

src/librustc/middle/ty/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,6 @@ pub struct RegionParameterDef {
633633
impl RegionParameterDef {
634634
pub fn to_early_bound_region(&self) -> ty::Region {
635635
ty::ReEarlyBound(ty::EarlyBoundRegion {
636-
def_id: self.def_id,
637636
space: self.space,
638637
index: self.index,
639638
name: self.name,

src/librustc/middle/ty/sty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,6 @@ pub enum Region {
695695

696696
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
697697
pub struct EarlyBoundRegion {
698-
pub def_id: DefId,
699698
pub space: subst::ParamSpace,
700699
pub index: u32,
701700
pub name: Name,

src/librustc/util/ppaux.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ impl fmt::Debug for ty::Region {
462462
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
463463
match *self {
464464
ty::ReEarlyBound(ref data) => {
465-
write!(f, "ReEarlyBound({:?}, {:?}, {}, {})",
466-
data.def_id,
465+
write!(f, "ReEarlyBound({:?}, {}, {})",
467466
data.space,
468467
data.index,
469468
data.name)

src/librustc_driver/test.rs

-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
289289
-> ty::Region {
290290
let name = token::intern(name);
291291
ty::ReEarlyBound(ty::EarlyBoundRegion {
292-
def_id: self.infcx.tcx.map.local_def_id(ast::DUMMY_NODE_ID),
293292
space: space,
294293
index: index,
295294
name: name,

src/librustc_metadata/tydecode.rs

-2
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
192192
}
193193
'B' => {
194194
assert_eq!(self.next(), '[');
195-
let def_id = self.parse_def();
196195
let space = self.parse_param_space();
197196
assert_eq!(self.next(), '|');
198197
let index = self.parse_u32();
199198
assert_eq!(self.next(), '|');
200199
let name = token::intern(&self.parse_str(']'));
201200
ty::ReEarlyBound(ty::EarlyBoundRegion {
202-
def_id: def_id,
203201
space: space,
204202
index: index,
205203
name: name

src/librustc_metadata/tyencode.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
253253
mywrite!(w, "]");
254254
}
255255
ty::ReEarlyBound(ref data) => {
256-
mywrite!(w, "B[{}|{}|{}|{}]",
257-
(cx.ds)(data.def_id),
256+
mywrite!(w, "B[{}|{}|{}]",
258257
data.space.to_uint(),
259258
data.index,
260259
data.name);

src/librustc_typeck/astconv.rs

+34-69
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use middle::resolve_lifetime as rl;
5757
use middle::privacy::{AllPublic, LastMod};
5858
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
5959
use middle::traits;
60-
use middle::ty::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags};
60+
use middle::ty::{self, Ty, ToPredicate, HasTypeFlags};
6161
use middle::ty::wf::object_region_bounds;
6262
use require_c_abi_if_variadic;
6363
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
@@ -169,10 +169,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
169169
ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id), lifetime.name))
170170
}
171171

172-
Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
173-
let def_id = tcx.map.local_def_id(id);
172+
Some(&rl::DefEarlyBoundRegion(space, index, _)) => {
174173
ty::ReEarlyBound(ty::EarlyBoundRegion {
175-
def_id: def_id,
176174
space: space,
177175
index: index,
178176
name: lifetime.name
@@ -1797,75 +1795,31 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
17971795
// lifetime elision, we can determine it in two ways. First (determined
17981796
// here), if self is by-reference, then the implied output region is the
17991797
// region of the self parameter.
1800-
let mut explicit_self_category_result = None;
1801-
let (self_ty, implied_output_region) = match opt_self_info {
1798+
let (self_ty, explicit_self_category) = match opt_self_info {
18021799
None => (None, None),
1803-
Some(self_info) => {
1804-
// This type comes from an impl or trait; no late-bound
1805-
// regions should be present.
1806-
assert!(!self_info.untransformed_self_ty.has_escaping_regions());
1807-
1808-
// Figure out and record the explicit self category.
1809-
let explicit_self_category =
1810-
determine_explicit_self_category(this, &rb, &self_info);
1811-
explicit_self_category_result = Some(explicit_self_category);
1812-
match explicit_self_category {
1813-
ty::StaticExplicitSelfCategory => {
1814-
(None, None)
1815-
}
1816-
ty::ByValueExplicitSelfCategory => {
1817-
(Some(self_info.untransformed_self_ty), None)
1818-
}
1819-
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
1820-
(Some(this.tcx().mk_ref(
1821-
this.tcx().mk_region(region),
1822-
ty::TypeAndMut {
1823-
ty: self_info.untransformed_self_ty,
1824-
mutbl: mutability
1825-
})),
1826-
Some(region))
1827-
}
1828-
ty::ByBoxExplicitSelfCategory => {
1829-
(Some(this.tcx().mk_box(self_info.untransformed_self_ty)), None)
1830-
}
1831-
}
1832-
}
1800+
Some(self_info) => determine_self_type(this, &rb, self_info)
18331801
};
18341802

18351803
// HACK(eddyb) replace the fake self type in the AST with the actual type.
1836-
let input_params = if self_ty.is_some() {
1804+
let arg_params = if self_ty.is_some() {
18371805
&decl.inputs[1..]
18381806
} else {
18391807
&decl.inputs[..]
18401808
};
1841-
let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None));
1842-
let input_pats: Vec<String> = input_params.iter()
1843-
.map(|a| pprust::pat_to_string(&*a.pat))
1844-
.collect();
1845-
let self_and_input_tys: Vec<Ty> =
1846-
self_ty.into_iter().chain(input_tys).collect();
1847-
1809+
let arg_tys: Vec<Ty> =
1810+
arg_params.iter().map(|a| ty_of_arg(this, &rb, a, None)).collect();
1811+
let arg_pats: Vec<String> =
1812+
arg_params.iter().map(|a| pprust::pat_to_string(&*a.pat)).collect();
18481813

18491814
// Second, if there was exactly one lifetime (either a substitution or a
18501815
// reference) in the arguments, then any anonymous regions in the output
18511816
// have that lifetime.
1852-
let implied_output_region = match implied_output_region {
1853-
Some(r) => Ok(r),
1854-
None => {
1855-
let input_tys = if self_ty.is_some() {
1856-
// Skip the first argument if `self` is present.
1857-
&self_and_input_tys[1..]
1858-
} else {
1859-
&self_and_input_tys[..]
1860-
};
1861-
1862-
find_implied_output_region(this.tcx(), input_tys, input_pats)
1863-
}
1817+
let implied_output_region = match explicit_self_category {
1818+
Some(ty::ByReferenceExplicitSelfCategory(region, _)) => Ok(region),
1819+
_ => find_implied_output_region(this.tcx(), &arg_tys, arg_pats)
18641820
};
18651821

18661822
let output_ty = match decl.output {
1867-
hir::Return(ref output) if output.node == hir::TyInfer =>
1868-
ty::FnConverging(this.ty_infer(None, None, None, output.span)),
18691823
hir::Return(ref output) =>
18701824
ty::FnConverging(convert_ty_with_lifetime_elision(this,
18711825
implied_output_region,
@@ -1878,28 +1832,37 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
18781832
unsafety: unsafety,
18791833
abi: abi,
18801834
sig: ty::Binder(ty::FnSig {
1881-
inputs: self_and_input_tys,
1835+
inputs: self_ty.into_iter().chain(arg_tys).collect(),
18821836
output: output_ty,
18831837
variadic: decl.variadic
18841838
}),
1885-
}, explicit_self_category_result)
1839+
}, explicit_self_category)
18861840
}
18871841

1888-
fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
1889-
rscope: &RegionScope,
1890-
self_info: &SelfInfo<'a, 'tcx>)
1891-
-> ty::ExplicitSelfCategory
1842+
fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx>,
1843+
rscope: &RegionScope,
1844+
self_info: SelfInfo<'a, 'tcx>)
1845+
-> (Option<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
18921846
{
1847+
let self_ty = self_info.untransformed_self_ty;
18931848
return match self_info.explicit_self.node {
1894-
hir::SelfStatic => ty::StaticExplicitSelfCategory,
1895-
hir::SelfValue(_) => ty::ByValueExplicitSelfCategory,
1849+
hir::SelfStatic => (None, Some(ty::StaticExplicitSelfCategory)),
1850+
hir::SelfValue(_) => {
1851+
(Some(self_ty), Some(ty::ByValueExplicitSelfCategory))
1852+
}
18961853
hir::SelfRegion(ref lifetime, mutability, _) => {
18971854
let region =
18981855
opt_ast_region_to_region(this,
18991856
rscope,
19001857
self_info.explicit_self.span,
19011858
lifetime);
1902-
ty::ByReferenceExplicitSelfCategory(region, mutability)
1859+
(Some(this.tcx().mk_ref(
1860+
this.tcx().mk_region(region),
1861+
ty::TypeAndMut {
1862+
ty: self_ty,
1863+
mutbl: mutability
1864+
})),
1865+
Some(ty::ByReferenceExplicitSelfCategory(region, mutability)))
19031866
}
19041867
hir::SelfExplicit(ref ast_type, _) => {
19051868
let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
@@ -1944,15 +1907,17 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
19441907
impl_modifiers,
19451908
method_modifiers);
19461909

1947-
if impl_modifiers >= method_modifiers {
1910+
let category = if impl_modifiers >= method_modifiers {
19481911
ty::ByValueExplicitSelfCategory
19491912
} else {
19501913
match explicit_type.sty {
19511914
ty::TyRef(r, mt) => ty::ByReferenceExplicitSelfCategory(*r, mt.mutbl),
19521915
ty::TyBox(_) => ty::ByBoxExplicitSelfCategory,
19531916
_ => ty::ByValueExplicitSelfCategory,
19541917
}
1955-
}
1918+
};
1919+
1920+
(Some(explicit_type), Some(category))
19561921
}
19571922
};
19581923

src/librustc_typeck/check/wfcheck.rs

+47-3
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
136136

137137
let item = fcx.tcx().impl_or_trait_item(fcx.tcx().map.local_def_id(item_id));
138138

139-
let mut implied_bounds = match item.container() {
140-
ty::TraitContainer(_) => vec![],
141-
ty::ImplContainer(def_id) => impl_implied_bounds(fcx, def_id, span)
139+
let (mut implied_bounds, self_ty) = match item.container() {
140+
ty::TraitContainer(_) => (vec![], fcx.tcx().mk_self_type()),
141+
ty::ImplContainer(def_id) => (impl_implied_bounds(fcx, def_id, span),
142+
fcx.tcx().lookup_item_type(def_id).ty)
142143
};
143144

144145
match item {
@@ -152,6 +153,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
152153
let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
153154
this.check_fn_or_method(fcx, span, &method_ty, &predicates,
154155
free_id_outlive, &mut implied_bounds);
156+
this.check_method_receiver(fcx, span, &method,
157+
free_id_outlive, self_ty);
155158
}
156159
ty::TypeTraitItem(assoc_type) => {
157160
if let Some(ref ty) = assoc_type.ty {
@@ -377,6 +380,47 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
377380
self.check_where_clauses(fcx, span, predicates);
378381
}
379382

383+
fn check_method_receiver<'fcx>(&mut self,
384+
fcx: &FnCtxt<'fcx,'tcx>,
385+
span: Span,
386+
method: &ty::Method<'tcx>,
387+
free_id_outlive: CodeExtent,
388+
self_ty: ty::Ty<'tcx>)
389+
{
390+
// check that the type of the method's receiver matches the
391+
// method's first parameter.
392+
393+
let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
394+
let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
395+
let sig = fcx.tcx().liberate_late_bound_regions(free_id_outlive, &fty.sig);
396+
397+
debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})",
398+
method.name, method.explicit_self, self_ty, sig);
399+
400+
let rcvr_ty = match method.explicit_self {
401+
ty::StaticExplicitSelfCategory => return,
402+
ty::ByValueExplicitSelfCategory => self_ty,
403+
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
404+
fcx.tcx().mk_ref(fcx.tcx().mk_region(region), ty::TypeAndMut {
405+
ty: self_ty,
406+
mutbl: mutability
407+
})
408+
}
409+
ty::ByBoxExplicitSelfCategory => fcx.tcx().mk_box(self_ty)
410+
};
411+
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
412+
let rcvr_ty = fcx.tcx().liberate_late_bound_regions(free_id_outlive,
413+
&ty::Binder(rcvr_ty));
414+
415+
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
416+
417+
let _ = ::require_same_types(
418+
fcx.tcx(), Some(fcx.infcx()), false, span,
419+
sig.inputs[0], rcvr_ty,
420+
|| "mismatched method receiver".to_owned()
421+
);
422+
}
423+
380424
fn check_variances_for_type_defn(&self,
381425
item: &hir::Item,
382426
ast_generics: &hir::Generics)

0 commit comments

Comments
 (0)