Skip to content

Commit

Permalink
Auto merge of #22172 - eddyb:almost-there, r=nikomatsakis
Browse files Browse the repository at this point in the history
Adds `<module::Type>::method` support and makes `module::Type::method` a shorthand for it.
This is most of #16293, except that chaining multiple associated types is not yet supported.
It also fixes #22563 as `impl`s are no longer treated as modules in resolve.

Unfortunately, this is still a *[breaking-change]*:
* If you used a global path to a primitive type, i.e. `::bool`, `::i32` etc. - that was a bug I had to fix.
Solution: remove the leading `::`.
* If you passed explicit `impl`-side type parameters to an inherent method, e.g.:
```rust
struct Foo<T>(T);
impl<A, B> Foo<(A, B)> {
    fn pair(a: A, b: B) -> Foo<(A, B)> { Foo((a, b)) }
}
Foo::<A, B>::pair(a, b)
// Now that is sugar for:
<Foo<A, B>>::pair(a, b)
// Which isn't valid because `Foo` has only one type parameter.
// Solution: replace with:
Foo::<(A, B)>::pair(a, b)
// And, if possible, remove the explicit type param entirely:
Foo::pair(a, b)
```
* If you used the `QPath`-related `AstBuilder` methods @hugwijst added in #21943.
The methods still exist, but `QPath` was replaced by `QSelf`, with the actual path stored separately.
Solution: unpack the pair returned by `cx.qpath` to get the two arguments for `cx.expr_qpath`.
  • Loading branch information
