Skip to content

Commit b522ee1

Browse files
committed
Check namespaces when resolving associated items in typeck
1 parent cbf5d39 commit b522ee1

File tree

10 files changed

+127
-25
lines changed

10 files changed

+127
-25
lines changed

src/librustc_typeck/astconv.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use hir;
1818
use hir::def::Def;
1919
use hir::def_id::DefId;
2020
use middle::resolve_lifetime as rl;
21+
use namespace::Namespace;
2122
use rustc::ty::subst::{Kind, Subst, Substs};
2223
use rustc::traits;
2324
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
@@ -827,8 +828,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
827828

828829
let trait_did = bound.0.def_id;
829830
let (assoc_ident, def_scope) = tcx.adjust(assoc_name, trait_did, ref_id);
830-
let item = tcx.associated_items(trait_did).find(|i| i.name.to_ident() == assoc_ident)
831-
.expect("missing associated type");
831+
let item = tcx.associated_items(trait_did).find(|i| {
832+
Namespace::from(i.kind) == Namespace::Type &&
833+
i.name.to_ident() == assoc_ident
834+
})
835+
.expect("missing associated type");
832836

833837
let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound);
834838
let ty = self.normalize_ty(span, ty);

src/librustc_typeck/check/method/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use check::FnCtxt;
1414
use hir::def::Def;
1515
use hir::def_id::DefId;
16+
use namespace::Namespace;
1617
use rustc::ty::subst::Substs;
1718
use rustc::traits;
1819
use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
@@ -275,7 +276,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
275276
// Trait must have a method named `m_name` and it should not have
276277
// type parameters or early-bound regions.
277278
let tcx = self.tcx;
278-
let method_item = self.associated_item(trait_def_id, m_name).unwrap();
279+
let method_item = self.associated_item(trait_def_id, m_name, Namespace::Value).unwrap();
279280
let def_id = method_item.def_id;
280281
let generics = tcx.generics_of(def_id);
281282
assert_eq!(generics.types.len(), 0);
@@ -371,10 +372,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
371372

372373
/// Find item with name `item_name` defined in impl/trait `def_id`
373374
/// and return it, or `None`, if no such item was defined there.
374-
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name)
375+
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name, ns: Namespace)
375376
-> Option<ty::AssociatedItem> {
376377
self.tcx.associated_items(def_id)
377-
.find(|item| self.tcx.hygienic_eq(item_name, item.name, def_id))
378-
378+
.find(|item| Namespace::from(item.kind) == ns &&
379+
self.tcx.hygienic_eq(item_name, item.name, def_id))
379380
}
380381
}

src/librustc_typeck/check/method/probe.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use super::suggest;
1616
use check::FnCtxt;
1717
use hir::def_id::DefId;
1818
use hir::def::Def;
19+
use namespace::Namespace;
1920
use rustc::ty::subst::{Subst, Substs};
2021
use rustc::traits::{self, ObligationCause};
2122
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
@@ -1317,11 +1318,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
13171318
self.tcx.associated_items(def_id)
13181319
.filter(|x| {
13191320
let dist = lev_distance(&*name.as_str(), &x.name.as_str());
1320-
dist > 0 && dist <= max_dist
1321+
Namespace::from(x.kind) == Namespace::Value && dist > 0
1322+
&& dist <= max_dist
13211323
})
13221324
.collect()
13231325
} else {
1324-
self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x])
1326+
self.fcx
1327+
.associated_item(def_id, name, Namespace::Value)
1328+
.map_or(Vec::new(), |x| vec![x])
13251329
}
13261330
} else {
13271331
self.tcx.associated_items(def_id).collect()

src/librustc_typeck/check/method/suggest.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
1717
use hir::def::Def;
1818
use hir::def_id::{CRATE_DEF_INDEX, DefId};
1919
use middle::lang_items::FnOnceTraitLangItem;
20+
use namespace::Namespace;
2021
use rustc::traits::{Obligation, SelectionContext};
2122
use util::nodemap::FxHashSet;
2223

@@ -92,12 +93,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9293
CandidateSource::ImplSource(impl_did) => {
9394
// Provide the best span we can. Use the item, if local to crate, else
9495
// the impl, if local to crate (item may be defaulted), else nothing.
95-
let item = self.associated_item(impl_did, item_name)
96+
let item = self.associated_item(impl_did, item_name, Namespace::Value)
9697
.or_else(|| {
9798
self.associated_item(
9899
self.tcx.impl_trait_ref(impl_did).unwrap().def_id,
99-
100-
item_name
100+
item_name,
101+
Namespace::Value,
101102
)
102103
}).unwrap();
103104
let note_span = self.tcx.hir.span_if_local(item.def_id).or_else(|| {
@@ -127,7 +128,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
127128
}
128129
}
129130
CandidateSource::TraitSource(trait_did) => {
130-
let item = self.associated_item(trait_did, item_name).unwrap();
131+
let item = self
132+
.associated_item(trait_did, item_name, Namespace::Value)
133+
.unwrap();
131134
let item_span = self.tcx.def_span(item.def_id);
132135
span_note!(err,
133136
item_span,
@@ -402,7 +405,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
402405
// implementing a trait would be legal but is rejected
403406
// here).
404407
(type_is_local || info.def_id.is_local())
405-
&& self.associated_item(info.def_id, item_name).is_some()
408+
&& self.associated_item(info.def_id, item_name, Namespace::Value).is_some()
406409
})
407410
.collect::<Vec<_>>();
408411

src/librustc_typeck/check/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ use astconv::AstConv;
8888
use hir::def::{Def, CtorKind};
8989
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
9090
use rustc_back::slice::ref_slice;
91+
use namespace::Namespace;
9192
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
9293
use rustc::infer::type_variable::{TypeVariableOrigin};
9394
use rustc::middle::region;
@@ -1293,7 +1294,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12931294
for impl_item in impl_items() {
12941295
let ty_impl_item = tcx.associated_item(tcx.hir.local_def_id(impl_item.id));
12951296
let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id)
1296-
.find(|ac| tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id));
1297+
.find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) &&
1298+
tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id))
1299+
.or_else(|| {
1300+
// Not compatible, but needed for the error message
1301+
tcx.associated_items(impl_trait_ref.def_id)
1302+
.find(|ac| tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id))
1303+
});
12971304

