Rollup merge of #22635 - kmcallister:macros-chapter, r=steveklabnik

r? @steveklabnik
This commit is contained in:
Manish Goregaokar 2015-02-25 10:27:03 +05:30
commit 9692f3bc94
115 changed files with 2509 additions and 2683 deletions

View File

@ -731,15 +731,20 @@ Rust syntax is restricted in two ways:
pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
requiring a distinctive token in front can solve the problem.
## Syntax extensions useful for the macro author
## Syntax extensions useful in macros
* `stringify!` : turn the identifier argument into a string literal
* `concat!` : concatenates a comma-separated list of literals
## Syntax extensions for macro debugging
* `log_syntax!` : print out the arguments at compile time
* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
* `stringify!` : turn the identifier argument into a string literal
* `concat!` : concatenates a comma-separated list of literals
* `concat_idents!` : create a new identifier by concatenating the arguments
The following attributes are used for quasiquoting in procedural macros:
## Quasiquoting
The following syntax extensions are used for quasiquoting Rust syntax trees,
usually in [procedural macros](book/plugins.html#syntax-extensions):
* `quote_expr!`
* `quote_item!`
@ -748,6 +753,8 @@ The following attributes are used for quasiquoting in procedural macros:
* `quote_tokens!`
* `quote_ty!`
Documentation is very limited at the moment.
# Crates and source files
Rust is a *compiled* language. Its semantics obey a *phase distinction*

View File

@ -192,19 +192,58 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# A final note
# The deep end
Macros, as currently implemented, are not for the faint of heart. Even
ordinary syntax errors can be more difficult to debug when they occur inside a
macro, and errors caused by parse problems in generated code can be very
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
states, invoking `trace_macros!(true)` will automatically print those
intermediate states out, and passing the flag `--pretty expanded` as a
command-line argument to the compiler will show the result of expansion.
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
```rust
#![feature(trace_macros)]
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
fn main() {
trace_macros!(true);
# /* just check the definition
bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
# */
}
```
Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and the warnings about debugging apply ten-fold. In exchange you get the
and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View File

@ -189,14 +189,12 @@ shorthand for a data type could be valid as either an expression or a pattern.
## Repetition
The repetition behavior can seem somewhat magical, especially when multiple
names are bound at multiple nested levels of repetition. The two rules to keep
in mind are:
The repetition operator follows two principal rules:
1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
all of the `$name`s it contains, in lockstep, and
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched
against. If it is under more, it'll be duplicated, as appropriate.
against. If it is under more, it'll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer
repetition levels.
@ -226,6 +224,10 @@ That's most of the matcher syntax. These examples use `$(...)*`, which is a
more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`.
This system is based on
"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
(PDF link).
# Hygiene
Some languages implement macros using simple text substitution, which leads to
@ -273,19 +275,26 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
})
```
This looks reasonable, but watch what happens in this example:
Here's a simple use case that goes terribly wrong:
```text
const char *state = "reticulating splines";
LOG(state);
LOG(state)
```
The program will likely segfault, after it tries to execute
This expands to
```text
printf("log(%d): %s\n", state, state);
const char *state = "reticulating splines";
int state = get_log_state();
if (state > 0) {
printf("log(%d): %s\n", state, state);
}
```
The second variable named `state` shadows the first one. This is a problem
because the print statement should refer to both of them.
The equivalent Rust macro has the desired behavior.
```rust
@ -357,6 +366,64 @@ fn main() {
[items]: ../reference.html#items
# Recursive macros
A macro's expansion can include more macro invocations, including invocations
of the very same macro being expanded. These recursive macros are useful for
processing tree-structured input, as illustrated by this (simplistic) HTML
shorthand:
```rust
# #![allow(unused_must_use)]
macro_rules! write_html {
($w:expr, ) => (());
($w:expr, $e:tt) => (write!($w, "{}", $e));
($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
write!($w, "<{}>", stringify!($tag));
write_html!($w, $($inner)*);
write!($w, "</{}>", stringify!($tag));
write_html!($w, $($rest)*);
}};
}
fn main() {
# // FIXME(#21826)
use std::fmt::Write;
let mut out = String::new();
write_html!(&mut out,
html[
head[title["Macros guide"]]
body[h1["Macros are the best!"]]
]);
assert_eq!(out,
"<html><head><title>Macros guide</title></head>\
<body><h1>Macros are the best!</h1></body></html>");
}
```
# Debugging macro code
To see the results of expanding macros, run `rustc --pretty expanded`. The
output represents a whole crate, so you can also feed it back in to `rustc`,
which will sometimes produce better error messages than the original
compilation. Note that the `--pretty expanded` output may have a different
meaning if multiple variables of the same name (but different syntax contexts)
are in play in the same scope. In this case `--pretty expanded,hygiene` will
tell you about the syntax contexts.
`rustc` provides two syntax extensions that help with macro debugging. For now,
they are unstable and require feature gates.
* `log_syntax!(...)` will print its arguments to standard output, at compile
time, and "expand" to nothing.
* `trace_macros!(true)` will enable a compiler message every time a macro is
expanded. Use `trace_macros!(false)` later in expansion to turn it off.
# Further reading
The [advanced macros chapter][] goes into more detail about macro syntax. It

View File

@ -146,14 +146,7 @@ a more involved macro example, see
## Tips and tricks
To see the results of expanding syntax extensions, run
`rustc --pretty expanded`. The output represents a whole crate, so you
can also feed it back in to `rustc`, which will sometimes produce better
error messages than the original compilation. Note that the
`--pretty expanded` output may have a different meaning if multiple
variables of the same name (but different syntax contexts) are in play
in the same scope. In this case `--pretty expanded,hygiene` will tell
you about the syntax contexts.
Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into
higher-level syntax elements like expressions:
@ -184,6 +177,11 @@ and return
[`DummyResult`](../syntax/ext/base/struct.DummyResult.html),
so that the compiler can continue and find further errors.
To print syntax fragments for debugging, you can use
[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together
with
[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
The example above produced an integer literal using
[`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint).
As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of

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,
@ -1899,10 +1902,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 {
get_static_val(cx, def_id, ety)
} else {
@ -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() { }

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