bors committed Feb 24, 2015
2 parents c9ace05 + 0c6d1f3 commit 0bd1565
Show file tree
Hide file tree
Showing 111 changed files with 2,363 additions and 2,648 deletions.
2 changes: 1 addition & 1 deletion src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ pub trait SliceExt {
fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;

/// Convert `self` into a vector without clones or allocation.
#[unstable(feature = "collections")]
#[stable(feature = "rust1", since = "1.0.0")]
fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ pub trait IteratorExt: Iterator + Sized {
#[unstable(feature = "core", reason = "recent addition")]
fn cloned(self) -> Cloned<Self> where
Self::Item: Deref,
<Self::Item as Deref>::Output: Clone,
<Self::Item as Deref>::Target: Clone,
{
Cloned { it: self }
}
Expand Down
38 changes: 19 additions & 19 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,8 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
}

impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
match self.cx.tcx.def_map.borrow()[path_id].clone() {
fn check_def(&mut self, sp: Span, id: ast::NodeId) {
match self.cx.tcx.def_map.borrow()[id].full_def() {
def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
self.cx.span_lint(IMPROPER_CTYPES, sp,
"found rust type `isize` in foreign module, while \
Expand All @@ -418,7 +418,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
libc::c_uint or libc::c_ulong should be used");
}
def::DefTy(..) => {
let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) {
let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
Some(&ty::atttce_resolved(t)) => t,
_ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
};
Expand All @@ -437,9 +437,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {

impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &ast::Ty) {
match ty.node {
ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id),
_ => (),
if let ast::TyPath(..) = ty.node {
self.check_def(ty.span, ty.id);
}
visit::walk_ty(self, ty);
}
Expand Down Expand Up @@ -683,8 +682,8 @@ impl LintPass for PathStatements {
match s.node {
ast::StmtSemi(ref expr, _) => {
match expr.node {
ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span,
"path statement with no effect"),
ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
"path statement with no effect"),
_ => ()
}
}
Expand Down Expand Up @@ -1001,7 +1000,8 @@ impl LintPass for NonSnakeCase {

fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
if let &ast::PatIdent(_, ref path1, _) = &p.node {
if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) {
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
if let Some(def::DefLocal(_)) = def {
self.check_snake_case(cx, "variable", path1.node, p.span);
}
}
Expand Down Expand Up @@ -1066,8 +1066,8 @@ impl LintPass for NonUpperCaseGlobals {

fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
// Lint for constants that look like binding identifiers (#7526)
match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) {
(&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => {
match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
(&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
path1.node, p.span);
}
Expand Down Expand Up @@ -1227,10 +1227,13 @@ impl LintPass for NonShorthandFieldPatterns {
fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
let def_map = cx.tcx.def_map.borrow();
if let ast::PatStruct(_, ref v, _) = pat.node {
for fieldpat in v.iter()
.filter(|fieldpat| !fieldpat.node.is_shorthand)
.filter(|fieldpat| def_map.get(&fieldpat.node.pat.id)
== Some(&def::DefLocal(fieldpat.node.pat.id))) {
let field_pats = v.iter()
.filter(|fieldpat| !fieldpat.node.is_shorthand)
.filter(|fieldpat| {
let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
def == Some(def::DefLocal(fieldpat.node.pat.id))
});
for fieldpat in field_pats {
if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node {
if ident.node.as_str() == fieldpat.node.ident.as_str() {
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
Expand Down Expand Up @@ -1909,10 +1912,7 @@ impl LintPass for UnconditionalRecursion {
_: ast::Ident,
id: ast::NodeId) -> bool {
tcx.def_map.borrow().get(&id)
.map_or(false, |def| {
let did = def.def_id();
ast_util::is_local(did) && did.node == fn_id
})
.map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
}

// check if the method call `id` refers to method `method_id`
Expand Down
7 changes: 2 additions & 5 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,9 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name {
def.node)
}

pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
-> (ast::Name, def::TraitItemKind) {
pub fn is_static_method(cstore: &cstore::CStore, def: ast::DefId) -> bool {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
&*cdata,
def.node)
decoder::is_static_method(&*cdata, def.node)
}

pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
Expand Down
62 changes: 27 additions & 35 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ enum Family {
StaticMethod, // F
Method, // h
Type, // y
ForeignType, // T
Mod, // m
ForeignMod, // n
Enum, // t
Expand All @@ -145,7 +144,6 @@ fn item_family(item: rbml::Doc) -> Family {
'F' => StaticMethod,
'h' => Method,
'y' => Type,
'T' => ForeignType,
'm' => Mod,
'n' => ForeignMod,
't' => Enum,
Expand Down Expand Up @@ -174,16 +172,13 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
}
}

fn item_sort(item: rbml::Doc) -> char {
fn item_sort(item: rbml::Doc) -> Option<char> {
let mut ret = None;
reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
ret = Some(doc.as_str_slice().as_bytes()[0] as char);
false
});
match ret {
Some(r) => r,
None => panic!("No item_sort found")
}
ret
}

fn item_symbol(item: rbml::Doc) -> String {
Expand Down Expand Up @@ -339,14 +334,16 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
};
match fam {
// We don't bother to get encode/decode the trait id, we don't need it.
Method => DlDef(def::DefMethod(did, None, provenance)),
StaticMethod => DlDef(def::DefStaticMethod(did, provenance)),
_ => panic!()
DlDef(def::DefMethod(did, provenance))
}
Type => {
if item_sort(item) == Some('t') {
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
DlDef(def::DefAssociatedTy(trait_did, did))
} else {
DlDef(def::DefTy(did, false))
}
}
Type | ForeignType => DlDef(def::DefTy(did, false)),
Mod => DlDef(def::DefMod(did)),
ForeignMod => DlDef(def::DefForeignMod(did)),
StructVariant => {
Expand All @@ -357,7 +354,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
DlDef(def::DefVariant(enum_did, did, false))
}
Trait => DlDef(def::DefaultImpl(did)),
Trait => DlDef(def::DefTrait(did)),
Enum => DlDef(def::DefTy(did, true)),
Impl | DefaultImpl => DlImpl(did),
PublicField | InheritedField => DlField,
Expand Down Expand Up @@ -831,8 +828,10 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
tag_item_impl_item, |doc| {
let def_id = item_def_id(doc, cdata);
match item_sort(doc) {
'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
't' => impl_items.push(ty::TypeTraitItemId(def_id)),
Some('r') | Some('p') => {
impl_items.push(ty::MethodTraitItemId(def_id))
}
Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)),
_ => panic!("unknown impl item sort"),
}
true
Expand All @@ -849,22 +848,13 @@ pub fn get_trait_name(intr: Rc<IdentInterner>,
item_name(&*intr, doc)
}

pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId)
-> (ast::Name, def::TraitItemKind) {
pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
let doc = lookup_item(id, cdata.data());
let name = item_name(&*intr, doc);
match item_sort(doc) {
'r' | 'p' => {
let explicit_self = get_explicit_self(doc);
(name, def::TraitItemKind::from_explicit_self_category(explicit_self))
}
't' => (name, def::TypeTraitItemKind),
c => {
panic!("get_trait_item_name_and_kind(): unknown trait item kind \
in metadata: `{}`", c)
Some('r') | Some('p') => {
get_explicit_self(doc) == ty::StaticExplicitSelfCategory
}
_ => false
}
}

Expand All @@ -889,7 +879,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
let vis = item_visibility(method_doc);

match item_sort(method_doc) {
'r' | 'p' => {
Some('r') | Some('p') => {
let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
let fty = doc_method_fty(method_doc, tcx, cdata);
Expand All @@ -906,7 +896,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
container,
provided_source)))
}
't' => {
Some('t') => {
ty::TypeTraitItem(Rc::new(ty::AssociatedType {
name: name,
vis: vis,
Expand All @@ -926,8 +916,10 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
reader::tagged_docs(item, tag_item_trait_item, |mth| {
let def_id = item_def_id(mth, cdata);
match item_sort(mth) {
'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
't' => result.push(ty::TypeTraitItemId(def_id)),
Some('r') | Some('p') => {
result.push(ty::MethodTraitItemId(def_id));
}
Some('t') => result.push(ty::TypeTraitItemId(def_id)),
_ => panic!("unknown trait item sort"),
}
true
Expand Down Expand Up @@ -956,7 +948,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
let did = item_def_id(mth_id, cdata);
let mth = lookup_item(did.node, data);

if item_sort(mth) == 'p' {
if item_sort(mth) == Some('p') {
let trait_item = get_impl_or_trait_item(intr.clone(),
cdata,
did.node,
Expand Down Expand Up @@ -1560,7 +1552,7 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
match maybe_find_item(id, items) {
None => false,
Some(item) => item_sort(item) == 't',
Some(item) => item_sort(item) == Some('t'),
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1193,15 +1193,15 @@ fn encode_info_for_item(ecx: &EncodeContext,
None => {}
}
}
ast::ItemDefaultImpl(unsafety, ref ast_trait_ref) => {
ast::ItemDefaultImpl(unsafety, _) => {
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'd');
encode_name(rbml_w, item.ident.name);
encode_unsafety(rbml_w, unsafety);

let trait_ref = ty::node_id_to_trait_ref(tcx, ast_trait_ref.ref_id);
let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
rbml_w.end_tag();
}
Expand All @@ -1221,7 +1221,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_unsafety(rbml_w, unsafety);
encode_polarity(rbml_w, polarity);
match ty.node {
ast::TyPath(ref path, _) if path.segments.len() == 1 => {
ast::TyPath(None, ref path) if path.segments.len() == 1 => {
let ident = path.segments.last().unwrap().identifier;
encode_impl_type_basename(rbml_w, ident);
}
Expand All @@ -1241,9 +1241,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
rbml_w.end_tag();
}
if let Some(ref ast_trait_ref) = *opt_trait {
let trait_ref = ty::node_id_to_trait_ref(
tcx, ast_trait_ref.ref_id);
if opt_trait.is_some() {
let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
}
encode_path(rbml_w, path.clone());
Expand Down Expand Up @@ -1871,9 +1870,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) {
if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
let def_map = &self.ecx.tcx.def_map;
let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
let def_id = trait_def.def_id();
let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id();

// Load eagerly if this is an implementation of the Drop trait
// or if the trait is not defined in this crate.
Expand Down
Loading

0 comments on commit 0bd1565

Please sign in to comment.