12981305
// Check that impl definition matches trait definition
12991306
if let Some(ty_trait_item) = ty_trait_item {

src/librustc_typeck/coherence/inherent_impls_overlap.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use namespace::Namespace;
1112
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
1213
use rustc::hir;
1314
use rustc::hir::itemlikevisit::ItemLikeVisitor;
1415
use rustc::traits;
15-
use rustc::ty::{self, TyCtxt};
16+
use rustc::ty::TyCtxt;
1617

1718
pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1819
crate_num: CrateNum) {
@@ -28,19 +29,10 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> {
2829
impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
2930
fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
3031
overlap: traits::OverlapResult) {
31-
#[derive(Copy, Clone, PartialEq)]
32-
enum Namespace {
33-
Type,
34-
Value,
35-
}
3632

3733
let name_and_namespace = |def_id| {
3834
let item = self.tcx.associated_item(def_id);
39-
(item.name, match item.kind {
40-
ty::AssociatedKind::Type => Namespace::Type,
41-
ty::AssociatedKind::Const |
42-
ty::AssociatedKind::Method => Namespace::Value,
43-
})
35+
(item.name, Namespace::from(item.kind))
4436
};
4537

4638
let impl_items1 = self.tcx.associated_item_def_ids(impl1);

src/librustc_typeck/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ mod constrained_type_params;
123123
mod impl_wf_check;
124124
mod coherence;
125125
mod variance;
126+
mod namespace;
126127

127128
pub struct TypeAndSubsts<'tcx> {
128129
substs: &'tcx Substs<'tcx>,

src/librustc_typeck/namespace.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::hir;
12+
use rustc::ty;
13+
14+
// Whether an item exists in the type or value namespace.
15+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
16+
pub enum Namespace {
17+
Type,
18+
Value,
19+
}
20+
21+
impl From<ty::AssociatedKind> for Namespace {
22+
fn from(a_kind: ty::AssociatedKind) -> Self {
23+
match a_kind {
24+
ty::AssociatedKind::Type => Namespace::Type,
25+
ty::AssociatedKind::Const |
26+
ty::AssociatedKind::Method => Namespace::Value,
27+
}
28+
}
29+
}
30+
31+
impl<'a> From <&'a hir::ImplItemKind> for Namespace {
32+
fn from(impl_kind: &'a hir::ImplItemKind) -> Self {
33+
match *impl_kind {
34+
hir::ImplItemKind::Type(..) => Namespace::Type,
35+
hir::ImplItemKind::Const(..) |
36+
hir::ImplItemKind::Method(..) => Namespace::Value,
37+
}
38+
}
39+
}

src/test/run-pass/issue-35600.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo {
12+
type bar;
13+
fn bar();
14+
}
15+
16+
impl Foo for () {
17+
type bar = ();
18+
fn bar() {}
19+
}
20+
21+
fn main() {
22+
let x: <() as Foo>::bar = ();
23+
<()>::bar();
24+
}

src/test/run-pass/issue-44247.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait T {
12+
type X;
13+
const X: Self::X;
14+
}
15+
fn foo<X: T>() {
16+
let _: X::X = X::X;
17+
}
18+
19+
trait S {
20+
const X: Self::X;
21+
type X;
22+
}
23+
fn bar<X: S>() {
24+
let _: X::X = X::X;
25+
}
26+
27+
fn main() {}

0 commit comments

Comments
 (0)