Auto merge of #22172 - eddyb:almost-there, r=nikomatsakis

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`.
This commit is contained in:
bors 2015-02-24 17:56:09 +00:00
commit 0bd15657d9
111 changed files with 2366 additions and 2651 deletions

View File

@ -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>;
}

View File

@ -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 }
}

View File

@ -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 \
@ -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!")
};
@ -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);
}
@ -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"),
_ => ()
}
}
@ -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);
}
}
@ -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);
}
@ -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,
@ -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`

View File

@ -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)

View File

@ -119,7 +119,6 @@ enum Family {
StaticMethod, // F
Method, // h
Type, // y
ForeignType, // T
Mod, // m
ForeignMod, // n
Enum, // t
@ -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,
@ -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 {
@ -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 => {
@ -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,
@ -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
@ -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
}
}
@ -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);
@ -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,
@ -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
@ -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,
@ -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'),
}
}

View File

@ -1193,7 +1193,7 @@ 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);
@ -1201,7 +1201,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
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();
}
@ -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);
}
@ -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());
@ -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.

View File

@ -22,68 +22,58 @@ use util::ppaux::Repr;
pub const NO_REGIONS: uint = 1;
pub const NO_TPS: uint = 2;
pub fn check_path_args(tcx: &ty::ctxt,
path: &ast::Path,
flags: uint) {
if (flags & NO_TPS) != 0 {
if path.segments.iter().any(|s| s.parameters.has_types()) {
span_err!(tcx.sess, path.span, E0109,
"type parameters are not allowed on this type");
pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
for segment in segments {
if (flags & NO_TPS) != 0 {
for typ in segment.parameters.types() {
span_err!(tcx.sess, typ.span, E0109,
"type parameters are not allowed on this type");
break;
}
}
if (flags & NO_REGIONS) != 0 {
for lifetime in segment.parameters.lifetimes() {
span_err!(tcx.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type");
break;
}
}
}
}
if (flags & NO_REGIONS) != 0 {
if path.segments.iter().any(|s| s.parameters.has_lifetimes()) {
span_err!(tcx.sess, path.span, E0110,
"region parameters are not allowed on this type");
}
pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
segments: &[ast::PathSegment],
nty: ast::PrimTy)
-> Ty<'tcx> {
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
match nty {
ast::TyBool => tcx.types.bool,
ast::TyChar => tcx.types.char,
ast::TyInt(it) => ty::mk_mach_int(tcx, it),
ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
ast::TyStr => ty::mk_str(tcx)
}
}
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
-> Option<Ty<'tcx>> {
match ast_ty.node {
ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}",
path.repr(tcx)))
}
Some(&d) => d
};
match a_def {
def::DefPrimTy(nty) => {
match nty {
ast::TyBool => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
Some(tcx.types.bool)
}
ast::TyChar => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
Some(tcx.types.char)
}
ast::TyInt(it) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
Some(ty::mk_mach_int(tcx, it))
}
ast::TyUint(uit) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
Some(ty::mk_mach_uint(tcx, uit))
}
ast::TyFloat(ft) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
Some(ty::mk_mach_float(tcx, ft))
}
ast::TyStr => {
Some(ty::mk_str(tcx))
}
}
}
_ => None
if let ast::TyPath(None, ref path) = ast_ty.node {
let def = match tcx.def_map.borrow().get(&ast_ty.id) {
None => {
tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}", path.repr(tcx)))
}
Some(d) => d.full_def()
};
if let def::DefPrimTy(nty) = def {
Some(prim_ty_to_ty(tcx, &path.segments[], nty))
} else {
None
}
_ => None
} else {
None
}
}

View File

