Rollup merge of #22635 - kmcallister:macros-chapter, r=steveklabnik
r? @steveklabnik
This commit is contained in:
commit
9692f3bc94
@ -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*
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -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)
|
||||
|
@ -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'),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(..)) => {
|
||||
|
@ -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 \
|
||||
|
@ -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) =>
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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?!")
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
..
|
||||
|
@ -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)),
|
||||
|
@ -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", (), |_|
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
@ -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 {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {:?} \
|
||||
|
@ -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));
|
||||
|
@ -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(_)) => {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) |
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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)) => {
|
||||
|
@ -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>,
|
||||
|
@ -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) => {}
|
||||
|
@ -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(..) => {}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ register_diagnostics! {
|
||||
E0120,
|
||||
E0121,
|
||||
E0122,
|
||||
E0123,
|
||||
E0124,
|
||||
E0127,
|
||||
E0128,
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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()))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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_),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, .. }] => {
|
||||
|
@ -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))),
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
|
@ -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| {
|
||||
|
@ -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)
|
||||
|
@ -22,5 +22,8 @@ trait Grab {
|
||||
//~^ ERROR ambiguous associated type
|
||||
}
|
||||
|
||||
type X = std::ops::Deref::Target;
|
||||
//~^ ERROR ambiguous associated type
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() {}
|
||||
|
@ -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!();
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user