@ -25,6 +25,7 @@ use metadata::tydecode::{RegionParameter, ClosureSource};
use metadata::tyencode;
use middle::check_const::ConstQualif;
use middle::mem_categorization::Typer;
use middle::privacy::{AllPublic, LastMod};
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
@ -423,13 +424,8 @@ impl tr for def::Def {
fn tr(&self, dcx: &DecodeContext) -> def::Def {
match *self {
def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
def::DefStaticMethod(did, p) => {
def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
}
def::DefMethod(did0, did1, p) => {
def::DefMethod(did0.tr(dcx),
did1.map(|did1| did1.tr(dcx)),
p.map(|did2| did2.tr(dcx)))
def::DefMethod(did, p) => {
def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
}
def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
@ -440,13 +436,10 @@ impl tr for def::Def {
def::DefVariant(e_did, v_did, is_s) => {
def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
},
def::DefaultImpl(did) => def::DefaultImpl(did.tr(dcx)),
def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident),
def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
def::DefAssociatedTy(trait_did, did) =>
def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
def::DefPrimTy(p) => def::DefPrimTy(p),
def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
def::DefUse(did) => def::DefUse(did.tr(dcx)),
@ -455,9 +448,6 @@ impl tr for def::Def {
}
def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
def::DefTyParamBinder(nid) => {
def::DefTyParamBinder(dcx.tr_id(nid))
}
def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
}
}
@ -1159,10 +1149,10 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
debug!("Encoding side tables for id {}", id);
if let Some(def) = tcx.def_map.borrow().get(&id) {
if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
rbml_w.tag(c::tag_table_def, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap());
rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap());
})
}
@ -1862,7 +1852,12 @@ fn decode_side_tables(dcx: &DecodeContext,
match value {
c::tag_table_def => {
let def = decode_def(dcx, val_doc);
dcx.tcx.def_map.borrow_mut().insert(id, def);
dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
base_def: def,
// This doesn't matter cross-crate.
last_private: LastMod(AllPublic),
depth: 0
});
}
c::tag_table_node_type => {
let ty = val_dsr.read_ty(dcx);

View File

@ -398,8 +398,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
ast::ExprMac(..) |
ast::ExprClosure(..) |
ast::ExprLit(..) |
ast::ExprPath(..) |
ast::ExprQPath(..) => {
ast::ExprPath(..) => {
self.straightline(expr, pred, None::<ast::Expr>.iter())
}
}
@ -610,32 +609,24 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn find_scope(&self,
expr: &ast::Expr,
label: Option<ast::Ident>) -> LoopScope {
match label {
None => {
return *self.loop_scopes.last().unwrap();
}
if label.is_none() {
return *self.loop_scopes.last().unwrap();
}
Some(_) => {
match self.tcx.def_map.borrow().get(&expr.id) {
Some(&def::DefLabel(loop_id)) => {
for l in &self.loop_scopes {
if l.loop_id == loop_id {
return *l;
}
}
self.tcx.sess.span_bug(
expr.span,
&format!("no loop scope for id {}",
loop_id));
}
r => {
self.tcx.sess.span_bug(
expr.span,
&format!("bad entry `{:?}` in def_map for label",
r));
match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
Some(def::DefLabel(loop_id)) => {
for l in &self.loop_scopes {
if l.loop_id == loop_id {
return *l;
}
}
self.tcx.sess.span_bug(expr.span,
&format!("no loop scope for id {}", loop_id));
}
r => {
self.tcx.sess.span_bug(expr.span,
&format!("bad entry `{:?}` in def_map for label", r));
}
}
}

View File

@ -439,8 +439,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = v.tcx.def_map.borrow().get(&e.id).cloned();
ast::ExprPath(..) => {
let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
match def {
Some(def::DefVariant(_, _, _)) => {
// Count the discriminator or function pointer.
@ -452,8 +452,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
v.add_qualif(NON_ZERO_SIZED);
}
}
Some(def::DefFn(..)) |
Some(def::DefStaticMethod(..)) | Some(def::DefMethod(..)) => {
Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
// Count the function pointer.
v.add_qualif(NON_ZERO_SIZED);
}
@ -500,7 +499,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
_ => break
};
}
let def = v.tcx.def_map.borrow().get(&callee.id).cloned();
let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
match def {
Some(def::DefStruct(..)) => {}
Some(def::DefVariant(..)) => {

View File

@ -242,7 +242,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
let pat_ty = ty::pat_ty(cx.tcx, p);
if let ty::ty_enum(def_id, _) = pat_ty.sty {
let def = cx.tcx.def_map.borrow().get(&p.id).cloned();
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
if let Some(DefLocal(_)) = def {
if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
token::get_name(variant.name) == token::get_name(ident.node.name)
@ -434,7 +434,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
return match pat.node {
ast::PatIdent(..) | ast::PatEnum(..) => {
let def = self.tcx.def_map.borrow().get(&pat.id).cloned();
let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
match def {
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
Some(const_expr) => {
@ -733,28 +733,28 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
let pat = raw_pat(p);
match pat.node {
ast::PatIdent(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) {
Some(&DefConst(..)) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(&DefStruct(_)) => vec!(Single),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
Some(DefStruct(_)) => vec!(Single),
Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!()
},
ast::PatEnum(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) {
Some(&DefConst(..)) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!(Single)
},
ast::PatStruct(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) {
Some(&DefConst(..)) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!(Single)
},
ast::PatLit(ref expr) =>
@ -847,7 +847,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
Some(repeat(DUMMY_WILD_PAT).take(arity).collect()),
ast::PatIdent(_, _, _) => {
let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned();
let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
match opt_def {
Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@ -862,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
}
ast::PatEnum(_, ref args) => {
let def = cx.tcx.def_map.borrow()[pat_id].clone();
let def = cx.tcx.def_map.borrow()[pat_id].full_def();
match def {
DefConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@ -880,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
ast::PatStruct(_, ref pattern_fields, _) => {
// Is this a struct or an enum variant?
let def = cx.tcx.def_map.borrow()[pat_id].clone();
let def = cx.tcx.def_map.borrow()[pat_id].full_def();
let class_id = match def {
DefConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \

View File

@ -93,10 +93,10 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
fn visit_expr(&mut self, e: &ast::Expr) {
match e.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
match self.def_map.borrow().get(&e.id) {
Some(&DefStatic(def_id, _)) |
Some(&DefConst(def_id)) if
ast::ExprPath(..) => {
match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
Some(DefStatic(def_id, _)) |
Some(DefConst(def_id)) if
ast_util::is_local(def_id) => {
match self.ast_map.get(def_id.node) {
ast_map::NodeItem(item) =>

View File

@ -31,7 +31,7 @@ use std::{i8, i16, i32, i64};
use std::rc::Rc;
fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
match opt_def {
Some(def::DefConst(def_id)) => {
lookup_const_by_id(tcx, def_id)
@ -148,11 +148,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
ast::ExprCall(ref callee, ref args) => {
let def = tcx.def_map.borrow()[callee.id].clone();
let def = tcx.def_map.borrow()[callee.id];
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
entry.insert(def);
}
let path = match def {
let path = match def.full_def() {
def::DefStruct(def_id) => def_to_path(tcx, def_id),
def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
_ => unreachable!()
@ -178,8 +178,8 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
ast::PatVec(pats, None, vec![])
}
ast::ExprPath(ref path) => {
let opt_def = tcx.def_map.borrow().get(&expr.id).cloned();
ast::ExprPath(_, ref path) => {
let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
match opt_def {
Some(def::DefStruct(..)) =>
ast::PatStruct(path.clone(), vec![], false),
@ -194,13 +194,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
}
}
ast::ExprQPath(_) => {
match lookup_const(tcx, expr) {
Some(actual) => return const_expr_to_pat(tcx, actual, span),
_ => unreachable!()
}
}
_ => ast::PatLit(P(expr.clone()))
};
P(ast::Pat { id: expr.id, node: pat, span: span })
@ -388,8 +381,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
cast_const(val, ety)
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
ast::ExprPath(..) => {
let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
let (const_expr, const_ty) = match opt_def {
Some(def::DefConst(def_id)) => {
if ast_util::is_local(def_id) {

View File

@ -71,13 +71,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
self.tcx.def_map.borrow().get(id).map(|def| {
match def {
&def::DefConst(_) => {
match def.full_def() {
def::DefConst(_) => {
self.check_def_id(def.def_id())
}
_ if self.ignore_non_const_paths => (),
&def::DefPrimTy(_) => (),
&def::DefVariant(enum_id, variant_id, _) => {
def::DefPrimTy(_) => (),
def::DefVariant(enum_id, variant_id, _) => {
self.check_def_id(enum_id);
self.check_def_id(variant_id);
}
@ -158,7 +158,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
pats: &[codemap::Spanned<ast::FieldPat>]) {
let id = match (*self.tcx.def_map.borrow())[lhs.id] {
let id = match self.tcx.def_map.borrow()[lhs.id].full_def() {
def::DefVariant(_, id, _) => id,
_ => {
match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,

View File

@ -10,10 +10,9 @@
pub use self::Def::*;
pub use self::MethodProvenance::*;
pub use self::TraitItemKind::*;
use middle::privacy::LastPrivate;
use middle::subst::ParamSpace;
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
use util::nodemap::NodeMap;
use syntax::ast;
use syntax::ast_util::local_def;
@ -23,7 +22,6 @@ use std::cell::RefCell;
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
DefFn(ast::DefId, bool /* is_ctor */),
DefStaticMethod(/* method */ ast::DefId, MethodProvenance),
DefSelfTy(/* trait id */ ast::NodeId),
DefMod(ast::DefId),
DefForeignMod(ast::DefId),
@ -32,13 +30,8 @@ pub enum Def {
DefLocal(ast::NodeId),
DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
DefTy(ast::DefId, bool /* is_enum */),
DefAssociatedTy(ast::DefId),
// A partially resolved path to an associated type `T::U` where `T` is a concrete
// type (indicated by the DefId) which implements a trait which has an associated
// type `U` (indicated by the Ident).
// FIXME(#20301) -- should use Name
DefAssociatedPath(TyParamProvenance, ast::Ident),
DefaultImpl(ast::DefId),
DefAssociatedTy(ast::DefId /* trait */, ast::DefId),
DefTrait(ast::DefId),
DefPrimTy(ast::PrimTy),
DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
DefUse(ast::DefId),
@ -54,14 +47,48 @@ pub enum Def {
/// - If it's an ExprPath referring to some tuple struct, then DefMap maps
/// it to a def whose id is the StructDef.ctor_id.
DefStruct(ast::DefId),
DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */
DefRegion(ast::NodeId),
DefLabel(ast::NodeId),
DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
DefMethod(ast::DefId /* method */, MethodProvenance),
}
/// The result of resolving a path.
/// Before type checking completes, `depth` represents the number of
/// trailing segments which are yet unresolved. Afterwards, if there
/// were no errors, all paths should be fully resolved, with `depth`
/// set to `0` and `base_def` representing the final resolution.
///
/// module::Type::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// base_def depth = 3
///
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
/// base_def depth = 2
#[derive(Copy, Debug)]
pub struct PathResolution {
pub base_def: Def,
pub last_private: LastPrivate,
pub depth: usize
}
impl PathResolution {
/// Get the definition, if fully resolved, otherwise panic.
pub fn full_def(&self) -> Def {
if self.depth != 0 {
panic!("path not fully resolved: {:?}", self);
}
self.base_def
}
/// Get the DefId, if fully resolved, otherwise panic.
pub fn def_id(&self) -> ast::DefId {
self.full_def().def_id()
}
}
// Definition mapping
pub type DefMap = RefCell<NodeMap<Def>>;
pub type DefMap = RefCell<NodeMap<PathResolution>>;
// This is the replacement export map. It maps a module to all of the exports
// within.
pub type ExportMap = NodeMap<Vec<Export>>;
@ -78,12 +105,6 @@ pub enum MethodProvenance {
FromImpl(ast::DefId),
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum TyParamProvenance {
FromSelf(ast::DefId),
FromParam(ast::DefId),
}
impl MethodProvenance {
pub fn map<F>(self, f: F) -> MethodProvenance where
F: FnOnce(ast::DefId) -> ast::DefId,
@ -95,34 +116,6 @@ impl MethodProvenance {
}
}
impl TyParamProvenance {
pub fn def_id(&self) -> ast::DefId {
match *self {
TyParamProvenance::FromSelf(ref did) => did.clone(),
TyParamProvenance::FromParam(ref did) => did.clone(),
}
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum TraitItemKind {
NonstaticMethodTraitItemKind,
StaticMethodTraitItemKind,
TypeTraitItemKind,
}
impl TraitItemKind {
pub fn from_explicit_self_category(explicit_self_category:
ExplicitSelfCategory)
-> TraitItemKind {
if explicit_self_category == StaticExplicitSelfCategory {
StaticMethodTraitItemKind
} else {
NonstaticMethodTraitItemKind
}
}
}
impl Def {
pub fn local_node_id(&self) -> ast::NodeId {
let def_id = self.def_id();
@ -132,25 +125,21 @@ impl Def {
pub fn def_id(&self) -> ast::DefId {
match *self {
DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefaultImpl(id) |
DefMethod(id, _, _) | DefConst(id) |
DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
DefMethod(id, _) | DefConst(id) => {
id
}
DefLocal(id) |
DefSelfTy(id) |
DefUpvar(id, _) |
DefRegion(id) |
DefTyParamBinder(id) |
DefLabel(id) => {
local_def(id)
}
DefPrimTy(_) => panic!()
DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
}
}

View File

@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
ast::ExprInlineAsm(..) => {
self.require_unsafe(expr.span, "use of inline assembly");
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
self.require_unsafe(expr.span, "use of mutable static");
}

View File

@ -422,7 +422,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
self.walk_expr(&**subexpr)
}
ast::ExprPath(_) | ast::ExprQPath(_) => { }
ast::ExprPath(..) => { }
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
@ -1017,7 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
// Each match binding is effectively an assignment to the
// binding being produced.
let def = def_map.borrow()[pat.id].clone();
let def = def_map.borrow()[pat.id].full_def();
match mc.cat_def(pat.id, pat.span, pat_ty, def) {
Ok(binding_cmt) => {
delegate.mutate(pat.id, pat.span, binding_cmt, Init);
@ -1097,13 +1097,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
match pat.node {
ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
match def_map.get(&pat.id) {
match def_map.get(&pat.id).map(|d| d.full_def()) {
None => {
// no definition found: pat is not a
// struct or enum pattern.
}
Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => {
Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
let downcast_cmt =
if ty::enum_is_univariant(tcx, enum_did) {
cmt_pat
@ -1119,7 +1119,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
delegate.matched_pat(pat, downcast_cmt, match_mode);
}
Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => {
Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
// A struct (in either the value or type
// namespace; we encounter the former on
// e.g. patterns for unit structs).
@ -1131,14 +1131,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
delegate.matched_pat(pat, cmt_pat, match_mode);
}
Some(&def::DefConst(..)) |
Some(&def::DefLocal(..)) => {
Some(def::DefConst(..)) |
Some(def::DefLocal(..)) => {
// This is a leaf (i.e. identifier binding
// or constant value to match); thus no
// `matched_pat` call.
}
Some(def @ &def::DefTy(_, true)) => {
Some(def @ def::DefTy(_, true)) => {
// An enum's type -- should never be in a
// pattern.

View File

@ -1233,8 +1233,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
}
ty_queue.push(&*mut_ty.ty);
}
ast::TyPath(ref path, id) => {
let a_def = match self.tcx.def_map.borrow().get(&id) {
ast::TyPath(ref maybe_qself, ref path) => {
let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) {
None => {
self.tcx
.sess
@ -1242,7 +1242,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
"unbound path {}",
pprust::path_to_string(path)))
}
Some(&d) => d
Some(d) => d.full_def()
};
match a_def {
def::DefTy(did, _) | def::DefStruct(did) => {
@ -1277,9 +1277,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
region_names: region_names
};
let new_path = self.rebuild_path(rebuild_info, lifetime);
let qself = maybe_qself.as_ref().map(|qself| {
ast::QSelf {
ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
anon_nums, region_names),
position: qself.position
}
});
let to = ast::Ty {
id: cur_ty.id,
node: ast::TyPath(new_path, id),
node: ast::TyPath(qself, new_path),
span: cur_ty.span
};
new_ty = self.rebuild_ty(new_ty, P(to));

View File

@ -445,8 +445,8 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
match expr.node {
// live nodes required for uses or definitions of variables:
ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = ir.tcx.def_map.borrow()[expr.id].clone();
ast::ExprPath(..) => {
let def = ir.tcx.def_map.borrow()[expr.id].full_def();
debug!("expr {}: path that leads to {:?}", expr.id, def);
if let DefLocal(..) = def {
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@ -705,8 +705,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
Some(_) => {
// Refers to a labeled loop. Use the results of resolve
// to find with one
match self.ir.tcx.def_map.borrow().get(&id) {
Some(&DefLabel(loop_id)) => loop_id,
match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
Some(DefLabel(loop_id)) => loop_id,
_ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
doesn't refer to a loop")
}
@ -947,7 +947,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.node {
// Interesting cases with control flow or which gen/kill
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
}
@ -1275,7 +1275,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// just ignore such cases and treat them as reads.
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => succ,
ast::ExprPath(..) => succ,
ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
_ => self.propagate_through_expr(expr, succ)
@ -1286,7 +1286,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
-> LiveNode {
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
self.access_path(expr, succ, acc)
}
@ -1300,7 +1300,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
-> LiveNode {
match self.ir.tcx.def_map.borrow()[expr.id].clone() {
match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
DefLocal(nid) => {
let ln = self.live_node(expr.id, expr.span);
if acc != 0 {
@ -1468,7 +1468,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
ast::ExprRange(..) | ast::ExprQPath(..) => {
ast::ExprRange(..) => {
visit::walk_expr(this, expr);
}
ast::ExprIfLet(..) => {
@ -1561,8 +1561,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn check_lvalue(&mut self, expr: &Expr) {
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
ast::ExprPath(..) => {
if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() {
// Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually
// mutable, then check for a reassignment to flag the mutability

View File

@ -529,8 +529,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
}
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = (*self.tcx().def_map.borrow())[expr.id];
ast::ExprPath(..) => {
let def = self.tcx().def_map.borrow()[expr.id].full_def();
self.cat_def(expr.id, expr.span, expr_ty, def)
}
@ -575,14 +575,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
match def {
def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
def::DefFn(..) | def::DefMethod(..) => {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
def::DefaultImpl(_) | def::DefTy(..) | def::DefPrimTy(_) |
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
def::DefTyParam(..) | def::DefRegion(_) |
def::DefLabel(_) | def::DefSelfTy(..) |
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
def::DefAssociatedTy(..) => {
Ok(Rc::new(cmt_ {
id:id,
span:span,
@ -1199,14 +1199,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
(*op)(self, cmt.clone(), pat);
let def_map = self.tcx().def_map.borrow();
let opt_def = def_map.get(&pat.id);
let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
// Note: This goes up here (rather than within the PatEnum arm
// alone) because struct patterns can refer to struct types or
// to struct variants within enums.
let cmt = match opt_def {
Some(&def::DefVariant(enum_did, variant_did, _))
Some(def::DefVariant(enum_did, variant_did, _))
// univariant enums do not need downcasts
if !ty::enum_is_univariant(self.tcx(), enum_did) => {
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@ -1224,7 +1223,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
}
ast::PatEnum(_, Some(ref subpats)) => {
match opt_def {
Some(&def::DefVariant(..)) => {
Some(def::DefVariant(..)) => {
// variant(x, y, z)
for (i, subpat) in subpats.iter().enumerate() {
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@ -1237,7 +1236,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
try!(self.cat_pattern_(subcmt, &**subpat, op));
}
}
Some(&def::DefStruct(..)) => {
Some(def::DefStruct(..)) => {
for (i, subpat) in subpats.iter().enumerate() {
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
let cmt_field =
@ -1247,7 +1246,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
try!(self.cat_pattern_(cmt_field, &**subpat, op));
}
}
Some(&def::DefConst(..)) => {
Some(def::DefConst(..)) => {
for subpat in subpats {
try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
}

View File

@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
ast::PatEnum(_, _) |
ast::PatIdent(_, _, None) |
ast::PatStruct(..) => {
match dm.borrow().get(&pat.id) {
Some(&DefVariant(..)) => true,
match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefVariant(..)) => true,
_ => false
}
}
@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
ast::PatEnum(_, _) |
ast::PatIdent(_, _, None) |
ast::PatStruct(..) => {
match dm.borrow().get(&pat.id) {
Some(&DefVariant(..)) | Some(&DefStruct(..)) => true,
match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefVariant(..)) | Some(DefStruct(..)) => true,
_ => false
}
}
@ -61,8 +61,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
match pat.node {
ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
match dm.borrow().get(&pat.id) {
Some(&DefConst(..)) => true,
match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) => true,
_ => false
}
}

View File

@ -16,7 +16,7 @@ pub use self::PrivateDep::*;
pub use self::ImportUse::*;
pub use self::LastPrivate::*;
use util::nodemap::{DefIdSet, NodeMap, NodeSet};
use util::nodemap::{DefIdSet, NodeSet};
use syntax::ast;
@ -32,9 +32,6 @@ pub type ExternalExports = DefIdSet;
/// reexporting a public struct doesn't inline the doc).
pub type PublicItems = NodeSet;
// FIXME: dox
pub type LastPrivateMap = NodeMap<LastPrivate>;
#[derive(Copy, Debug)]
pub enum LastPrivate {
LastMod(PrivateDep),

View File

@ -94,9 +94,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
fn visit_expr(&mut self, expr: &ast::Expr) {
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
let def = match self.tcx.def_map.borrow().get(&expr.id) {
Some(&def) => def,
Some(d) => d.full_def(),
None => {
self.tcx.sess.span_bug(expr.span,
"def ID not in def map?!")

View File

@ -165,13 +165,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
visit::walk_ty(this, ty);
});
}
ast::TyPath(ref path, id) => {
ast::TyPath(None, ref path) => {
// if this path references a trait, then this will resolve to
// a trait ref, which introduces a binding scope.
match self.def_map.borrow().get(&id) {
Some(&def::DefaultImpl(..)) => {
match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) {
Some((def::DefTrait(..), 0)) => {
self.with(LateScope(&Vec::new(), self.scope), |_, this| {
this.visit_path(path, id);
this.visit_path(path, ty.id);
});
}
_ => {
@ -270,16 +270,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
for lifetime in &trait_ref.bound_lifetimes {
this.visit_lifetime_def(lifetime);
}
this.visit_trait_ref(&trait_ref.trait_ref)
visit::walk_path(this, &trait_ref.trait_ref.path)
})
} else {
self.visit_trait_ref(&trait_ref.trait_ref)
}
}
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
self.visit_path(&trait_ref.path, trait_ref.ref_id);
}
}
impl<'a> LifetimeContext<'a> {

View File

@ -393,12 +393,14 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
let did = match tcx.def_map.borrow().get(&id) {
Some(&def::DefPrimTy(..)) => return,
Some(def) => def.def_id(),
None => return
};
maybe_do_stability_check(tcx, did, path.span, cb)
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
Some(def::DefPrimTy(..)) => {}
Some(def) => {
maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
}
None => {}
}
}
fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,

View File

@ -709,7 +709,7 @@ pub struct ctxt<'tcx> {
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
pub impl_trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
@ -2423,7 +2423,7 @@ impl<'tcx> CommonTypes<'tcx> {
pub fn mk_ctxt<'tcx>(s: Session,
arenas: &'tcx CtxtArenas<'tcx>,
dm: DefMap,
def_map: DefMap,
named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map<'tcx>,
freevars: RefCell<FreevarMap>,
@ -2445,11 +2445,11 @@ pub fn mk_ctxt<'tcx>(s: Session,
item_variance_map: RefCell::new(DefIdMap()),
variance_computed: Cell::new(false),
sess: s,
def_map: dm,
def_map: def_map,
region_maps: region_maps,
node_types: RefCell::new(FnvHashMap()),
item_substs: RefCell::new(NodeMap()),
trait_refs: RefCell::new(NodeMap()),
impl_trait_refs: RefCell::new(NodeMap()),
trait_defs: RefCell::new(DefIdMap()),
predicates: RefCell::new(DefIdMap()),
object_cast_map: RefCell::new(NodeMap()),
@ -4174,12 +4174,12 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
}
}
pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
-> Rc<ty::TraitRef<'tcx>> {
match cx.trait_refs.borrow().get(&id) {
match cx.impl_trait_refs.borrow().get(&id) {
Some(ty) => ty.clone(),
None => cx.sess.bug(
&format!("node_id_to_trait_ref: no trait ref for node `{}`",
&format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
cx.map.node_to_string(id)))
}
}
@ -4502,7 +4502,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
match tcx.def_map.borrow().get(&expr.id) {
Some(&def) => def,
Some(def) => def.full_def(),
None => {
tcx.sess.span_bug(expr.span, &format!(
"no def-map entry for expr {}", expr.id));
@ -4550,7 +4550,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
}
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
match resolve_expr(tcx, expr) {
def::DefVariant(tid, vid, _) => {
let variant_info = enum_variant_with_id(tcx, tid, vid);
@ -4581,7 +4581,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
def::DefFn(_, true) => RvalueDpsExpr,
// Fn pointers are just scalar values.
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr,
// Note: there is actually a good case to be made that
// DefArg's, particularly those of immediate type, ought to
@ -4685,11 +4685,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprBox(Some(ref place), _) => {
// Special case `Box<T>` for now:
let definition = match tcx.def_map.borrow().get(&place.id) {
Some(&def) => def,
let def_id = match tcx.def_map.borrow().get(&place.id) {
Some(def) => def.def_id(),
None => panic!("no def for place"),
};
let def_id = definition.def_id();
if tcx.lang_items.exchange_heap() == Some(def_id) {
RvalueDatumExpr
} else {
@ -5116,25 +5115,16 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
if id.krate == ast::LOCAL_CRATE {
debug!("(impl_trait_ref) searching for trait impl {:?}", id);
match cx.map.find(id.node) {
Some(ast_map::NodeItem(item)) => {
match item.node {
ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
match opt_trait {
&Some(ref t) => {
let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
Some(trait_ref)
}
&None => None
}
}
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id))
}
_ => None
if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
match item.node {
ast::ItemImpl(_, _, _, Some(_), _, _) |
ast::ItemDefaultImpl(..) => {
Some(ty::impl_id_to_trait_ref(cx, id.node))
}
_ => None
}
_ => None
} else {
None
}
} else {
csearch::get_impl_trait(cx, id)
@ -5143,10 +5133,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
}
pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
let def = *tcx.def_map.borrow()
.get(&tr.ref_id)
.expect("no def-map entry for trait");
def.def_id()
tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
}
pub fn try_add_builtin_trait(
@ -5848,7 +5835,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
}
Err(_) => {
let found = match count_expr.node {
ast::ExprPath(ast::Path {
ast::ExprPath(None, ast::Path {
global: false,
ref segments,
..

View File

@ -244,8 +244,7 @@ mod svh_visitor {
SawExprAssignOp(ast::BinOp_),
SawExprIndex,
SawExprRange,
SawExprPath,
SawExprQPath,
SawExprPath(Option<usize>),
SawExprAddrOf(ast::Mutability),
SawExprRet,
SawExprInlineAsm(&'a ast::InlineAsm),
@ -277,8 +276,7 @@ mod svh_visitor {
ExprTupField(_, id) => SawExprTupField(id.node),
ExprIndex(..) => SawExprIndex,
ExprRange(..) => SawExprRange,
ExprPath(..) => SawExprPath,
ExprQPath(..) => SawExprQPath,
ExprPath(ref qself, _) => SawExprPath(qself.as_ref().map(|q| q.position)),
ExprAddrOf(m, _) => SawExprAddrOf(m),
ExprBreak(id) => SawExprBreak(id.map(content)),
ExprAgain(id) => SawExprAgain(id.map(content)),

View File

@ -571,7 +571,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
export_map,
trait_map,
external_exports,
last_private_map,
glob_map,
} =
time(time_passes, "resolution", (),
@ -620,10 +619,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
time(time_passes, "const checking", (), |_|
middle::check_const::check_crate(&ty_cx));
let maps = (external_exports, last_private_map);
let (exported_items, public_items) =
time(time_passes, "privacy checking", maps, |(a, b)|
rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
time(time_passes, "privacy checking", (), |_|
rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
// Do not move this check past lint
time(time_passes, "stability index", (), |_|

View File

@ -17,7 +17,6 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(core)]
#![feature(int_uint)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
@ -38,8 +37,7 @@ use rustc::middle::def;
use rustc::middle::privacy::ImportUse::*;
use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
use rustc::middle::privacy::{ExternalExports};
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
@ -259,8 +257,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
// * Private trait impls for private types can be completely ignored
ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
let public_ty = match ty.node {
ast::TyPath(_, id) => {
match self.tcx.def_map.borrow()[id].clone() {
ast::TyPath(..) => {
match self.tcx.def_map.borrow()[ty.id].full_def() {
def::DefPrimTy(..) => true,
def => {
let did = def.def_id();
@ -326,8 +324,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
}
ast::ItemTy(ref ty, _) if public_first => {
if let ast::TyPath(_, id) = ty.node {
match self.tcx.def_map.borrow()[id].clone() {
if let ast::TyPath(..) = ty.node {
match self.tcx.def_map.borrow()[ty.id].full_def() {
def::DefPrimTy(..) | def::DefTyParam(..) => {},
def => {
let did = def.def_id();
@ -379,7 +377,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
in_foreign: bool,
parents: NodeMap<ast::NodeId>,
external_exports: ExternalExports,
last_private_map: LastPrivateMap,
}
enum PrivacyResult {
@ -628,11 +625,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
// back up the chains to find the relevant struct/enum that
// was private.
ast::ItemImpl(_, _, _, _, ref ty, _) => {
let id = match ty.node {
ast::TyPath(_, id) => id,
match ty.node {
ast::TyPath(..) => {}
_ => return Some((err_span, err_msg, None)),
};
let def = self.tcx.def_map.borrow()[id].clone();
let def = self.tcx.def_map.borrow()[ty.id].full_def();
let did = def.def_id();
assert!(is_local(did));
match self.tcx.map.get(did.node) {
@ -716,21 +713,21 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
}
// Checks that a path is in scope.
fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) {
debug!("privacy - path {}", self.nodestr(path_id));
let orig_def = self.tcx.def_map.borrow()[path_id].clone();
let path_res = self.tcx.def_map.borrow()[path_id];
let ck = |tyname: &str| {
let ck_public = |def: ast::DefId| {
debug!("privacy - ck_public {:?}", def);
let name = token::get_ident(path.segments.last().unwrap().identifier);
let origdid = orig_def.def_id();
let name = token::get_ident(last);
let origdid = path_res.def_id();
self.ensure_public(span,
def,
Some(origdid),
&format!("{} `{}`", tyname, name))
};
match self.last_private_map[path_id] {
match path_res.last_private {
LastMod(AllPublic) => {},
LastMod(DependsOn(def)) => {
self.report_error(ck_public(def));
@ -794,17 +791,15 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
// def map is not. Therefore the names we work out below will not always
// be accurate and we can get slightly wonky error messages (but type
// checking is always correct).
match self.tcx.def_map.borrow()[path_id].clone() {
def::DefStaticMethod(..) => ck("static method"),
match path_res.full_def() {
def::DefFn(..) => ck("function"),
def::DefStatic(..) => ck("static"),
def::DefConst(..) => ck("const"),
def::DefVariant(..) => ck("variant"),
def::DefTy(_, false) => ck("type"),
def::DefTy(_, true) => ck("enum"),
def::DefaultImpl(..) => ck("trait"),
def::DefTrait(..) => ck("trait"),
def::DefStruct(..) => ck("struct"),
def::DefMethod(_, Some(..), _) => ck("trait method"),
def::DefMethod(..) => ck("method"),
def::DefMod(..) => ck("module"),
_ => {}
@ -832,37 +827,22 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) {
match item.node {
ast::ItemUse(ref vpath) => {
match vpath.node {
ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
ast::ViewPathList(ref prefix, ref list) => {
for pid in list {
match pid.node {
ast::PathListIdent { id, name } => {
debug!("privacy - ident item {}", id);
let seg = ast::PathSegment {
identifier: name,
parameters: ast::PathParameters::none(),
};
let segs = vec![seg];
let path = ast::Path {
global: false,
span: pid.span,
segments: segs,
};
self.check_path(pid.span, id, &path);
}
ast::PathListMod { id } => {
debug!("privacy - mod item {}", id);
self.check_path(pid.span, id, prefix);
}
}
if let ast::ItemUse(ref vpath) = item.node {
if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
for pid in list {
match pid.node {
ast::PathListIdent { id, name } => {
debug!("privacy - ident item {}", id);
self.check_path(pid.span, id, name);
}
ast::PathListMod { id } => {
debug!("privacy - mod item {}", id);
let name = prefix.segments.last().unwrap().identifier;
self.check_path(pid.span, id, name);
}
}
}
}
_ => {}
}
let orig_curitem = replace(&mut self.curitem, item.id);
visit::walk_item(self, item);
@ -908,7 +888,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
}
ty::ty_enum(_, _) => {
match self.tcx.def_map.borrow()[expr.id].clone() {
match self.tcx.def_map.borrow()[expr.id].full_def() {
def::DefVariant(_, variant_id, _) => {
for field in fields {
self.check_field(expr.span, variant_id,
@ -927,7 +907,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
struct type?!"),
}
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
let guard = |did: ast::DefId| {
let fields = ty::lookup_struct_fields(self.tcx, did);
let any_priv = fields.iter().any(|f| {
@ -941,8 +921,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
with private fields");
}
};
match self.tcx.def_map.borrow().get(&expr.id) {
Some(&def::DefStruct(did)) => {
match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
Some(def::DefStruct(did)) => {
guard(if is_local(did) {
local_def(self.tcx.map.get_parent(did.node))
} else {
@ -981,8 +961,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
}
ty::ty_enum(_, _) => {
match self.tcx.def_map.borrow().get(&pattern.id) {
Some(&def::DefVariant(_, variant_id, _)) => {
match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
Some(def::DefVariant(_, variant_id, _)) => {
for field in fields {
self.check_field(pattern.span, variant_id,
NamedField(field.node.ident.name));
@ -1033,7 +1013,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
self.check_path(path.span, id, path);
self.check_path(path.span, id, path.segments.last().unwrap().identifier);
visit::walk_path(self, path);
}
}
@ -1233,7 +1213,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
let did = match self.tcx.def_map.borrow().get(&path_id).cloned() {
let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
// `int` etc. (None doesn't seem to occur.)
None | Some(def::DefPrimTy(..)) => return false,
Some(def) => def.def_id()
@ -1273,8 +1253,8 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
fn visit_ty(&mut self, ty: &ast::Ty) {
if let ast::TyPath(_, path_id) = ty.node {
if self.inner.path_is_private_type(path_id) {
if let ast::TyPath(..) = ty.node {
if self.inner.path_is_private_type(ty.id) {
self.contains_private = true;
// found what we're looking for so let's stop
// working.
@ -1398,7 +1378,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
//
// Those in 2. are warned via walk_generics and this
// call here.
self.visit_trait_ref(tr)
visit::walk_path(self, &tr.path);
}
}
} else if trait_ref.is_none() && self_is_public_path {
@ -1479,9 +1459,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_ty(&mut self, t: &ast::Ty) {
if let ast::TyPath(ref p, path_id) = t.node {
if let ast::TyPath(_, ref p) = t.node {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(path_id) {
self.path_is_private_type(t.id) {
self.tcx.sess.span_err(p.span,
"private type in exported type signature");
}
@ -1517,8 +1497,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
pub fn check_crate(tcx: &ty::ctxt,
export_map: &def::ExportMap,
external_exports: ExternalExports,
last_private_map: LastPrivateMap)
external_exports: ExternalExports)
-> (ExportedItems, PublicItems) {
let krate = tcx.map.krate();
@ -1536,7 +1515,6 @@ pub fn check_crate(tcx: &ty::ctxt,
tcx: tcx,
parents: visitor.parents,
external_exports: external_exports,
last_private_map: last_private_map,
};
visit::walk_crate(&mut visitor, krate);

View File

@ -23,10 +23,8 @@ use Namespace::{TypeNS, ValueNS};
use NameBindings;
use ParentLink::{self, ModuleParentLink, BlockParentLink};
use Resolver;
use RibKind::*;
use Shadowable;
use TypeNsDef;
use TypeParameters::HasTypeParameters;
use self::DuplicateCheckingMode::*;
use self::NamespaceError::*;
@ -34,7 +32,6 @@ use self::NamespaceError::*;
use rustc::metadata::csearch;
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
use rustc::middle::def::*;
use rustc::middle::subst::FnSpace;
use syntax::ast::{Block, Crate};
use syntax::ast::{DeclItem, DefId};
@ -42,19 +39,16 @@ use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
use syntax::ast::{PathListIdent, PathListMod};
use syntax::ast::{Public, SelfStatic};
use syntax::ast::{Name, NamedField, NodeId};
use syntax::ast::{PathListIdent, PathListMod, Public};
use syntax::ast::StmtDecl;
use syntax::ast::StructVariantKind;
use syntax::ast::TupleVariantKind;
use syntax::ast::TyObjectSum;
use syntax::ast::{TypeImplItem, UnnamedField};
use syntax::ast::UnnamedField;
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::ast::{Visibility};
use syntax::ast::TyPath;
use syntax::ast;
use syntax::ast_util::{self, PostExpansionMethod, local_def};
use syntax::ast_util::{self, local_def};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::{self, special_idents};
use syntax::codemap::{Span, DUMMY_SP};
@ -181,12 +175,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
Some(TypeNS)
}
ForbidDuplicateTypesAndModules => {
match child.def_for_namespace(TypeNS) {
None => {}
Some(_) if child.get_module_if_available()
.map(|m| m.kind.get()) ==
Some(ImplModuleKind) => {}
Some(_) => duplicate_type = TypeError
if child.defined_in_namespace(TypeNS) {
duplicate_type = TypeError;
}
Some(TypeNS)
}
@ -465,9 +455,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
let parent_link = self.get_parent_link(parent, name);
// We want to make sure the module type is EnumModuleKind
// even if there's already an ImplModuleKind module defined,
// since that's how we prevent duplicate enum definitions
name_bindings.set_module_kind(parent_link,
Some(local_def(item.id)),
EnumModuleKind,
@ -517,147 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone()
}
ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
// If this implements an anonymous trait, then add all the
// methods within to a new module, if the type was defined
// within this module.
let mod_name = match ty.node {
TyPath(ref path, _) if path.segments.len() == 1 => {
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
Some(path.segments.last().unwrap().identifier.name)
}
TyObjectSum(ref lhs_ty, _) => {
match lhs_ty.node {
TyPath(ref path, _) if path.segments.len() == 1 => {
Some(path.segments.last().unwrap().identifier.name)
}
_ => {
None
}
}
}
_ => {
None
}
};
let mod_name = match mod_name {
Some(mod_name) => mod_name,
None => {
self.resolve_error(ty.span,
"inherent implementations may \
only be implemented in the same \
module as the type they are \
implemented for");
return parent.clone();
}
};
// Create the module and add all methods.
let child_opt = parent.children.borrow().get(&mod_name)
.and_then(|m| m.get_module_if_available());
let new_parent = match child_opt {
// It already exists
Some(ref child) if (child.kind.get() == ImplModuleKind ||
child.kind.get() == TraitModuleKind) => {
child.clone()
}
Some(ref child) if child.kind.get() == EnumModuleKind ||
child.kind.get() == TypeModuleKind => {
child.clone()
}
// Create the module
_ => {
let name_bindings =
self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
let parent_link = self.get_parent_link(parent, name);
let def_id = local_def(item.id);
let ns = TypeNS;
let is_public =
!name_bindings.defined_in_namespace(ns) ||
name_bindings.defined_in_public_namespace(ns);
name_bindings.define_module(parent_link,
Some(def_id),
ImplModuleKind,
false,
is_public,
sp);
name_bindings.get_module()
}
};
// For each implementation item...
for impl_item in impl_items {
match *impl_item {
MethodImplItem(ref method) => {
// Add the method to the module.
let name = method.pe_ident().name;
let method_name_bindings =
self.add_child(name,
&new_parent,
ForbidDuplicateValues,
method.span);
let def = match method.pe_explicit_self()
.node {
SelfStatic => {
// Static methods become
// `DefStaticMethod`s.
DefStaticMethod(local_def(method.id),
FromImpl(local_def(item.id)))
}
_ => {
// Non-static methods become
// `DefMethod`s.
DefMethod(local_def(method.id),
None,
FromImpl(local_def(item.id)))
}
};
// NB: not IMPORTABLE
let modifiers = if method.pe_vis() == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value(
def,
method.span,
modifiers);
}
TypeImplItem(ref typedef) => {
// Add the typedef to the module.
let name = typedef.ident.name;
let typedef_name_bindings =
self.add_child(
name,
&new_parent,
ForbidDuplicateTypesAndModules,
typedef.span);
let def = DefAssociatedTy(local_def(
typedef.id));
// NB: not IMPORTABLE
let modifiers = if typedef.vis == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
typedef_name_bindings.define_type(
def,
typedef.span,
modifiers);
}
}
}
parent.clone()
}
ItemDefaultImpl(_, _) |
ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
ItemImpl(..) => parent.clone(),
ItemTrait(_, _, _, ref items) => {
let name_bindings =
@ -677,7 +525,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
// Add the names of all the items to the trait info.
for trait_item in items {
let (name, kind) = match *trait_item {
let (name, trait_item_id) = match *trait_item {
ast::RequiredMethod(_) |
ast::ProvidedMethod(_) => {
let ty_m = ast_util::trait_item_to_ty_method(trait_item);
@ -685,23 +533,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let name = ty_m.ident.name;
// Add it as a name in the trait module.
let (def, static_flag) = match ty_m.explicit_self
.node {
SelfStatic => {
// Static methods become `DefStaticMethod`s.
(DefStaticMethod(
local_def(ty_m.id),
FromTrait(local_def(item.id))),
StaticMethodTraitItemKind)
}
_ => {
// Non-static methods become `DefMethod`s.
(DefMethod(local_def(ty_m.id),
Some(local_def(item.id)),
FromTrait(local_def(item.id))),
NonstaticMethodTraitItemKind)
}
};
let def = DefMethod(local_def(ty_m.id),
FromTrait(local_def(item.id)));
let method_name_bindings =
self.add_child(name,
@ -713,11 +546,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
ty_m.span,
PUBLIC);
(name, static_flag)
(name, local_def(ty_m.id))
}
ast::TypeTraitItem(ref associated_type) => {
let def = DefAssociatedTy(local_def(
associated_type.ty_param.id));
let def = DefAssociatedTy(local_def(item.id),
local_def(associated_type.ty_param.id));
let name_bindings =
self.add_child(associated_type.ty_param.ident.name,
@ -729,14 +562,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
associated_type.ty_param.span,
PUBLIC);
(associated_type.ty_param.ident.name, TypeTraitItemKind)
(associated_type.ty_param.ident.name,
local_def(associated_type.ty_param.id))
}
};
self.trait_item_map.insert((name, def_id), kind);
self.trait_item_map.insert((name, def_id), trait_item_id);
}
name_bindings.define_type(DefaultImpl(def_id), sp, modifiers);
name_bindings.define_type(DefTrait(def_id), sp, modifiers);
parent.clone()
}
ItemMac(..) => parent.clone()
@ -773,12 +607,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
/// Constructs the reduced graph for one foreign item.
fn build_reduced_graph_for_foreign_item<F>(&mut self,
foreign_item: &ForeignItem,
parent: &Rc<Module>,
f: F) where
F: FnOnce(&mut Resolver),
{
fn build_reduced_graph_for_foreign_item(&mut self,
foreign_item: &ForeignItem,
parent: &Rc<Module>) {
let name = foreign_item.ident.name;
let is_public = foreign_item.vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
@ -786,25 +617,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span);
match foreign_item.node {
ForeignItemFn(_, ref generics) => {
let def = DefFn(local_def(foreign_item.id), false);
name_bindings.define_value(def, foreign_item.span, modifiers);
self.with_type_parameter_rib(
HasTypeParameters(generics,
FnSpace,
foreign_item.id,
NormalRibKind),
f);
let def = match foreign_item.node {
ForeignItemFn(..) => {
DefFn(local_def(foreign_item.id), false)
}
ForeignItemStatic(_, m) => {
let def = DefStatic(local_def(foreign_item.id), m);
name_bindings.define_value(def, foreign_item.span, modifiers);
f(self.resolver)
DefStatic(local_def(foreign_item.id), m)
}
}
};
name_bindings.define_value(def, foreign_item.span, modifiers);
}
fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
@ -850,8 +671,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let kind = match def {
DefTy(_, true) => EnumModuleKind,
DefTy(_, false) => TypeModuleKind,
DefStruct(..) => ImplModuleKind,
DefTy(_, false) | DefStruct(..) => TypeModuleKind,
_ => NormalModuleKind
};
@ -905,7 +725,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
.map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
}
DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
debug!("(building reduced graph for external \
crate) building value (fn/static) {}", final_ident);
// impl methods have already been defined with the correct importability modifier
@ -918,7 +738,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
}
DefaultImpl(def_id) => {
DefTrait(def_id) => {
debug!("(building reduced graph for external \
crate) building type {}", final_ident);
@ -927,21 +747,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let trait_item_def_ids =
csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
for trait_item_def_id in &trait_item_def_ids {
let (trait_item_name, trait_item_kind) =
csearch::get_trait_item_name_and_kind(
&self.session.cstore,
trait_item_def_id.def_id());
for trait_item_def in &trait_item_def_ids {
let trait_item_name = csearch::get_trait_name(&self.session.cstore,
trait_item_def.def_id());
debug!("(building reduced graph for external crate) ... \
adding trait item '{}'",
token::get_name(trait_item_name));
self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
self.trait_item_map.insert((trait_item_name, def_id),
trait_item_def.def_id());
if is_exported {
self.external_exports
.insert(trait_item_def_id.def_id());
self.external_exports.insert(trait_item_def.def_id());
}
}
@ -956,7 +774,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
is_public,
DUMMY_SP)
}
DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
DefTy(..) | DefAssociatedTy(..) => {
debug!("(building reduced graph for external \
crate) building type {}", final_ident);
@ -980,7 +798,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
DefUse(..) | DefUpvar(..) | DefRegion(..) |
DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
DefLabel(..) | DefSelfTy(..) => {
panic!("didn't expect `{:?}`", def);
}
}
@ -1027,92 +845,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
}
}
DlImpl(def) => {
match csearch::get_type_name_if_impl(&self.session.cstore, def) {
None => {}
Some(final_name) => {
let methods_opt =
csearch::get_methods_if_impl(&self.session.cstore, def);
match methods_opt {
Some(ref methods) if
methods.len() >= 1 => {
debug!("(building reduced graph for \
external crate) processing \
static methods for type name {}",
token::get_name(final_name));
let child_name_bindings =
self.add_child(
final_name,
root,
OverwriteDuplicates,
DUMMY_SP);
// Process the static methods. First,
// create the module.
let type_module;
let type_def = child_name_bindings.type_def.borrow().clone();
match type_def {
Some(TypeNsDef {
module_def: Some(module_def),
..
}) => {
// We already have a module. This
// is OK.
type_module = module_def;
// Mark it as an impl module if
// necessary.
type_module.kind.set(ImplModuleKind);
}
Some(_) | None => {
let parent_link =
self.get_parent_link(root, final_name);
child_name_bindings.define_module(
parent_link,
Some(def),
ImplModuleKind,
true,
true,
DUMMY_SP);
type_module =
child_name_bindings.
get_module();
}
}
// Add each static method to the module.
let new_parent = type_module;
for method_info in methods {
let name = method_info.name;
debug!("(building reduced graph for \
external crate) creating \
static method '{}'",
token::get_name(name));
let method_name_bindings =
self.add_child(name,
&new_parent,
OverwriteDuplicates,
DUMMY_SP);
let def = DefFn(method_info.def_id, false);
// NB: not IMPORTABLE
let modifiers = if method_info.vis == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value(
def, DUMMY_SP, modifiers);
}
}
// Otherwise, do nothing.
Some(_) | None => {}
}
}
}
DlImpl(_) => {
debug!("(building reduced graph for external crate) \
ignoring impl");
}
DlField => {
debug!("(building reduced graph for external crate) \
@ -1241,16 +976,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
let parent = &self.parent;
self.builder.build_reduced_graph_for_foreign_item(foreign_item,
parent,
|r| {
let mut v = BuildReducedGraphVisitor {
builder: GraphBuilder { resolver: r },
parent: parent.clone()
};
visit::walk_foreign_item(&mut v, foreign_item);
})
self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
}
fn visit_block(&mut self, block: &Block) {

View File

@ -68,17 +68,17 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
"unused import".to_string());
}
let (v_priv, t_priv) = match self.last_private.get(&id) {
Some(&LastImport {
value_priv: v,
value_used: _,
type_priv: t,
type_used: _
}) => (v, t),
Some(_) => {
let mut def_map = self.def_map.borrow_mut();
let path_res = if let Some(r) = def_map.get_mut(&id) {
r
} else {
return;
};
let (v_priv, t_priv) = match path_res.last_private {
LastImport { value_priv, type_priv, .. } => (value_priv, type_priv),
_ => {
panic!("we should only have LastImport for `use` directives")
}
_ => return,
};
let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
@ -100,10 +100,12 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
_ => {},
}
self.last_private.insert(id, LastImport{value_priv: v_priv,
value_used: v_used,
type_priv: t_priv,
type_used: t_used});
path_res.last_private = LastImport {
value_priv: v_priv,
value_used: v_used,
type_priv: t_priv,
type_used: t_used
};
}
}

File diff suppressed because it is too large Load Diff

View File

@ -218,7 +218,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
ref_id));
}
let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id];
let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def();
match def {
def::DefPrimTy(_) => None,
_ => Some(def.def_id()),
@ -231,15 +231,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
ref_id));
}
let def = (*def_map)[ref_id];
let def = def_map[ref_id].full_def();
match def {
def::DefMod(_) |
def::DefForeignMod(_) => Some(recorder::ModRef),
def::DefStruct(_) => Some(recorder::StructRef),
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefaultImpl(_) => Some(recorder::TypeRef),
def::DefTrait(_) => Some(recorder::TypeRef),
def::DefStatic(_, _) |
def::DefConst(_) |
def::DefLocal(_) |
@ -250,9 +249,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
def::DefSelfTy(_) |
def::DefRegion(_) |
def::DefTyParamBinder(_) |
def::DefLabel(_) |
def::DefStaticMethod(..) |
def::DefTyParam(..) |
def::DefUse(_) |
def::DefMethod(..) |
@ -662,9 +659,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
match typ.node {
// Common case impl for a struct or something basic.
ast::TyPath(ref path, id) => {
ast::TyPath(None, ref path) => {
let sub_span = self.span.sub_span_for_type_name(path.span);
let self_id = self.lookup_type_ref(id).map(|id| {
let self_id = self.lookup_type_ref(typ.id).map(|id| {
self.fmt.ref_str(recorder::TypeRef,
path.span,
sub_span,
@ -795,9 +792,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.span_bug(span,
&format!("def_map has no key for {} in visit_expr", id));
}
let def = &(*def_map)[id];
let def = def_map[id].full_def();
let sub_span = self.span.span_for_last_ident(span);
match *def {
match def {
def::DefUpvar(..) |
def::DefLocal(..) |
def::DefStatic(..) |
@ -817,8 +814,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
sub_span,
def_id,
self.cur_scope),
def::DefStaticMethod(declid, provenence) |
def::DefMethod(declid, _, provenence) => {
def::DefMethod(declid, provenence) => {
let sub_span = self.span.sub_span_for_meth_name(span);
let defid = if declid.krate == ast::LOCAL_CRATE {
let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
@ -870,11 +866,18 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
&format!("Unexpected def kind while looking \
up path in `{}`: `{:?}`",
self.span.snippet(span),
*def)),
def)),
}
// modules or types in the path prefix
match *def {
def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path),
match def {
def::DefMethod(did, _) => {
let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did);
if let ty::MethodTraitItem(m) = ti {
if m.explicit_self == ty::StaticExplicitSelfCategory {
self.write_sub_path_trait_truncated(path);
}
}
}
def::DefLocal(_) |
def::DefStatic(_,_) |
def::DefConst(..) |
@ -1001,7 +1004,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
visit::walk_path(self, path);
let def = self.analysis.ty_cx.def_map.borrow()[p.id];
let def = self.analysis.ty_cx.def_map.borrow()[p.id].full_def();
let struct_def = match def {
def::DefConst(..) => None,
def::DefVariant(_, variant_id, _) => Some(variant_id),
@ -1303,8 +1306,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
}
match t.node {
ast::TyPath(ref path, id) => {
match self.lookup_type_ref(id) {
ast::TyPath(_, ref path) => {
match self.lookup_type_ref(t.id) {
Some(id) => {
let sub_span = self.span.sub_span_for_type_name(t.span);
self.fmt.ref_str(recorder::TypeRef,
@ -1334,16 +1337,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
// Don't need to do anything for function calls,
// because just walking the callee path does what we want.
visit::walk_expr(self, ex);
},
ast::ExprPath(ref path) => {
self.process_path(ex.id, path.span, path, None);
visit::walk_path(self, path);
}
ast::ExprQPath(ref qpath) => {
let mut path = qpath.trait_ref.path.clone();
path.segments.push(qpath.item_path.clone());
self.process_path(ex.id, ex.span, &path, None);
visit::walk_qpath(self, ex.span, &**qpath);
ast::ExprPath(_, ref path) => {
self.process_path(ex.id, path.span, path, None);
visit::walk_expr(self, ex);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
@ -1459,8 +1456,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
&format!("def_map has no key for {} in visit_arm",
id));
}
let def = &(*def_map)[id];
match *def {
let def = def_map[id].full_def();
match def {
def::DefLocal(id) => {
let value = if *immut {
self.span.snippet(p.span).to_string()
@ -1483,7 +1480,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
def::DefStatic(_, _) => {}
def::DefConst(..) => {}
_ => error!("unexpected definition kind when processing collected paths: {:?}",
*def)
def)
}
}
for &(id, ref path, ref_kind) in &paths_to_process {

View File

@ -238,6 +238,7 @@ impl<'a> SpanUtils<'a> {
let mut toks = self.retokenise_span(span);
// We keep track of how many brackets we're nested in
let mut bracket_count = 0;
let mut found_ufcs_sep = false;
loop {
let ts = toks.real_token();
if ts.tok == token::Eof {
@ -254,13 +255,20 @@ impl<'a> SpanUtils<'a> {
}
bracket_count += match ts.tok {
token::Lt => 1,
token::Gt => -1,
token::Gt => {
// Ignore the `>::` in `<Type as Trait>::AssocTy`.
if !found_ufcs_sep && bracket_count == 0 {
found_ufcs_sep = true;
0
} else {
-1
}
}
token::BinOp(token::Shl) => 2,
token::BinOp(token::Shr) => -2,
_ => 0
};
if ts.tok.is_ident() &&
bracket_count == nesting {
if ts.tok.is_ident() && bracket_count == nesting {
result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
}
}

View File

@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
// This is either an enum variant or a variable binding.
let opt_def = tcx.def_map.borrow().get(&cur.id).cloned();
let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => {
let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
@ -725,14 +725,14 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
match pat.node {
ast::PatTup(_) => true,
ast::PatStruct(..) => {
match tcx.def_map.borrow().get(&pat.id) {
Some(&def::DefVariant(..)) => false,
match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(def::DefVariant(..)) => false,
_ => true,
}
}
ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
match tcx.def_map.borrow().get(&pat.id) {
Some(&def::DefStruct(..)) => true,
match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(def::DefStruct(..)) => true,
_ => false
}
}
@ -1277,20 +1277,20 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
let (vid, field) = match discr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
ast::ExprPath(..) => match bcx.def(discr.id) {
def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None),
_ => return false
},
ast::ExprField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
_ => return false
};
(vid, Some(mc::NamedField(field.node.name)))
},
ast::ExprTupField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
_ => return false
};
(vid, Some(mc::PositionalField(field.node)))
@ -1689,7 +1689,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
ast::PatEnum(_, ref sub_pats) => {
let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned();
let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => {
let repr = adt::represent_node(bcx, pat.id);

View File

@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
// pick out special kinds of expressions that can be called:
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
return trans_def(bcx, bcx.def(expr.id), expr);
}
_ => {}
@ -165,13 +165,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
}
def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
def::DefStaticMethod(did, def::FromImpl(_)) => {
def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => {
fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
bcx.fcx.param_substs).val)
}
def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
def::DefMethod(meth_did, def::FromTrait(trait_did)) => {
fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
meth_did,
trait_did,
@ -207,11 +205,10 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
def::DefUpvar(..) => {
datum_callee(bcx, ref_expr)
}
def::DefMod(..) | def::DefForeignMod(..) | def::DefaultImpl(..) |
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
def::DefUse(..) | def::DefTyParamBinder(..) |
def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |
def::DefSelfTy(..) | def::DefAssociatedPath(..) => {
def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) |
def::DefTyParam(..) | def::DefSelfTy(..) => {
bcx.tcx().sess.span_bug(
ref_expr.span,
&format!("cannot translate def {:?} \

View File

@ -603,7 +603,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
pub fn def(&self, nid: ast::NodeId) -> def::Def {
match self.tcx().def_map.borrow().get(&nid) {
Some(v) => v.clone(),
Some(v) => v.full_def(),
None => {
self.tcx().sess.bug(&format!(
"no def associated with node id {}", nid));

View File

@ -193,8 +193,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-> ValueRef {
// Special-case constants to cache a common global for all uses.
match expr.node {
ast::ExprPath(_) => {
let def = ccx.tcx().def_map.borrow()[expr.id];
ast::ExprPath(..) => {
let def = ccx.tcx().def_map.borrow()[expr.id].full_def();
match def {
def::DefConst(def_id) => {
if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
@ -582,7 +582,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
_ => break,
}
}
let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned();
let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
if let Some(def::DefStatic(def_id, _)) = opt_def {
return get_static_val(cx, def_id, ety);
}
@ -663,10 +663,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
C_array(llunitty, &vs[..])
}
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = cx.tcx().def_map.borrow()[e.id];
ast::ExprPath(..) => {
let def = cx.tcx().def_map.borrow()[e.id].full_def();
match def {
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
def::DefFn(..) | def::DefMethod(..) => {
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
}
def::DefConst(def_id) => {
@ -701,7 +701,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}
ast::ExprCall(ref callee, ref args) => {
let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned();
let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def());
let arg_vals = map_list(&args[..]);
match opt_def {
Some(def::DefStruct(_)) => {

View File

@ -306,11 +306,10 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let loop_id = match opt_label {
None => fcx.top_loop_scope(),
Some(_) => {
match bcx.tcx().def_map.borrow().get(&expr.id) {
Some(&def::DefLabel(loop_id)) => loop_id,
ref r => {
bcx.tcx().sess.bug(&format!("{:?} in def-map for label",
r))
match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
Some(def::DefLabel(loop_id)) => loop_id,
r => {
bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
}
}
}

View File

@ -3487,8 +3487,7 @@ fn create_scope_map(cx: &CrateContext,
ast::ExprLit(_) |
ast::ExprBreak(_) |
ast::ExprAgain(_) |
ast::ExprPath(_) |
ast::ExprQPath(_) => {}
ast::ExprPath(..) => {}
ast::ExprCast(ref sub_exp, _) |
ast::ExprAddrOf(_, ref sub_exp) |

View File

@ -143,7 +143,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// it prefers in-place instantiation, likely because it contains
// `[x; N]` somewhere within.
match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
match bcx.def(expr.id) {
def::DefConst(did) => {
let expr = consts::get_const_expr(bcx.ccx(), did, expr);
@ -629,7 +629,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ast::ExprParen(ref e) => {
trans(bcx, &**e)
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
trans_def(bcx, expr, bcx.def(expr.id))
}
ast::ExprField(ref base, ident) => {
@ -875,7 +875,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_def_lvalue");
match def {
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
def::DefFn(..) | def::DefMethod(..) |
def::DefStruct(_) | def::DefVariant(..) => {
let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
bcx.fcx.param_substs);
@ -1033,7 +1033,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ast::ExprParen(ref e) => {
trans_into(bcx, &**e, dest)
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
ast::ExprPath(..) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
}
ast::ExprIf(ref cond, ref thn, ref els) => {
@ -1275,12 +1275,10 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
match def {
def::DefFn(did, _) |
def::DefStruct(did) | def::DefVariant(_, did, _) |
def::DefStaticMethod(did, def::FromImpl(_)) |
def::DefMethod(did, _, def::FromImpl(_)) => {
def::DefMethod(did, def::FromImpl(_)) => {
callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
}
def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) |
def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => {
def::DefMethod(impl_did, def::FromTrait(trait_did)) => {
meth::trans_static_method_callee(ccx, impl_did,
trait_did, ref_expr.id,
param_substs)
@ -1365,7 +1363,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
ty.repr(tcx)));
}
Some(node_id) => {
let def = tcx.def_map.borrow()[node_id].clone();
let def = tcx.def_map.borrow()[node_id].full_def();
match def {
def::DefVariant(enum_id, variant_id, _) => {
let variant_info = ty::enum_variant_with_id(

View File

@ -48,22 +48,23 @@
//! case but `&a` in the second. Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
use middle::const_eval;
use middle::def;
use middle::resolve_lifetime as rl;
use middle::privacy::{AllPublic, LastMod};
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::traits;
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
use TypeAndSubsts;
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::DefIdMap;
use util::ppaux::{self, Repr, UserString};
use std::rc::Rc;
use std::iter::{repeat, AdditiveIterator};
use std::rc::Rc;
use std::slice;
use syntax::{abi, ast, ast_util};
use syntax::codemap::Span;
use syntax::parse::token;
@ -245,8 +246,10 @@ pub fn opt_ast_region_to_region<'tcx>(
pub fn ast_path_substs_for_ty<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
decl_generics: &ty::Generics<'tcx>,
path: &ast::Path)
item_segment: &ast::PathSegment)
-> Substs<'tcx>
{
let tcx = this.tcx();
@ -262,27 +265,36 @@ pub fn ast_path_substs_for_ty<'tcx>(
assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
assert!(decl_generics.types.all(|d| d.space != FnSpace));
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
let (regions, types, assoc_bindings) = match item_segment.parameters {
ast::AngleBracketedParameters(ref data) => {
convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data)
convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
}
ast::ParenthesizedParameters(ref data) => {
span_err!(tcx.sess, path.span, E0214,
span_err!(tcx.sess, span, E0214,
"parenthesized parameters may only be used with a trait");
convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data)
convert_parenthesized_parameters(this, rscope, span, decl_generics, data)
}
};
prohibit_projections(this.tcx(), &assoc_bindings);
create_substs_for_ast_path(this,
path.span,
span,
param_mode,
decl_generics,
None,
types,
regions)
}
#[derive(PartialEq, Eq)]
pub enum PathParamMode {
// Any path in a type context.
Explicit,
// The `module::Type` in `module::Type::method` in an expression.
Optional
}
fn create_region_substs<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
@ -330,6 +342,7 @@ fn create_region_substs<'tcx>(
fn create_substs_for_ast_path<'tcx>(
this: &AstConv<'tcx>,
span: Span,
param_mode: PathParamMode,
decl_generics: &ty::Generics<'tcx>,
self_ty: Option<Ty<'tcx>>,
types_provided: Vec<Ty<'tcx>>,
@ -348,13 +361,21 @@ fn create_substs_for_ast_path<'tcx>(
// Convert the type parameters supplied by the user.
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
let supplied_ty_param_count = types_provided.len();
let formal_ty_param_count = ty_param_defs.len();
let required_ty_param_count = ty_param_defs.iter()
.take_while(|x| x.default.is_none())
.count();
let mut type_substs = types_provided;
// Fill with `ty_infer` if no params were specified, as long as
// they were optional (e.g. paths inside expressions).
let mut type_substs = if param_mode == PathParamMode::Optional &&
types_provided.is_empty() {
(0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect()
} else {
types_provided
};
let supplied_ty_param_count = type_substs.len();
check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
required_ty_param_count, formal_ty_param_count);
@ -414,7 +435,7 @@ fn create_substs_for_ast_path<'tcx>(
}
}
return substs;
substs
}
struct ConvertedBinding<'tcx> {
@ -574,9 +595,9 @@ pub fn instantiate_poly_trait_ref<'tcx>(
// lifetimes. Oh well, not there yet.
let shifted_rscope = ShiftedRscope::new(rscope);
let trait_ref =
instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
self_ty, Some(&mut projections));
let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
&ast_trait_ref.trait_ref,
None, self_ty, Some(&mut projections));
for projection in projections {
poly_projections.push(ty::Binder(projection));
@ -594,26 +615,31 @@ pub fn instantiate_poly_trait_ref<'tcx>(
pub fn instantiate_trait_ref<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
ast_trait_ref: &ast::TraitRef,
trait_ref: &ast::TraitRef,
impl_id: Option<ast::NodeId>,
self_ty: Option<Ty<'tcx>>,
projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
-> Rc<ty::TraitRef<'tcx>>
{
match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
def::DefaultImpl(trait_def_id) => {
let path = &trait_ref.path;
match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
def::DefTrait(trait_def_id) => {
let trait_ref = ast_path_to_trait_ref(this,
rscope,
path.span,
PathParamMode::Explicit,
trait_def_id,
self_ty,
&ast_trait_ref.path,
path.segments.last().unwrap(),
projections);
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone());
if let Some(id) = impl_id {
this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
}
trait_ref
}
_ => {
span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245,
"`{}` is not a trait",
ast_trait_ref.path.user_string(this.tcx()));
span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
path.user_string(this.tcx()));
}
}
}
@ -621,8 +647,10 @@ pub fn instantiate_trait_ref<'tcx>(
fn object_path_to_poly_trait_ref<'a,'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
trait_def_id: ast::DefId,
path: &ast::Path,
trait_segment: &ast::PathSegment,
mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
@ -633,9 +661,11 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
let mut tmp = Vec::new();
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
&shifted_rscope,
span,
param_mode,
trait_def_id,
None,
path,
trait_segment,
Some(&mut tmp)));
projections.extend(tmp.into_iter().map(ty::Binder));
trait_ref
@ -644,48 +674,51 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
fn ast_path_to_trait_ref<'a,'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
trait_def_id: ast::DefId,
self_ty: Option<Ty<'tcx>>,
path: &ast::Path,
trait_segment: &ast::PathSegment,
mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
-> Rc<ty::TraitRef<'tcx>>
{
debug!("ast_path_to_trait_ref {:?}", path);
debug!("ast_path_to_trait_ref {:?}", trait_segment);
let trait_def = this.get_trait_def(trait_def_id);
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
let (regions, types, assoc_bindings) = match trait_segment.parameters {
ast::AngleBracketedParameters(ref data) => {
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
span_err!(this.tcx().sess, path.span, E0215,
span_err!(this.tcx().sess, span, E0215,
"angle-bracket notation is not stable when \
used with the `Fn` family of traits, use parentheses");
span_help!(this.tcx().sess, path.span,
span_help!(this.tcx().sess, span,
"add `#![feature(unboxed_closures)]` to \
the crate attributes to enable");
}
convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data)
convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
}
ast::ParenthesizedParameters(ref data) => {
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
span_err!(this.tcx().sess, path.span, E0216,
span_err!(this.tcx().sess, span, E0216,
"parenthetical notation is only stable when \
used with the `Fn` family of traits");
span_help!(this.tcx().sess, path.span,
span_help!(this.tcx().sess, span,
"add `#![feature(unboxed_closures)]` to \
the crate attributes to enable");
}
convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data)
convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data)
}
};
let substs = create_substs_for_ast_path(this,
path.span,
span,
param_mode,
&trait_def.generics,
self_ty,
types,
@ -818,78 +851,31 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
})
}
pub fn ast_path_to_ty<'tcx>(
fn ast_path_to_ty<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
did: ast::DefId,
path: &ast::Path)
-> TypeAndSubsts<'tcx>
item_segment: &ast::PathSegment)
-> Ty<'tcx>
{
let tcx = this.tcx();
let ty::TypeScheme {
generics,
ty: decl_ty
} = this.get_item_type_scheme(did);
let substs = ast_path_substs_for_ty(this,
rscope,
&generics,
path);
let ty = decl_ty.subst(tcx, &substs);
TypeAndSubsts { substs: substs, ty: ty }
}
let substs = ast_path_substs_for_ty(this, rscope,
span, param_mode,
&generics, item_segment);
/// Converts the given AST type to a built-in type. A "built-in type" is, at
/// present, either a core numeric type, a string, or `Box`.
pub fn ast_ty_to_builtin_ty<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
ast_ty: &ast::Ty)
-> Option<Ty<'tcx>> {
match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
Some(typ) => return Some(typ),
None => {}
// FIXME(#12938): This is a hack until we have full support for DST.
if Some(did) == this.tcx().lang_items.owned_box() {
assert_eq!(substs.types.len(TypeSpace), 1);
return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0));
}
match ast_ty.node {
ast::TyPath(ref path, id) => {
let a_def = match this.tcx().def_map.borrow().get(&id) {
None => {
this.tcx()
.sess
.span_bug(ast_ty.span,
&format!("unbound path {}",
path.repr(this.tcx())))
}
Some(&d) => d
};
// FIXME(#12938): This is a hack until we have full support for
// DST.
match a_def {
def::DefTy(did, _) |
def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
let ty = ast_path_to_ty(this, rscope, did, path).ty;
match ty.sty {
ty::ty_struct(struct_def_id, ref substs) => {
assert_eq!(struct_def_id, did);
assert_eq!(substs.types.len(TypeSpace), 1);
let referent_ty = *substs.types.get(TypeSpace, 0);
Some(ty::mk_uniq(this.tcx(), referent_ty))
}
_ => {
this.tcx().sess.span_bug(
path.span,
&format!("converting `Box` to `{}`",
ty.repr(this.tcx())));
}
}
}
_ => None
}
}
_ => None
}
decl_ty.subst(this.tcx(), &substs)
}
type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
@ -912,14 +898,20 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
*/
match ty.node {
ast::TyPath(ref path, id) => {
match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefaultImpl(trait_def_id)) => {
ast::TyPath(None, ref path) => {
let def = match this.tcx().def_map.borrow().get(&ty.id) {
Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def),
_ => None
};
match def {
Some(def::DefTrait(trait_def_id)) => {
let mut projection_bounds = Vec::new();
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
path.span,
PathParamMode::Explicit,
trait_def_id,
path,
path.segments.last().unwrap(),
&mut projection_bounds);
Ok((trait_ref, projection_bounds))
}
@ -983,21 +975,40 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
}
fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
ast_ty: &ast::Ty,
provenance: def::TyParamProvenance,
assoc_name: ast::Name)
-> Ty<'tcx>
span: Span,
ty: Ty<'tcx>,
ty_path_def: def::Def,
item_segment: &ast::PathSegment)
-> (Ty<'tcx>, def::Def)
{
let tcx = this.tcx();
let ty_param_def_id = provenance.def_id();
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
let assoc_name = item_segment.identifier.name;
let is_param = match (&ty.sty, ty_path_def) {
(&ty::ty_param(_), def::DefTyParam(..)) |
(&ty::ty_param(_), def::DefSelfTy(_)) => true,
_ => false
};
let ty_param_node_id = if is_param {
ty_path_def.local_node_id()
} else {
span_err!(tcx.sess, span, E0223,
"ambiguous associated type; specify the type using the syntax \
`<{} as Trait>::{}`",
ty.user_string(tcx), token::get_name(assoc_name));
return (tcx.types.err, ty_path_def);
};
let mut suitable_bounds: Vec<_>;
let ty_param_name: ast::Name;
{ // contain scope of refcell:
let ty_param_defs = tcx.ty_param_defs.borrow();
let ty_param_def = &ty_param_defs[ty_param_def_id.node];
let ty_param_def = &ty_param_defs[ty_param_node_id];
ty_param_name = ty_param_def.name;
// FIXME(#20300) -- search where clauses, not bounds
suitable_bounds =
traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds)
@ -1006,21 +1017,21 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
}
if suitable_bounds.len() == 0 {
span_err!(tcx.sess, ast_ty.span, E0220,
span_err!(tcx.sess, span, E0220,
"associated type `{}` not found for type parameter `{}`",
token::get_name(assoc_name),
token::get_name(ty_param_name));
return this.tcx().types.err;
return (this.tcx().types.err, ty_path_def);
}
if suitable_bounds.len() > 1 {
span_err!(tcx.sess, ast_ty.span, E0221,
span_err!(tcx.sess, span, E0221,
"ambiguous associated type `{}` in bounds of `{}`",
token::get_name(assoc_name),
token::get_name(ty_param_name));
for suitable_bound in &suitable_bounds {
span_note!(this.tcx().sess, ast_ty.span,
span_note!(this.tcx().sess, span,
"associated type `{}` could derive from `{}`",
token::get_name(ty_param_name),
suitable_bound.user_string(this.tcx()));
@ -1028,7 +1039,32 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
}
let suitable_bound = suitable_bounds.pop().unwrap().clone();
return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name);
let trait_did = suitable_bound.0.def_id;
let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name);
let item_did = if trait_did.krate == ast::LOCAL_CRATE {
// `ty::trait_items` used below requires information generated
// by type collection, which may be in progress at this point.
match this.tcx().map.expect_item(trait_did.node).node {
ast::ItemTrait(_, _, _, ref trait_items) => {
trait_items.iter().filter_map(|i| {
if let ast::TypeTraitItem(ref assoc) = *i {
if assoc.ty_param.ident.name == assoc_name {
return Some(ast_util::local_def(assoc.ty_param.id));
}
}
None
}).next().expect("missing associated type")
}
_ => unreachable!()
}
} else {
let trait_items = ty::trait_items(this.tcx(), trait_did);
let item = trait_items.iter().find(|i| i.name() == assoc_name);
item.expect("missing associated type").def_id()
};
(ty, def::DefAssociatedTy(trait_did, item_did))
}
fn trait_defines_associated_type_named(this: &AstConv,
@ -1043,31 +1079,43 @@ fn trait_defines_associated_type_named(this: &AstConv,
fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
rscope: &RegionScope,
ast_ty: &ast::Ty, // the TyQPath
qpath: &ast::QPath)
span: Span,
param_mode: PathParamMode,
opt_self_ty: Option<Ty<'tcx>>,
trait_def_id: ast::DefId,
trait_segment: &ast::PathSegment,
item_segment: &ast::PathSegment)
-> Ty<'tcx>
{
debug!("qpath_to_ty(ast_ty={})",
ast_ty.repr(this.tcx()));
let tcx = this.tcx();
let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
let self_ty = if let Some(ty) = opt_self_ty {
ty
} else {
let path_str = ty::item_path_str(tcx, trait_def_id);
span_err!(tcx.sess, span, E0223,
"ambiguous associated type; specify the type using the syntax \
`<Type as {}>::{}`",
path_str, &token::get_ident(item_segment.identifier));
return tcx.types.err;
};
let trait_ref = instantiate_trait_ref(this,
debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
let trait_ref = ast_path_to_trait_ref(this,
rscope,
&*qpath.trait_ref,
Some(self_type),
span,
param_mode,
trait_def_id,
Some(self_ty),
trait_segment,
None);
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
// `<T as Trait>::U<V>` shouldn't parse right now.
assert!(qpath.item_path.parameters.is_empty());
return this.projected_ty(ast_ty.span,
trait_ref,
qpath.item_path.identifier.name);
this.projected_ty(span, trait_ref, item_segment.identifier.name)
}
/// Convert a type supplied as value for a type argument from AST into our
@ -1103,6 +1151,96 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
}
}
pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
def: &mut def::Def,
opt_self_ty: Option<Ty<'tcx>>,
segments: &[ast::PathSegment],
assoc_segments: &[ast::PathSegment])
-> Ty<'tcx> {
let tcx = this.tcx();
let base_ty = match *def {
def::DefTrait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let mut projection_bounds = Vec::new();
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
span,
param_mode,
trait_def_id,
segments.last().unwrap(),
&mut projection_bounds);
check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
trait_ref_to_object_type(this, rscope, span, trait_ref,
projection_bounds, &[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
ast_path_to_ty(this, rscope, span,
param_mode, did,
segments.last().unwrap())
}
def::DefTyParam(space, index, _, name) => {
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
ty::mk_param(tcx, space, index, name)
}
def::DefSelfTy(_) => {
// n.b.: resolve guarantees that the this type only appears in a
// trait, which we rely upon in various places when creating
// substs
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
ty::mk_self_type(tcx)
}
def::DefAssociatedTy(trait_did, _) => {
check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS);
qpath_to_ty(this, rscope, span, param_mode,
opt_self_ty, trait_did,
&segments[segments.len()-2],
segments.last().unwrap())
}
def::DefMod(id) => {
// Used as sentinel by callers to indicate the `<T>::A::B::C` form.
// FIXME(#22519) This part of the resolution logic should be
// avoided entirely for that form, once we stop needed a Def
// for `associated_path_def_to_ty`.
if segments.is_empty() {
opt_self_ty.expect("missing T in <T>::a::b::c")
} else {
tcx.sess.span_bug(span,
&format!("found module name used as a type: {}",
tcx.map.node_to_string(id.node)));
}
}
def::DefPrimTy(prim_ty) => {
prim_ty_to_ty(tcx, segments, prim_ty)
}
_ => {
span_fatal!(tcx.sess, span, E0248,
"found value name used as a type: {:?}", *def);
}
};
// If any associated type segments remain, attempt to resolve them.
let mut ty = base_ty;
for segment in assoc_segments {
if ty.sty == ty::ty_err {
break;
}
// This is pretty bad (it will fail except for T::A and Self::A).
let (a_ty, a_def) = associated_path_def_to_ty(this, span,
ty, *def, segment);
ty = a_ty;
*def = a_def;
}
ty
}
/// Parses the programmer's textual representation of a type into our
/// internal notion of a type.
pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
@ -1129,173 +1267,128 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
drop(ast_ty_to_ty_cache);
let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
match ast_ty.node {
ast::TyVec(ref ty) => {
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
ast::TyObjectSum(ref ty, ref bounds) => {
match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) {
Ok((trait_ref, projection_bounds)) => {
trait_ref_to_object_type(this,
rscope,
ast_ty.span,
trait_ref,
projection_bounds,
&bounds[..])
}
Err(ErrorReported) => {
this.tcx().types.err
}
let typ = match ast_ty.node {
ast::TyVec(ref ty) => {
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
ast::TyObjectSum(ref ty, ref bounds) => {
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
Ok((trait_ref, projection_bounds)) => {
trait_ref_to_object_type(this,
rscope,
ast_ty.span,
trait_ref,
projection_bounds,
bounds)
}
}
ast::TyPtr(ref mt) => {
ty::mk_ptr(tcx, ty::mt {
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
mutbl: mt.mutbl
})
}
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
let rscope1 =
&ObjectLifetimeDefaultRscope::new(
rscope,
Some(ty::ObjectLifetimeDefault::Specific(r)));
let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
}
ast::TyTup(ref fields) => {
let flds = fields.iter()
.map(|t| ast_ty_to_ty(this, rscope, &**t))
.collect();
ty::mk_tup(tcx, flds)
}
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
ast::TyBareFn(ref bf) => {
if bf.decl.variadic && bf.abi != abi::C {
span_err!(tcx.sess, ast_ty.span, E0222,
"variadic function must have C calling convention");
Err(ErrorReported) => {
this.tcx().types.err
}
let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
}
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
}
ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess
.span_bug(ast_ty.span,
&format!("unbound path {}",
path.repr(tcx)))
}
Some(&d) => d
};
match a_def {
def::DefaultImpl(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let mut projection_bounds = Vec::new();
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
trait_def_id,
path,
&mut projection_bounds);
trait_ref_to_object_type(this, rscope, path.span,
trait_ref, projection_bounds, &[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty
}
def::DefTyParam(space, index, _, name) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_param(tcx, space, index, name)
}
def::DefSelfTy(_) => {
// n.b.: resolve guarantees that the this type only appears in a
// trait, which we rely upon in various places when creating
// substs
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_self_type(tcx)
}
def::DefMod(id) => {
span_fatal!(tcx.sess, ast_ty.span, E0247,
"found module name used as a type: {}",
tcx.map.node_to_string(id.node));
}
def::DefPrimTy(_) => {
panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
}
def::DefAssociatedTy(trait_type_id) => {
let path_str = tcx.map.path_to_string(
tcx.map.get_parent(trait_type_id.node));
span_err!(tcx.sess, ast_ty.span, E0223,
"ambiguous associated \
type; specify the type \
using the syntax `<Type \
as {}>::{}`",
path_str,
&token::get_ident(
path.segments
.last()
.unwrap()
.identifier));
this.tcx().types.err
}
def::DefAssociatedPath(provenance, assoc_ident) => {
associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
}
_ => {
span_fatal!(tcx.sess, ast_ty.span, E0248,
"found value name used \
as a type: {:?}",
a_def);
}
}
}
ast::TyQPath(ref qpath) => {
qpath_to_ty(this, rscope, ast_ty, &**qpath)
}
ast::TyFixedLengthVec(ref ty, ref e) => {
match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
Ok(ref r) => {
match *r {
const_eval::const_int(i) =>
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
Some(i as uint)),
const_eval::const_uint(i) =>
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
Some(i as uint)),
_ => {
span_fatal!(tcx.sess, ast_ty.span, E0249,
"expected constant expr for array length");
}
}
}
Err(ref r) => {
span_fatal!(tcx.sess, ast_ty.span, E0250,
"expected constant expr for array \
length: {}",
*r);
}
}
}
ast::TyTypeof(ref _e) => {
tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
}
ast::TyInfer => {
// TyInfer also appears as the type of arguments or return
// values in a ExprClosure, or as
// the type of local variables. Both of these cases are
// handled specially and will not descend into this routine.
this.ty_infer(ast_ty.span)
}
}
});
ast::TyPtr(ref mt) => {
ty::mk_ptr(tcx, ty::mt {
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
mutbl: mt.mutbl
})
}
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
let rscope1 =
&ObjectLifetimeDefaultRscope::new(
rscope,
Some(ty::ObjectLifetimeDefault::Specific(r)));
let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
}
ast::TyTup(ref fields) => {
let flds = fields.iter()
.map(|t| ast_ty_to_ty(this, rscope, &**t))
.collect();
ty::mk_tup(tcx, flds)
}
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
ast::TyBareFn(ref bf) => {
if bf.decl.variadic && bf.abi != abi::C {
span_err!(tcx.sess, ast_ty.span, E0222,
"variadic function must have C calling convention");
}
let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
}
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
}
ast::TyPath(ref maybe_qself, ref path) => {
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
d
} else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)),
last_private: LastMod(AllPublic),
depth: path.segments.len()
}
} else {
tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}", ast_ty.repr(tcx)))
};
let mut def = path_res.base_def;
let base_ty_end = path.segments.len() - path_res.depth;
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
ast_ty_to_ty(this, rscope, &qself.ty)
});
let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span,
PathParamMode::Explicit, &mut def,
opt_self_ty,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);
if path_res.depth != 0 && ty.sty != ty::ty_err {
// Write back the new resolution.
tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution {
base_def: def,
last_private: path_res.last_private,
depth: 0
});
}
ty
}
ast::TyFixedLengthVec(ref ty, ref e) => {
match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
Ok(r) => {
match r {
const_eval::const_int(i) =>
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
Some(i as uint)),
const_eval::const_uint(i) =>
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
Some(i as uint)),
_ => {
span_fatal!(tcx.sess, ast_ty.span, E0249,
"expected constant expr for array length");
}
}
}
Err(r) => {
span_fatal!(tcx.sess, ast_ty.span, E0250,
"expected constant expr for array length: {}", r);
}
}
}
ast::TyTypeof(ref _e) => {
tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
}
ast::TyInfer => {
// TyInfer also appears as the type of arguments or return
// values in a ExprClosure, or as
// the type of local variables. Both of these cases are
// handled specially and will not descend into this routine.
this.ty_infer(ast_ty.span)
}
};
tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
return typ;
@ -1803,8 +1896,8 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
for ast_bound in ast_bounds {
match *ast_bound {
ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefaultImpl(trait_did) => {
match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefTrait(trait_did) => {
match trait_def_ids.get(&trait_did) {
// Already seen this trait. We forbid
// duplicates in the list (for some

View File

@ -103,7 +103,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
demand::eqtype(fcx, pat.span, expected, lhs_ty);
}
ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
let const_did = tcx.def_map.borrow()[pat.id].def_id();
let const_scheme = ty::lookup_item_type(tcx, const_did);
assert!(const_scheme.generics.is_empty());
let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
@ -433,9 +433,9 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow()[pat.id].clone();
let def = tcx.def_map.borrow()[pat.id].full_def();
let (enum_def_id, variant_def_id) = match def {
def::DefaultImpl(_) => {
def::DefTrait(_) => {
let name = pprust::path_to_string(path);
span_err!(tcx.sess, pat.span, E0168,
"use of trait `{}` in a struct pattern", name);
@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
};
instantiate_path(pcx.fcx,
path,
&path.segments,
ty::lookup_item_type(tcx, enum_def_id),
&ty::lookup_predicates(tcx, enum_def_id),
None,
@ -502,7 +502,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow()[pat.id].clone();
let def = tcx.def_map.borrow()[pat.id].full_def();
let enum_def = def.variant_def_ids()
.map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
} else {
ctor_scheme
};
instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id);
instantiate_path(pcx.fcx, &path.segments,
path_scheme, &ctor_predicates,
None, def, pat.span, pat.id);
let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);

View File

@ -14,6 +14,8 @@ use astconv::AstConv;
use check::{FnCtxt};
use check::vtable;
use check::vtable::select_new_fcx_obligations;
use middle::def;
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
use middle::subst;
use middle::traits;
use middle::ty::*;
@ -66,7 +68,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr_id: ast::NodeId)
-> bool
{
match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
let mode = probe::Mode::MethodCall;
match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) {
Ok(..) => true,
Err(NoMatch(..)) => false,
Err(Ambiguity(..)) => true,
@ -103,8 +106,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr.repr(fcx.tcx()),
self_expr.repr(fcx.tcx()));
let mode = probe::Mode::MethodCall;
let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id));
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id));
Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
}
@ -301,6 +305,29 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some(callee)
}
pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
method_name: ast::Name,
self_ty: Ty<'tcx>,
expr_id: ast::NodeId)
-> Result<(def::Def, LastPrivate), MethodError>
{
let mode = probe::Mode::Path;
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
let def_id = pick.method_ty.def_id;
let mut lp = LastMod(AllPublic);
let provenance = match pick.kind {
probe::InherentImplPick(impl_def_id) => {
if pick.method_ty.vis != ast::Public {
lp = LastMod(DependsOn(def_id));
}
def::FromImpl(impl_def_id)
}
_ => def::FromTrait(pick.method_ty.container.id())
};
Ok((def::DefMethod(def_id, provenance), lp))
}
/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
/// index (or `None`, if no such method).

View File

@ -37,6 +37,7 @@ pub use self::PickKind::*;
struct ProbeContext<'a, 'tcx:'a> {
fcx: &'a FnCtxt<'a, 'tcx>,
span: Span,
mode: Mode,
method_name: ast::Name,
steps: Rc<Vec<CandidateStep<'tcx>>>,
opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
@ -108,17 +109,30 @@ pub enum PickAdjustment {
AutoRef(ast::Mutability, Box<PickAdjustment>),
}
#[derive(PartialEq, Eq, Copy)]
pub enum Mode {
// An expression of the form `receiver.method_name(...)`.
// Autoderefs are performed on `receiver`, lookup is done based on the
// `self` argument of the method, and static methods aren't considered.
MethodCall,
// An expression of the form `Type::method` or `<T>::method`.
// No autoderefs are performed, lookup is done based on the type each
// implementation is for, and static methods are included.
Path
}
pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
mode: Mode,
method_name: ast::Name,
self_ty: Ty<'tcx>,
call_expr_id: ast::NodeId)
scope_expr_id: ast::NodeId)
-> PickResult<'tcx>
{
debug!("probe(self_ty={}, method_name={}, call_expr_id={})",
debug!("probe(self_ty={}, method_name={}, scope_expr_id={})",
self_ty.repr(fcx.tcx()),
method_name,
call_expr_id);
scope_expr_id);
// FIXME(#18741) -- right now, creating the steps involves evaluating the
// `*` operator, which registers obligations that then escape into
@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// it ride, although it's really not great, and in fact could I
// think cause spurious errors. Really though this part should
// take place in the `fcx.infcx().probe` below.
let steps = match create_steps(fcx, span, self_ty) {
Some(steps) => steps,
None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
let steps = if mode == Mode::MethodCall {
match create_steps(fcx, span, self_ty) {
Some(steps) => steps,
None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
}
} else {
vec![CandidateStep {
self_ty: self_ty,
adjustment: AutoDeref(0)
}]
};
// Create a list of simplified self types, if we can.
@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// this creates one big transaction so that all type variables etc
// that we create during the probe process are removed later
let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
fcx.infcx().probe(|_| {
let (steps, opt_simplified_steps) = dummy.take().unwrap();
let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
let mut probe_cx = ProbeContext::new(fcx,
span,
mode,
method_name,
steps,
opt_simplified_steps);
probe_cx.assemble_inherent_candidates();
try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id));
try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id));
probe_cx.pick()
})
}
@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn new(fcx: &'a FnCtxt<'a,'tcx>,
span: Span,
mode: Mode,
method_name: ast::Name,
steps: Vec<CandidateStep<'tcx>>,
opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
@ -206,6 +231,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
ProbeContext {
fcx: fcx,
span: span,
mode: mode,
method_name: method_name,
inherent_candidates: Vec::new(),
extension_candidates: Vec::new(),
@ -255,6 +281,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
ty::ty_closure(did, _, _) => {
self.assemble_inherent_impl_candidates_for_type(did);
}
ty::ty_uniq(_) => {
if let Some(box_did) = self.tcx().lang_items.owned_box() {
self.assemble_inherent_impl_candidates_for_type(box_did);
}
}
ty::ty_param(p) => {
self.assemble_inherent_candidates_from_param(self_ty, p);
}
@ -292,11 +323,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
return self.record_static_candidate(ImplSource(impl_def_id));
}
let impl_substs = self.impl_substs(impl_def_id);
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
// Determine the receiver type that the method itself expects.
let xform_self_ty =
self.xform_self_ty(&method, &impl_substs);
self.xform_self_ty(&method, impl_ty, &impl_substs);
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
@ -330,7 +362,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
new_trait_ref.def_id,
method_num);
let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs);
let xform_self_ty = this.xform_self_ty(&m,
new_trait_ref.self_ty(),
new_trait_ref.substs);
this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
@ -373,7 +407,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
this.erase_late_bound_regions(&poly_trait_ref);
let xform_self_ty =
this.xform_self_ty(&m, trait_ref.substs);
this.xform_self_ty(&m,
trait_ref.self_ty(),
trait_ref.substs);
debug!("found match: trait_ref={} substs={} m={}",
trait_ref.repr(this.tcx()),
@ -540,7 +576,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
continue;
}
let impl_substs = self.impl_substs(impl_def_id);
let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
debug!("impl_substs={}", impl_substs.repr(self.tcx()));
@ -553,7 +589,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// Determine the receiver type that the method itself expects.
let xform_self_ty =
self.xform_self_ty(&method, impl_trait_ref.substs);
self.xform_self_ty(&method,
impl_trait_ref.self_ty(),
impl_trait_ref.substs);
debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
@ -630,7 +668,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
&trait_def.generics,
step.self_ty);
let xform_self_ty = self.xform_self_ty(&method_ty, &substs);
let xform_self_ty = self.xform_self_ty(&method_ty,
step.self_ty,
&substs);
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
method_ty: method_ty.clone(),
@ -684,7 +724,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
bound.repr(self.tcx()));
if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
let xform_self_ty = self.xform_self_ty(&method, bound.substs);
let xform_self_ty = self.xform_self_ty(&method,
bound.self_ty(),
bound.substs);
debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
bound.repr(self.tcx()),
@ -714,7 +756,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
.filter(|b| b.def_id() == trait_def_id)
{
let bound = self.erase_late_bound_regions(&poly_bound);
let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs);
let xform_self_ty = self.xform_self_ty(&method_ty,
bound.self_ty(),
bound.substs);
debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
bound.repr(self.tcx()),
@ -1023,7 +1067,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// "fast track" -- check for usage of sugar
match method.explicit_self {
ty::StaticExplicitSelfCategory => {
// fallthrough
if self.mode == Mode::Path {
return true;
}
}
ty::ByValueExplicitSelfCategory |
ty::ByReferenceExplicitSelfCategory(..) |
@ -1047,11 +1093,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn xform_self_ty(&self,
method: &Rc<ty::Method<'tcx>>,
impl_ty: Ty<'tcx>,
substs: &subst::Substs<'tcx>)
-> Ty<'tcx>
{
debug!("xform_self_ty(self_ty={}, substs={})",
method.fty.sig.0.inputs[0].repr(self.tcx()),
debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
impl_ty.repr(self.tcx()),
method.fty.sig.0.inputs.get(0).repr(self.tcx()),
substs.repr(self.tcx()));
assert!(!substs.has_escaping_regions());
@ -1063,6 +1111,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// if there are any.
assert_eq!(substs.types.len(subst::FnSpace), 0);
assert_eq!(substs.regions().len(subst::FnSpace), 0);
if self.mode == Mode::Path {
return impl_ty;
}
let placeholder;
let mut substs = substs;
if
@ -1094,9 +1147,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
xform_self_ty
}
fn impl_substs(&self,
impl_def_id: ast::DefId)
-> subst::Substs<'tcx>
/// Get the type of an impl and generate substitutions with placeholders.
fn impl_ty_and_substs(&self,
impl_def_id: ast::DefId)
-> (Ty<'tcx>, subst::Substs<'tcx>)
{
let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
@ -1108,7 +1162,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
impl_pty.generics.regions.map(
|_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static
subst::Substs::new(type_vars, region_placeholders)
let substs = subst::Substs::new(type_vars, region_placeholders);
(impl_pty.ty, substs)
}
/// Replace late-bound-regions bound by `value` with `'static` using

View File

@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
rcvr_ty: Ty<'tcx>,
method_name: ast::Name,
callee_expr: &ast::Expr,
rcvr_expr: Option<&ast::Expr>,
error: MethodError)
{
// avoid suggestions when we don't know what's going on.
@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let cx = fcx.tcx();
let method_ustring = method_name.user_string(cx);
// True if the type is a struct and contains a field with
// the same name as the not-found method
let is_field = match rcvr_ty.sty {
ty::ty_struct(did, _) =>
ty::lookup_struct_fields(cx, did)
.iter()
.any(|f| f.name.user_string(cx) == method_ustring),
_ => false
};
fcx.type_error_message(
span,
|actual| {
@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
None);
// If the method has the name of a field, give a help note
if is_field {
cx.sess.span_note(span,
&format!("use `(s.{0})(...)` if you meant to call the \
function stored in the `{0}` field", method_ustring));
if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
let fields = ty::lookup_struct_fields(cx, did);
if fields.iter().any(|f| f.name == method_name) {
cx.sess.span_note(span,
&format!("use `(s.{0})(...)` if you meant to call the \
function stored in the `{0}` field", method_ustring));
}
}
if static_sources.len() > 0 {
@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
report_candidates(fcx, span, method_name, static_sources);
}
suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
suggest_traits_to_import(fcx, span, rcvr_ty, method_name,
rcvr_expr, out_of_scope_traits)
}
MethodError::Ambiguity(sources) => {
@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
MethodError::ClosureAmbiguity(trait_def_id) => {
fcx.sess().span_err(
span,
&*format!("the `{}` method from the `{}` trait cannot be explicitly \
invoked on this closure as we have not yet inferred what \
kind of closure it is; use overloaded call notation instead \
(e.g., `{}()`)",
method_name.user_string(fcx.tcx()),
ty::item_path_str(fcx.tcx(), trait_def_id),
pprust::expr_to_string(callee_expr)));
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
invoked on this closure as we have not yet inferred what \
kind of closure it is",
method_name.user_string(fcx.tcx()),
ty::item_path_str(fcx.tcx(), trait_def_id));
let msg = if let Some(callee) = rcvr_expr {
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
msg, pprust::expr_to_string(callee))
} else {
msg
};
fcx.sess().span_err(span, &msg);
}
}
@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
rcvr_ty: Ty<'tcx>,
method_name: ast::Name,
rcvr_expr: Option<&ast::Expr>,
valid_out_of_scope_traits: Vec<ast::DefId>)
{
let tcx = fcx.tcx();
@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
return
}
let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty);
let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr);
// there's no implemented traits, so lets suggest some traits to
// implement, by finding ones that have the method name, and are
@ -233,33 +231,39 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
/// autoderefs of `rcvr_ty`.
fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
rcvr_ty: Ty<'tcx>) -> bool {
check::autoderef(fcx, span, rcvr_ty, None,
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|&: ty, _| {
let is_local = match ty.sty {
rcvr_ty: Ty<'tcx>,
rcvr_expr: Option<&ast::Expr>) -> bool {
fn is_local(ty: Ty) -> bool {
match ty.sty {
ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
ty::ty_param(_) => true,
// the user cannot implement traits for unboxed closures, so
// there's no point suggesting anything at all, local or not.
ty::ty_closure(..) => return Some(false),
// everything else (primitive types etc.) is effectively
// non-local (there are "edge" cases, e.g. (LocalType,), but
// the noise from these sort of types is usually just really
// annoying, rather than any sort of help).
_ => false
};
if is_local {
Some(true)
}
}
// This occurs for UFCS desugaring of `T::method`, where there is no
// receiver expression for the method call, and thus no autoderef.
if rcvr_expr.is_none() {
return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty));
}
check::autoderef(fcx, span, rcvr_ty, None,
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|ty, _| {
if is_local(ty) {
Some(())
} else {
None
}
}).2.unwrap_or(false)
}).2.is_some()
}
#[derive(Copy)]
@ -330,7 +334,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
cstore: &cstore::CStore,
dl: decoder::DefLike) {
match dl {
decoder::DlDef(def::DefaultImpl(did)) => {
decoder::DlDef(def::DefTrait(did)) => {
traits.push(TraitInfo::new(did));
}
decoder::DlDef(def::DefMod(did)) => {

View File

@ -82,14 +82,16 @@ pub use self::compare_method::compare_impl_method;
use self::IsBinopAssignment::*;
use self::TupleArgumentsFlag::*;
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
use check::_match::pat_ctxt;
use fmt_macros::{Parser, Piece, Position};
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
use middle::{const_eval, def};
use middle::infer;
use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
use middle::pat_util::{self, pat_id_map};
use middle::privacy::{AllPublic, LastMod};
use middle::region::{self, CodeExtent};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
use middle::traits;
@ -101,7 +103,7 @@ use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
use middle::ty_fold::{TypeFolder, TypeFoldable};
use rscope::RegionScope;
use session::Session;
use {CrateCtxt, lookup_def_ccx, require_same_types};
use {CrateCtxt, lookup_full_def, require_same_types};
use TypeAndSubsts;
use lint;
use util::common::{block_query, indenter, loop_query};
@ -1598,23 +1600,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty::TypeScheme { generics, ty: decl_ty } =
ty::lookup_item_type(tcx, did);
let wants_params =
generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
let needs_defaults =
wants_params &&
path.segments.iter().all(|s| s.parameters.is_empty());
let substs = if needs_defaults {
let tps =
self.infcx().next_ty_vars(generics.types.len(TypeSpace));
let rps =
self.infcx().region_vars_for_defs(path.span,
generics.regions.get_slice(TypeSpace));
Substs::new_type(tps, rps)
} else {
astconv::ast_path_substs_for_ty(self, self, &generics, path)
};
let substs = astconv::ast_path_substs_for_ty(self, self,
path.span,
PathParamMode::Optional,
&generics,
path.segments.last().unwrap());
let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
@ -2698,7 +2688,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
Err(error) => {
method::report_error(fcx, method_name.span, expr_t,
method_name.node.name, rcvr, error);
method_name.node.name, Some(rcvr), error);
fcx.write_error(expr.id);
fcx.tcx().types.err
}
@ -3408,10 +3398,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
let mut checked = false;
opt_place.as_ref().map(|place| match place.node {
ast::ExprPath(ref path) => {
ast::ExprPath(None, ref path) => {
// FIXME(pcwalton): For now we hardcode the two permissible
// places: the exchange heap and the managed heap.
let definition = lookup_def(fcx, path.span, place.id);
let definition = lookup_full_def(tcx, path.span, place.id);
let def_id = definition.def_id();
let referent_ty = fcx.expr_ty(&**subexpr);
if tcx.lang_items.exchange_heap() == Some(def_id) {
@ -3601,26 +3591,65 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
};
fcx.write_ty(id, oprnd_t);
}
ast::ExprPath(ref path) => {
let defn = lookup_def(fcx, path.span, id);
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
ast::ExprPath(ref maybe_qself, ref path) => {
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
fcx.to_ty(&qself.ty)
});
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
constrain_path_type_parameters(fcx, expr);
}
ast::ExprQPath(ref qpath) => {
// Require explicit type params for the trait.
let self_ty = fcx.to_ty(&*qpath.self_type);
astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
d
} else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
last_private: LastMod(AllPublic),
depth: path.segments.len()
}
} else {
tcx.sess.span_bug(expr.span,
&format!("unbound path {}", expr.repr(tcx))[])
};
let defn = lookup_def(fcx, expr.span, id);
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
let mut path = qpath.trait_ref.path.clone();
path.segments.push(qpath.item_path.clone());
instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
defn, expr.span, expr.id);
let mut def = path_res.base_def;
if path_res.depth == 0 {
let (scheme, predicates) =
type_scheme_and_predicates_for_def(fcx, expr.span, def);
instantiate_path(fcx, &path.segments,
scheme, &predicates,
opt_self_ty, def, expr.span, id);
} else {
let ty_segments = path.segments.init();
let base_ty_end = path.segments.len() - path_res.depth;
let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
PathParamMode::Optional,
&mut def,
opt_self_ty,
&ty_segments[..base_ty_end],
&ty_segments[base_ty_end..]);
let method_segment = path.segments.last().unwrap();
let method_name = method_segment.identifier.name;
match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
Ok((def, lp)) => {
// Write back the new resolution.
tcx.def_map.borrow_mut().insert(id, def::PathResolution {
base_def: def,
last_private: path_res.last_private.or(lp),
depth: 0
});
let (scheme, predicates) =
type_scheme_and_predicates_for_def(fcx, expr.span, def);
instantiate_path(fcx, slice::ref_slice(method_segment),
scheme, &predicates,
Some(ty), def, expr.span, id);
}
Err(error) => {
method::report_error(fcx, expr.span, ty,
method_name, None, error);
fcx.write_error(id);
}
}
}
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
@ -3855,14 +3884,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::ExprStruct(ref path, ref fields, ref base_expr) => {
// Resolve the path.
let def = tcx.def_map.borrow().get(&id).cloned();
let def = lookup_full_def(tcx, path.span, id);
let struct_id = match def {
Some(def::DefVariant(enum_id, variant_id, true)) => {
def::DefVariant(enum_id, variant_id, true) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
variant_id, &fields[..]);
enum_id
}
Some(def::DefaultImpl(def_id)) => {
def::DefTrait(def_id) => {
span_err!(tcx.sess, path.span, E0159,
"use of trait `{}` as a struct constructor",
pprust::path_to_string(path));
@ -3872,7 +3901,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
base_expr);
def_id
},
Some(def) => {
def => {
// Verify that this was actually a struct.
let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
match typ.ty.sty {
@ -3897,10 +3926,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
def.def_id()
}
_ => {
tcx.sess.span_bug(path.span,
"structure constructor wasn't resolved")
}
};
// Turn the path into a type and verify that that type unifies with
@ -4614,10 +4639,6 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
check_instantiable(ccx.tcx, sp, id);
}
pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
lookup_def_ccx(fcx.ccx, sp, id)
}
// Returns the type parameter count and the type for the given definition.
fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
sp: Span,
@ -4629,22 +4650,20 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
(ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
ty::GenericPredicates::empty())
}
def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
def::DefFn(id, _) | def::DefMethod(id, _) |
def::DefStatic(id, _) | def::DefVariant(_, id, _) |
def::DefStruct(id) | def::DefConst(id) => {
(ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
}
def::DefaultImpl(_) |
def::DefTrait(_) |
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefPrimTy(_) |
def::DefTyParam(..) |
def::DefMod(..) |
def::DefForeignMod(..) |
def::DefUse(..) |
def::DefRegion(..) |
def::DefTyParamBinder(..) |
def::DefLabel(..) |
def::DefSelfTy(..) => {
fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
@ -4655,15 +4674,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
path: &ast::Path,
segments: &[ast::PathSegment],
type_scheme: TypeScheme<'tcx>,
type_predicates: &ty::GenericPredicates<'tcx>,
opt_self_ty: Option<Ty<'tcx>>,
def: def::Def,
span: Span,
node_id: ast::NodeId) {
debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
path.repr(fcx.tcx()),
debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
segments,
def.repr(fcx.tcx()),
node_id,
type_scheme.repr(fcx.tcx()));
@ -4727,23 +4746,23 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
//
// The first step then is to categorize the segments appropriately.
assert!(path.segments.len() >= 1);
assert!(segments.len() >= 1);
let mut ufcs_method = None;
let mut segment_spaces: Vec<_>;
match def {
// Case 1 and 1b. Reference to a *type* or *enum variant*.
def::DefSelfTy(..) |
def::DefStruct(..) |
def::DefVariant(..) |
def::DefTyParamBinder(..) |
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefaultImpl(..) |
def::DefTrait(..) |
def::DefPrimTy(..) |
def::DefTyParam(..) => {
// Everything but the final segment should have no
// parameters at all.
segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
segment_spaces = repeat(None).take(segments.len() - 1).collect();
segment_spaces.push(Some(subst::TypeSpace));
}
@ -4751,25 +4770,29 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def::DefFn(..) |
def::DefConst(..) |
def::DefStatic(..) => {
segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
segment_spaces = repeat(None).take(segments.len() - 1).collect();
segment_spaces.push(Some(subst::FnSpace));
}
// Case 3. Reference to a method.
def::DefStaticMethod(_, providence) |
def::DefMethod(_, _, providence) => {
assert!(path.segments.len() >= 2);
match providence {
def::DefMethod(_, provenance) => {
match provenance {
def::FromTrait(trait_did) => {
callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
}
def::FromImpl(_) => {}
}
segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
segment_spaces.push(Some(subst::TypeSpace));
segment_spaces.push(Some(subst::FnSpace));
if segments.len() >= 2 {
segment_spaces = repeat(None).take(segments.len() - 2).collect();
segment_spaces.push(Some(subst::TypeSpace));
segment_spaces.push(Some(subst::FnSpace));
} else {
// `<T>::method` will end up here, and so can `T::method`.
let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
segment_spaces = vec![Some(subst::FnSpace)];
ufcs_method = Some((provenance, self_ty));
}
}
// Other cases. Various nonsense that really shouldn't show up
@ -4782,10 +4805,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def::DefRegion(..) |
def::DefLabel(..) |
def::DefUpvar(..) => {
segment_spaces = repeat(None).take(path.segments.len()).collect();
segment_spaces = repeat(None).take(segments.len()).collect();
}
}
assert_eq!(segment_spaces.len(), path.segments.len());
assert_eq!(segment_spaces.len(), segments.len());
// In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
// `opt_self_ty` can also be Some for `Foo::method`, where Foo's
// type parameters are not mandatory.
let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
debug!("segment_spaces={:?}", segment_spaces);
@ -4799,16 +4827,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// provided (if any) into their appropriate spaces. We'll also report
// errors if type parameters are provided in an inappropriate place.
let mut substs = Substs::empty();
for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
match *opt_space {
None => {
report_error_if_segment_contains_type_parameters(fcx, segment);
check_path_args(fcx.tcx(), slice::ref_slice(segment),
NO_TPS | NO_REGIONS);
}
Some(space) => {
push_explicit_parameters_from_segment_to_substs(fcx,
space,
path.span,
span,
type_defs,
region_defs,
segment,
@ -4817,9 +4846,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
if let Some(self_ty) = opt_self_ty {
// `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
assert_eq!(type_defs.len(subst::SelfSpace), 1);
substs.types.push(subst::SelfSpace, self_ty);
if type_defs.len(subst::SelfSpace) == 1 {
substs.types.push(subst::SelfSpace, self_ty);
}
}
// Now we have to compare the types that the user *actually*
@ -4829,7 +4858,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// to add defaults. If the user provided *too many* types, that's
// a problem.
for &space in &ParamSpace::all() {
adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
adjust_type_parameters(fcx, span, space, type_defs,
require_type_space, &mut substs);
assert_eq!(substs.types.len(space), type_defs.len(space));
adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
@ -4852,27 +4882,32 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// the referenced item.
let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
// In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
// is inherent, there is no `Self` parameter, instead, the impl needs
// type parameters, which we can infer by unifying the provided `Self`
// with the substituted impl type.
let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
assert_eq!(substs.types.len(subst::TypeSpace),
impl_scheme.generics.types.len(subst::TypeSpace));
assert_eq!(substs.regions().len(subst::TypeSpace),
impl_scheme.generics.regions.len(subst::TypeSpace));
let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
fcx.tcx().sess.span_bug(span,
&format!(
"instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
self_ty.repr(fcx.tcx()),
impl_ty.repr(fcx.tcx())));
}
}
fcx.write_ty(node_id, ty_substituted);
fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
return;
fn report_error_if_segment_contains_type_parameters(
fcx: &FnCtxt,
segment: &ast::PathSegment)
{
for typ in &segment.parameters.types() {
span_err!(fcx.tcx().sess, typ.span, E0085,
"type parameters may not appear here");
break;
}
for lifetime in &segment.parameters.lifetimes() {
span_err!(fcx.tcx().sess, lifetime.span, E0086,
"lifetime parameters may not appear here");
break;
}
}
/// Finds the parameters that the user provided and adds them to `substs`. If too many
/// parameters are provided, then reports an error and clears the output vector.
///
@ -5007,6 +5042,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
space: ParamSpace,
defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
require_type_space: bool,
substs: &mut Substs<'tcx>)
{
let provided_len = substs.types.len(space);
@ -5029,9 +5065,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Nothing specified at all: supply inference variables for
// everything.
if provided_len == 0 {
substs.types.replace(space,
fcx.infcx().next_ty_vars(desired.len()));
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
return;
}
@ -5153,18 +5188,15 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
_ => false
}
})) ||
// Second: is there a labeled break with label
// <id> nested anywhere inside the loop?
// Second: is there a labeled break with label
// <id> nested anywhere inside the loop?
(block_query(b, |e| {
match e.node {
ast::ExprBreak(Some(_)) => {
match cx.def_map.borrow().get(&e.id) {
Some(&def::DefLabel(loop_id)) if id == loop_id => true,
_ => false,
}
}
_ => false
}}))
if let ast::ExprBreak(Some(_)) = e.node {
lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
} else {
false
}
}))
}
pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,

View File

@ -81,8 +81,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
self.check_impl(item);
}
ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}

View File

@ -28,8 +28,8 @@ struct ImplsChecker<'cx, 'tcx:'cx> {
impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
ast::ItemImpl(_, _, _, Some(_), _, _) => {
let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id);
if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
match trait_ref.self_ty().sty {
ty::ty_struct(..) | ty::ty_enum(..) => {}

View File

@ -106,19 +106,9 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
//debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
match item.node {
ItemImpl(_, _, _, ref opt_trait, _, _) => {
match opt_trait.clone() {
Some(opt_trait) => {
self.cc.check_implementation(item, &[opt_trait]);
}
None => self.cc.check_implementation(item, &[])
}
}
_ => {
// Nothing to do.
}
};
if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
self.cc.check_implementation(item, opt_trait.as_ref())
}
visit::walk_item(self, item);
}
@ -155,9 +145,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
self.check_implementations_of_copy();
}
fn check_implementation(&self,
item: &Item,
associated_traits: &[TraitRef]) {
fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
let tcx = self.crate_context.tcx;
let impl_did = local_def(item.id);
let self_type = ty::lookup_item_type(tcx, impl_did);
@ -167,9 +155,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
let impl_items = self.create_impl_from_item(item);
for associated_trait in associated_traits {
let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx,
associated_trait.ref_id);
if opt_trait.is_some() {
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
debug!("(checking implementation) adding impl for trait '{}', item '{}'",
trait_ref.repr(self.crate_context.tcx),
token::get_ident(item.ident));
@ -191,7 +178,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
Some(base_type_def_id) => {
// FIXME: Gather up default methods?
if associated_traits.len() == 0 {
if opt_trait.is_none() {
self.add_inherent_impl(base_type_def_id, impl_did);
}
}
@ -289,7 +276,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
// Converts an implementation in the AST to a vector of items.
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => {
let mut items: Vec<ImplOrTraitItemId> =
ast_items.iter()
.map(|ast_item| {
@ -304,13 +291,12 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
}).collect();
if let Some(ref trait_ref) = *trait_refs {
let ty_trait_ref = ty::node_id_to_trait_ref(
self.crate_context.tcx,
trait_ref.ref_id);
if opt_trait.is_some() {
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
item.id);
self.instantiate_default_methods(local_def(item.id),
&*ty_trait_ref,
&*trait_ref,
&mut items);
}

View File

@ -16,7 +16,6 @@ use middle::ty;
use syntax::ast::{Item, ItemImpl};
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::visit;
use util::ppaux::{Repr, UserString};
@ -30,9 +29,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
}
impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
fn check_def_id(&self, span: Span, def_id: ast::DefId) {
fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) {
if def_id.krate != ast::LOCAL_CRATE {
span_err!(self.tcx.sess, span, E0116,
span_err!(self.tcx.sess, item.span, E0116,
"cannot associate methods with a type outside the \
crate the type is defined in; define and implement \
a trait or new type instead");
@ -41,7 +40,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
}
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
fn visit_item(&mut self, item: &ast::Item) {
let def_id = ast_util::local_def(item.id);
match item.node {
ast::ItemImpl(_, _, _, None, _, _) => {
@ -52,15 +51,13 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
match self_ty.sty {
ty::ty_enum(def_id, _) |
ty::ty_struct(def_id, _) => {
self.check_def_id(item.span, def_id);
self.check_def_id(item, def_id);
}
ty::ty_trait(ref data) => {
self.check_def_id(item.span, data.principal_def_id());
self.check_def_id(item, data.principal_def_id());
}
ty::ty_uniq(..) => {
self.check_def_id(item.span,
self.tcx.lang_items.owned_box()
.unwrap());
self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
}
_ => {
span_err!(self.tcx.sess, item.span, E0118,
@ -96,10 +93,10 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
}
}
}
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
ast::ItemDefaultImpl(..) => {
// "Trait" impl
debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx));
let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id);
let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
if trait_ref.def_id.krate != ast::LOCAL_CRATE {
span_err!(self.tcx.sess, item.span, E0318,
"cannot create default implementations for traits outside the \

View File

@ -649,8 +649,12 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
&enum_definition.variants);
},
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope,
ast_trait_ref, None, None);
let trait_ref = astconv::instantiate_trait_ref(ccx,
&ExplicitRscope,
ast_trait_ref,
Some(it.id),
None,
None);
ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id))
}
@ -741,6 +745,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
astconv::instantiate_trait_ref(ccx,
&ExplicitRscope,
trait_ref,
Some(it.id),
Some(selfty),
None);
}
@ -1682,20 +1687,15 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
index: u32)
-> bool
{
match ast_ty.node {
ast::TyPath(_, id) => {
match ccx.tcx.def_map.borrow()[id] {
def::DefTyParam(s, i, _, _) => {
space == s && index == i
}
_ => {
false
}
}
}
_ => {
if let ast::TyPath(None, _) = ast_ty.node {
let path_res = ccx.tcx.def_map.borrow()[ast_ty.id];
if let def::DefTyParam(s, i, _, _) = path_res.base_def {
path_res.depth == 0 && space == s && index == i
} else {
false
}
} else {
false
}
}
}

View File

@ -80,6 +80,7 @@ register_diagnostics! {
E0120,
E0121,
E0122,
E0123,
E0124,
E0127,
E0128,

View File

@ -163,20 +163,16 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
tcx.item_substs.borrow_mut().insert(node_id, item_substs);
}
}
fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
match tcx.def_map.borrow().get(&id) {
Some(x) => x.clone(),
_ => {
Some(x) => x.full_def(),
None => {
span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
}
}
}
fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
-> def::Def {
lookup_def_tcx(ccx.tcx, sp, id)
}
fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
t1_is_expected: bool,

View File

@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Ident>)
None => return None,
};
let def = match tcx.def_map.borrow().get(&id) {
Some(def) => *def,
Some(d) => d.full_def(),
None => return None,
};
let did = def.def_id();
@ -69,7 +69,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
let mut ret = Vec::new();
let did = def.def_id();
let inner = match def {
def::DefaultImpl(did) => {
def::DefTrait(did) => {
record_extern_fqn(cx, did, clean::TypeTrait);
clean::TraitItem(build_external_trait(cx, tcx, did))
}

View File

@ -1344,8 +1344,6 @@ pub enum Type {
typarams: Option<Vec<TyParamBound>>,
did: ast::DefId,
},
// I have no idea how to usefully use this.
TyParamBinder(ast::NodeId),
/// For parameterized types, so the consumer of the JSON don't go
/// looking for types which don't exist anywhere.
Generic(String),
@ -1496,8 +1494,17 @@ impl Clean<Type> for ast::Ty {
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
e.span.to_src(cx)),
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(ref p, id) => {
resolve_type(cx, p.clean(cx), id)
TyPath(None, ref p) => {
resolve_type(cx, p.clean(cx), self.id)
}
TyPath(Some(ref qself), ref p) => {
let mut trait_path = p.clone();
trait_path.segments.pop();
Type::QPath {
name: p.segments.last().unwrap().identifier.clean(cx),
self_type: box qself.ty.clean(cx),
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
}
}
TyObjectSum(ref lhs, ref bounds) => {
let lhs_ty = lhs.clean(cx);
@ -1512,7 +1519,6 @@ impl Clean<Type> for ast::Ty {
}
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyParen(ref ty) => ty.clean(cx),
TyQPath(ref qp) => qp.clean(cx),
TyPolyTraitRef(ref bounds) => {
PolyTraitRef(bounds.clean(cx))
},
@ -1624,16 +1630,6 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
}
}
impl Clean<Type> for ast::QPath {
fn clean(&self, cx: &DocContext) -> Type {
Type::QPath {
name: self.item_path.identifier.clean(cx),
self_type: box self.self_type.clean(cx),
trait_: box self.trait_ref.clean(cx)
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum StructField {
HiddenStructField, // inserted later by strip passes
@ -2392,7 +2388,7 @@ fn resolve_type(cx: &DocContext,
};
debug!("searching for {} in defmap", id);
let def = match tcx.def_map.borrow().get(&id) {
Some(&k) => k,
Some(k) => k.full_def(),
None => panic!("unresolved id not in defmap")
};
@ -2418,7 +2414,6 @@ fn resolve_type(cx: &DocContext,
ast::TyFloat(ast::TyF64) => return Primitive(F64),
},
def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
def::DefTyParamBinder(i) => return TyParamBinder(i),
_ => {}
};
let did = register_def(&*cx, def);
@ -2430,7 +2425,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
def::DefFn(i, _) => (i, TypeFunction),
def::DefTy(i, false) => (i, TypeTypedef),
def::DefTy(i, true) => (i, TypeEnum),
def::DefaultImpl(i) => (i, TypeTrait),
def::DefTrait(i) => (i, TypeTrait),
def::DefStruct(i) => (i, TypeStruct),
def::DefMod(i) => (i, TypeModule),
def::DefStatic(i, _) => (i, TypeStatic),
@ -2459,7 +2454,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
cx.tcx_opt().and_then(|tcx| {
tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def))
tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
})
}

View File

@ -454,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter,
impl fmt::Display for clean::Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
clean::TyParamBinder(id) => {
f.write_str(&cache().typarams[ast_util::local_def(id)])
}
clean::Generic(ref name) => {
f.write_str(name)
}

View File

@ -196,7 +196,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
Some(tcx) => tcx,
None => return false
};
let def = (*tcx.def_map.borrow())[id].def_id();
let def = tcx.def_map.borrow()[id].def_id();
if !ast_util::is_local(def) { return false }
let analysis = match self.analysis {
Some(analysis) => analysis, None => return false

View File

@ -753,11 +753,10 @@ pub enum Expr_ {
ExprIndex(P<Expr>, P<Expr>),
ExprRange(Option<P<Expr>>, Option<P<Expr>>),
/// Variable reference, possibly containing `::` and/or
/// type parameters, e.g. foo::bar::<baz>
ExprPath(Path),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
ExprQPath(P<QPath>),
/// Variable reference, possibly containing `::` and/or type
/// parameters, e.g. foo::bar::<baz>. Optionally "qualified",
/// e.g. `<Vec<T> as SomeTrait>::SomeType`.
ExprPath(Option<QSelf>, Path),
ExprAddrOf(Mutability, P<Expr>),
ExprBreak(Option<Ident>),
@ -778,16 +777,22 @@ pub enum Expr_ {
ExprParen(P<Expr>)
}
/// A "qualified path":
/// The explicit Self type in a "qualified path". The actual
/// path, including the trait and the associated item, is stored
/// sepparately. `position` represents the index of the associated
/// item qualified with this Self type.
///
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
/// self_type trait_name item_path
/// <Vec<T> as a::b::Trait>::AssociatedItem
/// ^~~~~ ~~~~~~~~~~~~~~^
/// ty position = 3
///
/// <Vec<T>>::AssociatedItem
/// ^~~~~ ^
/// ty position = 0
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct QPath {
pub self_type: P<Ty>,
pub trait_ref: P<TraitRef>,
pub item_path: PathSegment,
pub struct QSelf {
pub ty: P<Ty>,
pub position: usize
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@ -1254,16 +1259,15 @@ pub enum Ty_ {
TyBareFn(P<BareFnTy>),
/// A tuple (`(A, B, C, D,...)`)
TyTup(Vec<P<Ty>> ),
/// A path (`module::module::...::Type`) or primitive
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
///
/// Type parameters are stored in the Path itself
TyPath(Path, NodeId),
TyPath(Option<QSelf>, Path),
/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
TyQPath(P<QPath>),
/// No-op; kept solely so that we can pretty-print faithfully
TyParen(P<Ty>),
/// Unused for now

View File

@ -134,7 +134,7 @@ pub fn unop_to_string(op: UnOp) -> &'static str {
}
pub fn is_path(e: P<Expr>) -> bool {
return match e.node { ExprPath(_) => true, _ => false };
match e.node { ExprPath(..) => true, _ => false }
}
/// Get a string representation of a signed int type, with its value.
@ -488,9 +488,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
fn visit_ty(&mut self, typ: &Ty) {
self.operation.visit_id(typ.id);
if let TyPath(_, id) = typ.node {
self.operation.visit_id(id);
}
visit::walk_ty(self, typ)
}
@ -564,13 +561,18 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
visit::walk_trait_item(self, tm);
}
fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
self.operation.visit_id(lifetime.id);
}
fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) {
fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
self.visit_lifetime_ref(&def.lifetime);
}
fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
self.operation.visit_id(trait_ref.ref_id);
visit::walk_trait_ref(self, trait_ref);
}
}
pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,

View File

@ -41,16 +41,16 @@ pub trait AstBuilder {
-> ast::Path;
fn qpath(&self, self_type: P<ast::Ty>,
trait_ref: P<ast::TraitRef>,
ident: ast::Ident )
-> P<ast::QPath>;
trait_path: ast::Path,
ident: ast::Ident)
-> (ast::QSelf, ast::Path);
fn qpath_all(&self, self_type: P<ast::Ty>,
trait_ref: P<ast::TraitRef>,
trait_path: ast::Path,
ident: ast::Ident,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
bindings: Vec<P<ast::TypeBinding>> )
-> P<ast::QPath>;
bindings: Vec<P<ast::TypeBinding>>)
-> (ast::QSelf, ast::Path);
// types
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
@ -114,7 +114,7 @@ pub trait AstBuilder {
// expressions
fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr>;
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
fn expr_self(&self, span: Span) -> P<ast::Expr>;
@ -346,40 +346,40 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
/// Constructs a qualified path.
///
/// Constructs a path like `<self_type as trait_ref>::ident`.
/// Constructs a path like `<self_type as trait_path>::ident`.
fn qpath(&self,
self_type: P<ast::Ty>,
trait_ref: P<ast::TraitRef>,
trait_path: ast::Path,
ident: ast::Ident)
-> P<ast::QPath> {
self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
-> (ast::QSelf, ast::Path) {
self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
}
/// Constructs a qualified path.
///
/// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
/// Constructs a path like `<self_type as trait_path>::ident<'a, T, A=Bar>`.
fn qpath_all(&self,
self_type: P<ast::Ty>,
trait_ref: P<ast::TraitRef>,
trait_path: ast::Path,
ident: ast::Ident,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
bindings: Vec<P<ast::TypeBinding>> )
-> P<ast::QPath> {
let segment = ast::PathSegment {
bindings: Vec<P<ast::TypeBinding>>)
-> (ast::QSelf, ast::Path) {
let mut path = trait_path;
path.segments.push(ast::PathSegment {
identifier: ident,
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: OwnedSlice::from_vec(types),
bindings: OwnedSlice::from_vec(bindings),
})
};
});
P(ast::QPath {
self_type: self_type,
trait_ref: trait_ref,
item_path: segment,
})
(ast::QSelf {
ty: self_type,
position: path.segments.len() - 1
}, path)
}
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
@ -398,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID))
self.ty(path.span, ast::TyPath(None, path))
}
fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> {
@ -603,12 +603,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
self.expr(path.span, ast::ExprPath(path))
self.expr(path.span, ast::ExprPath(None, path))
}
/// Constructs a QPath expression.
fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
self.expr(span, ast::ExprQPath(qpath))
fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr> {
self.expr(span, ast::ExprPath(Some(qself), path))
}
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {

View File

@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]
let e = P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(
node: ast::ExprPath(None,
ast::Path {
span: sp,
global: false,

View File

@ -70,7 +70,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec!(borrowed_self()),
ret_ty: Literal(path!(bool)),
ret_ty: Literal(path_local!(bool)),
attributes: attrs,
combine_substructure: combine_substructure(box |a, b, c| {
$f(a, b, c)

View File

@ -36,7 +36,7 @@ pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt,
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec!(borrowed_self()),
ret_ty: Literal(path!(bool)),
ret_ty: Literal(path_local!(bool)),
attributes: attrs,
combine_substructure: combine_substructure(box |cx, span, substr| {
cs_op($op, $equal, cx, span, substr)

View File

@ -30,6 +30,12 @@ macro_rules! path {
)
}
macro_rules! path_local {
($x:ident) => (
::ext::deriving::generic::ty::Path::new_local(stringify!($x))
)
}
macro_rules! pathvec_std {
($cx:expr, $first:ident :: $($rest:ident)::+) => (
if $cx.use_std {

View File

@ -38,7 +38,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
name: "from_i64",
generics: LifetimeBounds::empty(),
explicit_self: None,
args: vec!(Literal(path!(i64))),
args: vec!(Literal(path_local!(i64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
vec!(box Self_),
@ -53,7 +53,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
name: "from_u64",
generics: LifetimeBounds::empty(),
explicit_self: None,
args: vec!(Literal(path!(u64))),
args: vec!(Literal(path_local!(u64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
vec!(box Self_),

View File

@ -41,7 +41,7 @@ pub fn expand_type(t: P<ast::Ty>,
debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty);
let t = match (t.node.clone(), impl_ty) {
// Expand uses of `Self` in impls to the concrete type.
(ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => {
(ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => {
let path_as_ident = path_to_ident(path);
// Note unhygenic comparison here. I think this is correct, since
// even though `Self` is almost just a type parameter, the treatment
@ -1594,13 +1594,10 @@ mod test {
impl<'v> Visitor<'v> for PathExprFinderContext {
fn visit_expr(&mut self, expr: &ast::Expr) {
match expr.node {
ast::ExprPath(ref p) => {
self.path_accumulator.push(p.clone());
// not calling visit_path, but it should be fine.
}
_ => visit::walk_expr(self, expr)
if let ast::ExprPath(None, ref p) = expr.node {
self.path_accumulator.push(p.clone());
}
visit::walk_expr(self, expr);
}
}

View File

@ -549,7 +549,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
fn visit_ty(&mut self, t: &ast::Ty) {
match t.node {
ast::TyPath(ref p, _) => {
ast::TyPath(None, ref p) => {
match &*p.segments {
[ast::PathSegment { identifier, .. }] => {

View File

@ -146,10 +146,6 @@ pub trait Folder : Sized {
noop_fold_ty(t, self)
}
fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
noop_fold_qpath(t, self)
}
fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
noop_fold_ty_binding(t, self)
}
@ -428,17 +424,19 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
}
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
TyParen(ty) => TyParen(fld.fold_ty(ty)),
TyPath(path, id) => {
let id = fld.new_id(id);
TyPath(fld.fold_path(path), id)
TyPath(qself, path) => {
let qself = qself.map(|QSelf { ty, position }| {
QSelf {
ty: fld.fold_ty(ty),
position: position
}
});
TyPath(qself, fld.fold_path(path))
}
TyObjectSum(ty, bounds) => {
TyObjectSum(fld.fold_ty(ty),
fld.fold_bounds(bounds))
}
TyQPath(qpath) => {
TyQPath(fld.fold_qpath(qpath))
}
TyFixedLengthVec(ty, e) => {
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
}
@ -453,19 +451,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
})
}
pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
qpath.map(|qpath| {
QPath {
self_type: fld.fold_ty(qpath.self_type),
trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
item_path: PathSegment {
identifier: fld.fold_ident(qpath.item_path.identifier),
parameters: fld.fold_path_parameters(qpath.item_path.parameters),
}
}
})
}
pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
fld: &mut T) -> ForeignMod {
ForeignMod {
@ -1364,8 +1349,15 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
ExprRange(e1.map(|x| folder.fold_expr(x)),
e2.map(|x| folder.fold_expr(x)))
}
ExprPath(pth) => ExprPath(folder.fold_path(pth)),
ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
ExprPath(qself, path) => {
let qself = qself.map(|QSelf { ty, position }| {
QSelf {
ty: folder.fold_ty(ty),
position: position
}
});
ExprPath(qself, folder.fold_path(path))
}
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),

View File

@ -774,7 +774,7 @@ mod test {
assert!(string_to_expr("a".to_string()) ==
P(ast::Expr{
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
node: ast::ExprPath(None, ast::Path {
span: sp(0, 1),
global: false,
segments: vec!(
@ -792,7 +792,7 @@ mod test {
assert!(string_to_expr("::a::b".to_string()) ==
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
node: ast::ExprPath(None, ast::Path {
span: sp(0, 6),
global: true,
segments: vec!(
@ -974,7 +974,7 @@ mod test {
id: ast::DUMMY_NODE_ID,
node:ast::ExprRet(Some(P(ast::Expr{
id: ast::DUMMY_NODE_ID,
node:ast::ExprPath(ast::Path{
node:ast::ExprPath(None, ast::Path{
span: sp(7, 8),
global: false,
segments: vec!(
@ -995,7 +995,7 @@ mod test {
P(Spanned{
node: ast::StmtExpr(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
node: ast::ExprPath(None, ast::Path {
span:sp(0,1),
global:false,
segments: vec!(
@ -1041,7 +1041,7 @@ mod test {
node: ast::ItemFn(P(ast::FnDecl {
inputs: vec!(ast::Arg{
ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::TyPath(ast::Path{
node: ast::TyPath(None, ast::Path{
span:sp(10,13),
global:false,
segments: vec!(
@ -1051,7 +1051,7 @@ mod test {
parameters: ast::PathParameters::none(),
}
),
}, ast::DUMMY_NODE_ID),
}),
span:sp(10,13)
}),
pat: P(ast::Pat {
@ -1084,7 +1084,7 @@ mod test {
stmts: vec!(P(Spanned{
node: ast::StmtSemi(P(ast::Expr{
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(
node: ast::ExprPath(None,
ast::Path{
span:sp(17,18),
global:false,

View File

@ -25,7 +25,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast};
use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath};
use ast::{ExprMethodCall, ExprParen, ExprPath};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
@ -43,7 +43,7 @@ use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot};
use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
use ast::{PolyTraitRef};
use ast::{QPath, RequiredMethod};
use ast::{QSelf, RequiredMethod};
use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub, StrStyle};
@ -53,7 +53,7 @@ use ast::{TtDelimited, TtSequence, TtToken};
use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
use ast::{TyFixedLengthVec, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
use ast::{TypeImplItem, TypeTraitItem, Typedef,};
use ast::{UnnamedField, UnsafeBlock};
@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr {
_ => unreachable!()
};
let span = $p.span;
Some($p.mk_expr(span.lo, span.hi, ExprPath(pt)))
Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt)))
}
token::Interpolated(token::NtBlock(_)) => {
// FIXME: The following avoids an issue with lexical borrowck scopes,
@ -1076,8 +1076,7 @@ impl<'a> Parser<'a> {
}
pub fn parse_ty_path(&mut self) -> Ty_ {
let path = self.parse_path(LifetimeAndTypesWithoutColons);
TyPath(path, ast::DUMMY_NODE_ID)
TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons))
}
/// parse a TyBareFn type:
@ -1525,19 +1524,36 @@ impl<'a> Parser<'a> {
} else if self.eat_lt() {
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
let trait_ref = self.parse_trait_ref();
let mut path = if self.eat_keyword(keywords::As) {
self.parse_path(LifetimeAndTypesWithoutColons)
} else {
ast::Path {
span: self.span,
global: false,
segments: vec![]
}
};
let qself = QSelf {
ty: self_type,
position: path.segments.len()
};
self.expect(&token::Gt);
self.expect(&token::ModSep);
let item_name = self.parse_ident();
TyQPath(P(QPath {
self_type: self_type,
trait_ref: P(trait_ref),
item_path: ast::PathSegment {
identifier: item_name,
parameters: ast::PathParameters::none()
}
}))
path.segments.push(ast::PathSegment {
identifier: self.parse_ident(),
parameters: ast::PathParameters::none()
});
if path.segments.len() == 1 {
path.span.lo = self.last_span.lo;
}
path.span.hi = self.last_span.hi;
TyPath(Some(qself), path)
} else if self.check(&token::ModSep) ||
self.token.is_ident() ||
self.token.is_path() {
@ -2178,7 +2194,7 @@ impl<'a> Parser<'a> {
}, token::Plain) => {
self.bump();
let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
ex = ExprPath(path);
ex = ExprPath(None, path);
hi = self.last_span.hi;
}
token::OpenDelim(token::Bracket) => {
@ -2220,10 +2236,22 @@ impl<'a> Parser<'a> {
if self.eat_lt() {
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
let trait_ref = self.parse_trait_ref();
let mut path = if self.eat_keyword(keywords::As) {
self.parse_path(LifetimeAndTypesWithoutColons)
} else {
ast::Path {
span: self.span,
global: false,
segments: vec![]
}
};
let qself = QSelf {
ty: self_type,
position: path.segments.len()
};
self.expect(&token::Gt);
self.expect(&token::ModSep);
let item_name = self.parse_ident();
let parameters = if self.eat(&token::ModSep) {
self.expect_lt();
@ -2238,15 +2266,18 @@ impl<'a> Parser<'a> {
} else {
ast::PathParameters::none()
};
path.segments.push(ast::PathSegment {
identifier: item_name,
parameters: parameters
});
if path.segments.len() == 1 {
path.span.lo = self.last_span.lo;
}
path.span.hi = self.last_span.hi;
let hi = self.span.hi;
return self.mk_expr(lo, hi, ExprQPath(P(QPath {
self_type: self_type,
trait_ref: P(trait_ref),
item_path: ast::PathSegment {
identifier: item_name,
parameters: parameters
}
})));
return self.mk_expr(lo, hi, ExprPath(Some(qself), path));
}
if self.eat_keyword(keywords::Move) {
return self.parse_lambda_expr(CaptureByValue);
@ -2386,7 +2417,7 @@ impl<'a> Parser<'a> {
}
hi = pth.span.hi;
ex = ExprPath(pth);
ex = ExprPath(None, pth);
} else {
// other literal expression
let lit = self.parse_lit();
@ -3428,7 +3459,7 @@ impl<'a> Parser<'a> {
let end = if self.token.is_ident() || self.token.is_path() {
let path = self.parse_path(LifetimeAndTypesWithColons);
let hi = self.span.hi;
self.mk_expr(lo, hi, ExprPath(path))
self.mk_expr(lo, hi, ExprPath(None, path))
} else {
self.parse_literal_maybe_minus()
};
@ -4815,10 +4846,10 @@ impl<'a> Parser<'a> {
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
// New-style trait. Reinterpret the type as a trait.
match ty.node {
TyPath(ref path, node_id) => {
TyPath(None, ref path) => {
Some(TraitRef {
path: (*path).clone(),
ref_id: node_id,
ref_id: ty.id,
})
}
_ => {

View File

@ -373,7 +373,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
}
pub fn path_to_string(p: &ast::Path) -> String {
$to_string(|s| s.print_path(p, false))
$to_string(|s| s.print_path(p, false, 0))
}
pub fn ident_to_string(id: &ast::Ident) -> String {
@ -729,8 +729,11 @@ impl<'a> State<'a> {
&generics,
None));
}
ast::TyPath(ref path, _) => {
try!(self.print_path(path, false));
ast::TyPath(None, ref path) => {
try!(self.print_path(path, false, 0));
}
ast::TyPath(Some(ref qself), ref path) => {
try!(self.print_qpath(path, qself, false))
}
ast::TyObjectSum(ref ty, ref bounds) => {
try!(self.print_type(&**ty));
@ -739,9 +742,6 @@ impl<'a> State<'a> {
ast::TyPolyTraitRef(ref bounds) => {
try!(self.print_bounds("", &bounds[..]));
}
ast::TyQPath(ref qpath) => {
try!(self.print_qpath(&**qpath, false))
}
ast::TyFixedLengthVec(ref ty, ref v) => {
try!(word(&mut self.s, "["));
try!(self.print_type(&**ty));
@ -1018,7 +1018,7 @@ impl<'a> State<'a> {
ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
..}) => {
try!(self.print_visibility(item.vis));
try!(self.print_path(pth, false));
try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "! "));
try!(self.print_ident(item.ident));
try!(self.cbox(indent_unit));
@ -1033,7 +1033,7 @@ impl<'a> State<'a> {
}
fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
self.print_path(&t.path, false)
self.print_path(&t.path, false, 0)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> {
@ -1297,7 +1297,7 @@ impl<'a> State<'a> {
ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
..}) => {
// code copied from ItemMac:
try!(self.print_path(pth, false));
try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "! "));
try!(self.cbox(indent_unit));
try!(self.popen());
@ -1514,7 +1514,7 @@ impl<'a> State<'a> {
match m.node {
// I think it's reasonable to hide the ctxt here:
ast::MacInvocTT(ref pth, ref tts, _) => {
try!(self.print_path(pth, false));
try!(self.print_path(pth, false, 0));
try!(word(&mut self.s, "!"));
match delim {
token::Paren => try!(self.popen()),
@ -1584,7 +1584,7 @@ impl<'a> State<'a> {
path: &ast::Path,
fields: &[ast::Field],
wth: &Option<P<ast::Expr>>) -> IoResult<()> {
try!(self.print_path(path, true));
try!(self.print_path(path, true, 0));
if !(fields.is_empty() && wth.is_none()) {
try!(word(&mut self.s, "{"));
try!(self.commasep_cmnt(
@ -1852,8 +1852,12 @@ impl<'a> State<'a> {
try!(self.print_expr(&**e));
}
}
ast::ExprPath(ref path) => try!(self.print_path(path, true)),
ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
ast::ExprPath(None, ref path) => {
try!(self.print_path(path, true, 0))
}
ast::ExprPath(Some(ref qself), ref path) => {
try!(self.print_qpath(path, qself, true))
}
ast::ExprBreak(opt_ident) => {
try!(word(&mut self.s, "break"));
try!(space(&mut self.s));
@ -2014,16 +2018,14 @@ impl<'a> State<'a> {
fn print_path(&mut self,
path: &ast::Path,
colons_before_params: bool)
colons_before_params: bool,
depth: usize)
-> IoResult<()>
{
try!(self.maybe_print_comment(path.span.lo));
if path.global {
try!(word(&mut self.s, "::"));
}
let mut first = true;
for segment in &path.segments {
let mut first = !path.global;
for segment in &path.segments[..path.segments.len()-depth] {
if first {
first = false
} else {
@ -2039,19 +2041,24 @@ impl<'a> State<'a> {
}
fn print_qpath(&mut self,
qpath: &ast::QPath,
path: &ast::Path,
qself: &ast::QSelf,
colons_before_params: bool)
-> IoResult<()>
{
try!(word(&mut self.s, "<"));
try!(self.print_type(&*qpath.self_type));
try!(space(&mut self.s));
try!(self.word_space("as"));
try!(self.print_trait_ref(&*qpath.trait_ref));
try!(self.print_type(&qself.ty));
if qself.position > 0 {
try!(space(&mut self.s));
try!(self.word_space("as"));
let depth = path.segments.len() - qself.position;
try!(self.print_path(&path, false, depth));
}
try!(word(&mut self.s, ">"));
try!(word(&mut self.s, "::"));
try!(self.print_ident(qpath.item_path.identifier));
self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
let item_segment = path.segments.last().unwrap();
try!(self.print_ident(item_segment.identifier));
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
fn print_path_parameters(&mut self,
@ -2156,7 +2163,7 @@ impl<'a> State<'a> {
}
}
ast::PatEnum(ref path, ref args_) => {
try!(self.print_path(path, true));
try!(self.print_path(path, true, 0));
match *args_ {
None => try!(word(&mut self.s, "(..)")),
Some(ref args) => {
@ -2170,7 +2177,7 @@ impl<'a> State<'a> {
}
}
ast::PatStruct(ref path, ref fields, etc) => {
try!(self.print_path(path, true));
try!(self.print_path(path, true, 0));
try!(self.nbsp());
try!(self.word_space("{"));
try!(self.commasep_cmnt(
@ -2555,7 +2562,7 @@ impl<'a> State<'a> {
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
try!(self.print_path(path, false));
try!(self.print_path(path, false, 0));
try!(space(&mut self.s));
try!(self.word_space("="));
try!(self.print_type(&**ty));
@ -2592,7 +2599,7 @@ impl<'a> State<'a> {
pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
match vp.node {
ast::ViewPathSimple(ident, ref path) => {
try!(self.print_path(path, false));
try!(self.print_path(path, false, 0));
// FIXME(#6993) can't compare identifiers directly here
if path.segments.last().unwrap().identifier.name !=
@ -2606,7 +2613,7 @@ impl<'a> State<'a> {
}
ast::ViewPathGlob(ref path) => {
try!(self.print_path(path, false));
try!(self.print_path(path, false, 0));
word(&mut self.s, "::*")
}
@ -2614,7 +2621,7 @@ impl<'a> State<'a> {
if path.segments.is_empty() {
try!(word(&mut self.s, "{"));
} else {
try!(self.print_path(path, false));
try!(self.print_path(path, false, 0));
try!(word(&mut self.s, "::{"));
}
try!(self.commasep(Inconsistent, &idents[..], |s, w| {

View File

@ -125,9 +125,6 @@ pub trait Visitor<'v> : Sized {
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
}
fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
walk_qpath(self, qpath_span, qpath)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
@ -399,16 +396,16 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
}
TyPath(ref path, id) => {
visitor.visit_path(path, id);
TyPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, typ.id);
}
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(&**ty);
walk_ty_param_bounds_helper(visitor, bounds);
}
TyQPath(ref qpath) => {
visitor.visit_qpath(typ.span, &**qpath);
}
TyFixedLengthVec(ref ty, ref expression) => {
visitor.visit_ty(&**ty);
visitor.visit_expr(&**expression)
@ -436,14 +433,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
}
}
pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
qpath_span: Span,
qpath: &'v QPath) {
visitor.visit_ty(&*qpath.self_type);
visitor.visit_trait_ref(&*qpath.trait_ref);
visitor.visit_path_segment(qpath_span, &qpath.item_path);
}
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
@ -869,12 +858,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
walk_expr_opt(visitor, start);
walk_expr_opt(visitor, end)
}
ExprPath(ref path) => {
ExprPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, expression.id)
}
ExprQPath(ref qpath) => {
visitor.visit_qpath(expression.span, &**qpath)
}
ExprBreak(_) | ExprAgain(_) => {}
ExprRet(ref optional_expression) => {
walk_expr_opt(visitor, optional_expression)

View File

@ -22,5 +22,8 @@ trait Grab {
//~^ ERROR ambiguous associated type
}
type X = std::ops::Deref::Target;
//~^ ERROR ambiguous associated type
fn main() {
}

View File

@ -43,7 +43,7 @@ fn foo<'a>() {
//~^ ERROR too many type parameters provided
let _ = S::<'a,isize>::new::<f64>(1, 1.0);
//~^ ERROR too many lifetime parameters provided
//~^ ERROR wrong number of lifetime parameters
let _: S2 = Trait::new::<isize,f64>(1, 1.0);
//~^ ERROR too many type parameters provided

View File

@ -24,7 +24,7 @@ extern "rust-intrinsic" {
// Unresolved bounds should still error.
fn align_of<T: NoSuchTrait>() -> usize;
//~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait`
//~^ ERROR use of undeclared trait name `NoSuchTrait`
}
fn main() {}

View File

@ -19,5 +19,5 @@ impl<A, B, C = (A, B)> Foo<A, B, C> {
fn main() {
Foo::<isize>::new();
//~^ ERROR too few type parameters provided
//~^ ERROR wrong number of type arguments
}

View File

@ -21,5 +21,5 @@ impl<T, A = Heap> Vec<T, A> {
fn main() {
Vec::<isize, Heap, bool>::new();
//~^ ERROR too many type parameters provided
//~^ ERROR wrong number of type arguments
}

View File

@ -36,9 +36,6 @@ fn main() {
import(); //~ ERROR: unresolved
foo::<A>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
foo::<C>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
foo::<D>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
}

View File

@ -11,7 +11,7 @@
struct Foo;
impl Foo {
fn orange(&self){}
fn orange(&self){} //~ ERROR error: duplicate definition of value `orange`
fn orange(&self){} //~ ERROR error: duplicate method in trait impl
}
fn main() {}

View File

@ -14,7 +14,8 @@ enum Bar<T> { What }
fn foo<T>() {
static a: Bar<T> = Bar::What;
//~^ ERROR: cannot use an outer type parameter in this context
//~^ ERROR cannot use an outer type parameter in this context
//~| ERROR use of undeclared type name `T`
}
fn main() {

View File

@ -17,9 +17,9 @@ mod a {
fn main() {
a::Foo::new();
//~^ ERROR: static method `new` is inaccessible
//~^ ERROR: method `new` is inaccessible
//~^^ NOTE: struct `Foo` is private
a::Bar::new();
//~^ ERROR: static method `new` is inaccessible
//~^ ERROR: method `new` is inaccessible
//~^^ NOTE: enum `Bar` is private
}

View File

@ -29,7 +29,7 @@ impl Foo for *const BarTy {
baz();
//~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
a;
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
//~^ ERROR: unresolved name `a`
}
}
@ -42,11 +42,11 @@ impl<'a> Foo for &'a BarTy {
y;
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
a;
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
//~^ ERROR: unresolved name `a`
bah;
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
b;
//~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
//~^ ERROR: unresolved name `b`
}
}
@ -59,11 +59,11 @@ impl<'a> Foo for &'a mut BarTy {
y;
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
a;
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
//~^ ERROR: unresolved name `a`
bah;
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
b;
//~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
//~^ ERROR: unresolved name `b`
}
}

View File

@ -15,18 +15,11 @@ trait From<Src> {
}
trait To {
// This is a typo, the return type should be `<Dst as From<Self>>::Output`
fn to<Dst: From<Self>>(
self
//~^ error: the trait `core::marker::Sized` is not implemented
) ->
fn to<Dst: From<Self>>(self) ->
<Dst as From<Self>>::Dst
//~^ error: the trait `core::marker::Sized` is not implemented
//~^ ERROR use of undeclared associated type `From::Dst`
{
From::from(
//~^ error: the trait `core::marker::Sized` is not implemented
self
)
From::from(self)
}
}

View File

@ -18,7 +18,7 @@ mod B {
use crate1::A::Foo;
fn bar(f: Foo) {
Foo::foo(&f);
//~^ ERROR: function `foo` is private
//~^ ERROR: method `foo` is private
}
}

View File

@ -36,7 +36,7 @@ impl Groom for cat {
shave(4);
//~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `purr`
}
}
@ -45,13 +45,13 @@ impl cat {
fn purr_louder() {
static_method();
//~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method`
//~^ ERROR: unresolved name `static_method`
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `purr`
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `purr`
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `purr`
}
}
@ -65,7 +65,7 @@ impl cat {
fn purr(&self) {
grow_older();
//~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older`
//~^ ERROR: unresolved name `grow_older`
shave();
//~^ ERROR: unresolved name `shave`
}
@ -79,7 +79,7 @@ impl cat {
whiskers = 4;
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
purr_louder();
//~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder`
//~^ ERROR: unresolved name `purr_louder`
}
}

View File

@ -11,7 +11,9 @@
fn main() {
let foo = 100;
static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant
static y: isize = foo + 1;
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `foo`
println!("{}", y);
}

View File

@ -13,7 +13,9 @@ fn main() {
#[derive(Debug)]
enum Stuff {
Bar = foo //~ ERROR attempt to use a non-constant value in a constant
Bar = foo
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `foo`
}
println!("{}", Stuff::Bar);

View File

@ -9,7 +9,9 @@
// except according to those terms.
fn f(x:isize) {
static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant
static child: isize = x + 1;
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `x`
}
fn main() {}

View File

@ -17,6 +17,7 @@ impl PTrait for P {
fn getChildOption(&self) -> Option<Box<P>> {
static childVal: Box<P> = self.child.get();
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `self`
panic!();
}
}

View File

@ -30,7 +30,5 @@ impl ToString_ for Point {
fn main() {
let p = Point::new(0.0, 0.0);
//~^ ERROR unresolved name `Point::new`
//~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
println!("{}", p.to_string());
}

View File

@ -17,7 +17,7 @@ impl Foo {
Foo { baz: 0 }.bar();
}
fn bar() { //~ ERROR duplicate definition of value `bar`
fn bar() { //~ ERROR duplicate method in trait impl
}
}

View File

@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
struct Foo {
x: isize
}
impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module
impl Fo { //~ ERROR use of undeclared type name `Fo`
fn foo() {}
}

View File

@ -10,7 +10,7 @@
// ignore-tidy-linelength
impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module
impl B { //~ ERROR use of undeclared type name `B`
}
fn main() {

View File

@ -29,45 +29,104 @@ mod cross_crate {
use lint_stability::*;
fn test() {
type Foo = MethodTester;
let foo = MethodTester;
deprecated(); //~ ERROR use of deprecated item
foo.method_deprecated(); //~ ERROR use of deprecated item
Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
foo.trait_deprecated(); //~ ERROR use of deprecated item
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
deprecated_text(); //~ ERROR use of deprecated item: text
foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
deprecated_unstable(); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
foo.method_deprecated_unstable(); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
<Foo>::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
<Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
<Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
deprecated_unstable_text(); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
<Foo>::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
<Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
<Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
unstable(); //~ WARNING use of unstable library feature
foo.method_unstable(); //~ WARNING use of unstable library feature
Foo::method_unstable(&foo); //~ WARNING use of unstable library feature
<Foo>::method_unstable(&foo); //~ WARNING use of unstable library feature
foo.trait_unstable(); //~ WARNING use of unstable library feature
Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
<Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
<Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
unstable_text();
//~^ WARNING use of unstable library feature 'test_feature': text
foo.method_unstable_text();
//~^ WARNING use of unstable library feature 'test_feature': text
Foo::method_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
<Foo>::method_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
foo.trait_unstable_text();
//~^ WARNING use of unstable library feature 'test_feature': text
Trait::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
<Foo>::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
<Foo as Trait>::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
stable();
foo.method_stable();
Foo::method_stable(&foo);
<Foo>::method_stable(&foo);
foo.trait_stable();
Trait::trait_stable(&foo);
<Foo>::trait_stable(&foo);
<Foo as Trait>::trait_stable(&foo);
stable_text();
foo.method_stable_text();
Foo::method_stable_text(&foo);
<Foo>::method_stable_text(&foo);
foo.trait_stable_text();
Trait::trait_stable_text(&foo);
<Foo>::trait_stable_text(&foo);
<Foo as Trait>::trait_stable_text(&foo);
let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item
@ -104,16 +163,47 @@ mod cross_crate {
macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
}
fn test_method_param<F: Trait>(foo: F) {
fn test_method_param<Foo: Trait>(foo: Foo) {
foo.trait_deprecated(); //~ ERROR use of deprecated item
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
<Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
<Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
//~^ WARNING use of unstable library feature
foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
<Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
<Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
foo.trait_unstable(); //~ WARNING use of unstable library feature
foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
<Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
<Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
foo.trait_unstable_text();
//~^ WARNING use of unstable library feature 'test_feature': text
Trait::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
<Foo>::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
<Foo as Trait>::trait_unstable_text(&foo);
//~^ WARNING use of unstable library feature 'test_feature': text
foo.trait_stable();
Trait::trait_stable(&foo);
<Foo>::trait_stable(&foo);
<Foo as Trait>::trait_stable(&foo);
}
fn test_method_object(foo: &Trait) {
@ -124,7 +214,8 @@ mod cross_crate {
foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
//~^ WARNING use of unstable library feature
foo.trait_unstable(); //~ WARNING use of unstable library feature
foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
foo.trait_unstable_text();
//~^ WARNING use of unstable library feature 'test_feature': text
foo.trait_stable();
}
@ -264,31 +355,62 @@ mod this_crate {
// errors, because other stability attributes now have meaning
// only *across* crates, not within a single crate.
type Foo = MethodTester;
let foo = MethodTester;
deprecated(); //~ ERROR use of deprecated item
foo.method_deprecated(); //~ ERROR use of deprecated item
Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
foo.trait_deprecated(); //~ ERROR use of deprecated item
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
deprecated_text(); //~ ERROR use of deprecated item: text
foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
unstable();
foo.method_unstable();
Foo::method_unstable(&foo);
<Foo>::method_unstable(&foo);
foo.trait_unstable();
Trait::trait_unstable(&foo);
<Foo>::trait_unstable(&foo);
<Foo as Trait>::trait_unstable(&foo);
unstable_text();
foo.method_unstable_text();
Foo::method_unstable_text(&foo);
<Foo>::method_unstable_text(&foo);
foo.trait_unstable_text();
Trait::trait_unstable_text(&foo);
<Foo>::trait_unstable_text(&foo);
<Foo as Trait>::trait_unstable_text(&foo);
stable();
foo.method_stable();
Foo::method_stable(&foo);
<Foo>::method_stable(&foo);
foo.trait_stable();
Trait::trait_stable(&foo);
<Foo>::trait_stable(&foo);
<Foo as Trait>::trait_stable(&foo);
stable_text();
foo.method_stable_text();
Foo::method_stable_text(&foo);
<Foo>::method_stable_text(&foo);
foo.trait_stable_text();
Trait::trait_stable_text(&foo);
<Foo>::trait_stable_text(&foo);
<Foo as Trait>::trait_stable_text(&foo);
let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
let _ = UnstableStruct { i: 0 };
@ -307,12 +429,27 @@ mod this_crate {
let _ = StableTupleStruct (1);
}
fn test_method_param<F: Trait>(foo: F) {
fn test_method_param<Foo: Trait>(foo: Foo) {
foo.trait_deprecated(); //~ ERROR use of deprecated item
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
foo.trait_unstable();
Trait::trait_unstable(&foo);
<Foo>::trait_unstable(&foo);
<Foo as Trait>::trait_unstable(&foo);
foo.trait_unstable_text();
Trait::trait_unstable_text(&foo);
<Foo>::trait_unstable_text(&foo);
<Foo as Trait>::trait_unstable_text(&foo);
foo.trait_stable();
Trait::trait_stable(&foo);
<Foo>::trait_stable(&foo);
<Foo as Trait>::trait_stable(&foo);
}
fn test_method_object(foo: &Trait) {

View File

@ -29,7 +29,7 @@ impl S {
// Cause an error. It shouldn't have any macro backtrace frames.
fn bar(&self) { }
fn bar(&self) { } //~ ERROR duplicate definition
fn bar(&self) { } //~ ERROR duplicate method
}
fn main() { }

View File

@ -18,11 +18,11 @@
mod foo {
mod baz {
struct Test;
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Add for Test {} //~ ERROR: use of undeclared trait
impl Clone for Test {} //~ ERROR: use of undeclared trait
impl Iterator for Test {} //~ ERROR: use of undeclared trait
impl ToString for Test {} //~ ERROR: use of undeclared trait
impl Writer for Test {} //~ ERROR: use of undeclared trait
fn foo() {
drop(2) //~ ERROR: unresolved name
@ -30,11 +30,11 @@ mod foo {
}
struct Test;
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Add for Test {} //~ ERROR: use of undeclared trait
impl Clone for Test {} //~ ERROR: use of undeclared trait
impl Iterator for Test {} //~ ERROR: use of undeclared trait
impl ToString for Test {} //~ ERROR: use of undeclared trait
impl Writer for Test {} //~ ERROR: use of undeclared trait
fn foo() {
drop(2) //~ ERROR: unresolved name
@ -45,11 +45,11 @@ fn qux() {
#[no_implicit_prelude]
mod qux_inner {
struct Test;
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Add for Test {} //~ ERROR: use of undeclared trait
impl Clone for Test {} //~ ERROR: use of undeclared trait
impl Iterator for Test {} //~ ERROR: use of undeclared trait
impl ToString for Test {} //~ ERROR: use of undeclared trait
impl Writer for Test {} //~ ERROR: use of undeclared trait
fn foo() {
drop(2) //~ ERROR: unresolved name

View File

@ -17,11 +17,11 @@
// fail with the same error message).
struct Test;
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Add for Test {} //~ ERROR: use of undeclared trait
impl Clone for Test {} //~ ERROR: use of undeclared trait
impl Iterator for Test {} //~ ERROR: use of undeclared trait
impl ToString for Test {} //~ ERROR: use of undeclared trait
impl Writer for Test {} //~ ERROR: use of undeclared trait
fn main() {
drop(2) //~ ERROR: unresolved name

View File

@ -10,11 +10,11 @@
trait NewTrait : SomeNonExistentTrait {}
//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait`
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
impl SomeNonExistentTrait for isize {}
//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait`
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
fn f<T:SomeNonExistentTrait>() {}
//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait`
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`

View File

@ -14,7 +14,7 @@ mod a {
trait A {
}
impl A for a { //~ERROR found module name used as a type
impl A for a { //~ ERROR use of undeclared type name `a`
}
fn main() {

Some files were not shown because too many files have changed in this diff Show More