Auto merge of #37678 - eddyb:rollup, r=eddyb
Rollup of 5 pull requests - Successful merges: #37402, #37412, #37661, #37664, #37667 - Failed merges:
This commit is contained in:
commit
b46ce08df5
src
doc
libpanic_abort
librustc
cfg
dep_graph
diagnostics.rshir
lint
middle
cstore.rsdataflow.rsdead.rseffect.rsexpr_use_visitor.rsintrinsicck.rsliveness.rsreachable.rsregion.rsresolve_lifetime.rsstability.rs
traits
ty
util
librustc_borrowck/borrowck
librustc_const_eval
librustc_driver
librustc_lint
librustc_llvm
librustc_metadata
librustc_mir
librustc_passes
librustc_privacy
librustc_resolve
librustc_save_analysis
librustc_trans
librustc_typeck
astconv.rs
check
_match.rsclosure.rscompare_method.rsdropck.rs
method
mod.rsop.rsregionck.rsupvar.rswfcheck.rswriteback.rscoherence
collect.rslibrustdoc/clean
libsyntax
libsyntax_ext/deriving
test/compile-fail
@ -94,6 +94,7 @@
|
||||
* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
|
||||
* `||` (`expr || expr`): logical or.
|
||||
* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]).
|
||||
* `?` (`expr?`): Error propagation. Returns early when `Err(_)` is encountered, unwraps otherwise. Similar to the [`try!` macro].
|
||||
|
||||
## Other Syntax
|
||||
|
||||
@ -210,6 +211,7 @@
|
||||
[Functions]: functions.html
|
||||
[Generics]: generics.html
|
||||
[Iterators]: iterators.html
|
||||
[`try!` macro]: error-handling.html#the-try-macro
|
||||
[Lifetimes]: lifetimes.html
|
||||
[Loops (`for`)]: loops.html#for
|
||||
[Loops (`loop`)]: loops.html#loop
|
||||
|
@ -2863,8 +2863,8 @@ assert_eq!(x, y);
|
||||
|
||||
### Unary operator expressions
|
||||
|
||||
Rust defines the following unary operators. They are all written as prefix operators,
|
||||
before the expression they apply to.
|
||||
Rust defines the following unary operators. With the exception of `?`, they are
|
||||
all written as prefix operators, before the expression they apply to.
|
||||
|
||||
* `-`
|
||||
: Negation. Signed integer types and floating-point types support negation. It
|
||||
@ -2893,6 +2893,10 @@ before the expression they apply to.
|
||||
If the `&` or `&mut` operators are applied to an rvalue, a
|
||||
temporary value is created; the lifetime of this temporary value
|
||||
is defined by [syntactic rules](#temporary-lifetimes).
|
||||
* `?`
|
||||
: Propagating errors if applied to `Err(_)` and unwrapping if
|
||||
applied to `Ok(_)`. Only works on the `Result<T, E>` type,
|
||||
and written in postfix notation.
|
||||
|
||||
### Binary operator expressions
|
||||
|
||||
|
@ -53,7 +53,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
|
||||
// now hopefully.
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
|
||||
return abort();
|
||||
abort();
|
||||
|
||||
#[cfg(unix)]
|
||||
unsafe fn abort() -> ! {
|
||||
|
@ -33,16 +33,16 @@ struct LoopScope {
|
||||
}
|
||||
|
||||
pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
blk: &hir::Block) -> CFG {
|
||||
body: &hir::Expr) -> CFG {
|
||||
let mut graph = graph::Graph::new();
|
||||
let entry = graph.add_node(CFGNodeData::Entry);
|
||||
|
||||
// `fn_exit` is target of return exprs, which lies somewhere
|
||||
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
|
||||
// outside input `body`. (Distinguishing `fn_exit` and `body_exit`
|
||||
// also resolves chicken-and-egg problem that arises if you try to
|
||||
// have return exprs jump to `block_exit` during construction.)
|
||||
// have return exprs jump to `body_exit` during construction.)
|
||||
let fn_exit = graph.add_node(CFGNodeData::Exit);
|
||||
let block_exit;
|
||||
let body_exit;
|
||||
|
||||
let mut cfg_builder = CFGBuilder {
|
||||
graph: graph,
|
||||
@ -50,8 +50,8 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tcx: tcx,
|
||||
loop_scopes: Vec::new()
|
||||
};
|
||||
block_exit = cfg_builder.block(blk, entry);
|
||||
cfg_builder.add_contained_edge(block_exit, fn_exit);
|
||||
body_exit = cfg_builder.expr(body, entry);
|
||||
cfg_builder.add_contained_edge(body_exit, fn_exit);
|
||||
let CFGBuilder {graph, ..} = cfg_builder;
|
||||
CFG {graph: graph,
|
||||
entry: entry,
|
||||
|
@ -59,8 +59,8 @@ pub type CFGEdge = graph::Edge<CFGEdgeData>;
|
||||
|
||||
impl CFG {
|
||||
pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
blk: &hir::Block) -> CFG {
|
||||
construct::construct(tcx, blk)
|
||||
body: &hir::Expr) -> CFG {
|
||||
construct::construct(tcx, body)
|
||||
}
|
||||
|
||||
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
|
||||
|
@ -103,11 +103,11 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
// nodes. Often we map multiple tables to the same node if there
|
||||
// is no point in distinguishing them (e.g., both the type and
|
||||
// predicates for an item wind up in `ItemSignature`).
|
||||
ImplOrTraitItems(D),
|
||||
AssociatedItems(D),
|
||||
ItemSignature(D),
|
||||
FieldTy(D),
|
||||
SizedConstraint(D),
|
||||
ImplOrTraitItemDefIds(D),
|
||||
AssociatedItemDefIds(D),
|
||||
InherentImpls(D),
|
||||
|
||||
// The set of impls for a given trait. Ultimately, it would be
|
||||
@ -153,10 +153,10 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
TransCrateItem,
|
||||
TypeckItemType,
|
||||
TypeckItemBody,
|
||||
ImplOrTraitItems,
|
||||
AssociatedItems,
|
||||
ItemSignature,
|
||||
FieldTy,
|
||||
ImplOrTraitItemDefIds,
|
||||
AssociatedItemDefIds,
|
||||
InherentImpls,
|
||||
TraitImpls,
|
||||
ReprHints,
|
||||
@ -219,11 +219,11 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
RvalueCheck(ref d) => op(d).map(RvalueCheck),
|
||||
TransCrateItem(ref d) => op(d).map(TransCrateItem),
|
||||
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
|
||||
ImplOrTraitItems(ref d) => op(d).map(ImplOrTraitItems),
|
||||
AssociatedItems(ref d) => op(d).map(AssociatedItems),
|
||||
ItemSignature(ref d) => op(d).map(ItemSignature),
|
||||
FieldTy(ref d) => op(d).map(FieldTy),
|
||||
SizedConstraint(ref d) => op(d).map(SizedConstraint),
|
||||
ImplOrTraitItemDefIds(ref d) => op(d).map(ImplOrTraitItemDefIds),
|
||||
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
||||
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
|
@ -672,120 +672,6 @@ extern "C" {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0269: r##"
|
||||
A returned value was expected but not all control paths return one.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0269
|
||||
fn abracada_FAIL() -> String {
|
||||
"this won't work".to_string();
|
||||
// error: not all control paths return a value
|
||||
}
|
||||
```
|
||||
|
||||
In the previous code, the function is supposed to return a `String`, however,
|
||||
the code returns nothing (because of the ';'). Another erroneous code would be:
|
||||
|
||||
```compile_fail
|
||||
fn abracada_FAIL(b: bool) -> u32 {
|
||||
if b {
|
||||
0
|
||||
} else {
|
||||
"a" // It fails because an `u32` was expected and something else is
|
||||
// returned.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is advisable to find out what the unhandled cases are and check for them,
|
||||
returning an appropriate value or panicking if necessary. Check if you need
|
||||
to remove a semicolon from the last expression, like in the first erroneous
|
||||
code example.
|
||||
"##,
|
||||
|
||||
E0270: r##"
|
||||
Rust lets you define functions which are known to never return, i.e. are
|
||||
'diverging', by marking its return type as `!`.
|
||||
|
||||
For example, the following functions never return:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn bar() -> ! {
|
||||
foo() // foo() is diverging, so this will diverge too
|
||||
}
|
||||
|
||||
fn baz() -> ! {
|
||||
panic!(); // this macro internally expands to a call to a diverging function
|
||||
}
|
||||
```
|
||||
|
||||
Such functions can be used in a place where a value is expected without
|
||||
returning a value of that type, for instance:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo() // diverging function called here
|
||||
};
|
||||
|
||||
println!("{}", y)
|
||||
```
|
||||
|
||||
If the third arm of the match block is reached, since `foo()` doesn't ever
|
||||
return control to the match block, it is fine to use it in a place where an
|
||||
integer was expected. The `match` block will never finish executing, and any
|
||||
point where `y` (like the print statement) is needed will not be reached.
|
||||
|
||||
However, if we had a diverging function that actually does finish execution:
|
||||
|
||||
```ignore
|
||||
fn foo() -> ! {
|
||||
loop {break;}
|
||||
}
|
||||
```
|
||||
|
||||
Then we would have an unknown value for `y` in the following code:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo()
|
||||
};
|
||||
|
||||
println!("{}", y);
|
||||
```
|
||||
|
||||
In the previous example, the print statement was never reached when the
|
||||
wildcard match arm was hit, so we were okay with `foo()` not returning an
|
||||
integer that we could set to `y`. But in this example, `foo()` actually does
|
||||
return control, so the print statement will be executed with an uninitialized
|
||||
value.
|
||||
|
||||
Obviously we cannot have functions which are allowed to be used in such
|
||||
positions and yet can return control. So, if you are defining a function that
|
||||
returns `!`, make sure that there is no way for it to actually finish
|
||||
executing.
|
||||
"##,
|
||||
|
||||
E0271: r##"
|
||||
This is because of a type mismatch between the associated type of some
|
||||
trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`)
|
||||
|
@ -138,7 +138,7 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
|
||||
walk_where_predicate(self, predicate)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Expr, s: Span, id: NodeId) {
|
||||
walk_fn(self, fk, fd, b, s, id)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &'v TraitItem) {
|
||||
@ -635,13 +635,13 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
|
||||
pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
function_kind: FnKind<'v>,
|
||||
function_declaration: &'v FnDecl,
|
||||
function_body: &'v Block,
|
||||
function_body: &'v Expr,
|
||||
_span: Span,
|
||||
id: NodeId) {
|
||||
visitor.visit_id(id);
|
||||
walk_fn_decl(visitor, function_declaration);
|
||||
walk_fn_kind(visitor, function_kind);
|
||||
visitor.visit_block(function_body)
|
||||
visitor.visit_expr(function_body)
|
||||
}
|
||||
|
||||
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
|
||||
@ -925,7 +925,7 @@ impl<'v> Visitor<'v> for IdRangeComputingVisitor {
|
||||
/// Computes the id range for a single fn body, ignoring nested items.
|
||||
pub fn compute_id_range_for_fn_body(fk: FnKind,
|
||||
decl: &FnDecl,
|
||||
body: &Block,
|
||||
body: &Expr,
|
||||
sp: Span,
|
||||
id: NodeId)
|
||||
-> IdRange {
|
||||
|
@ -595,12 +595,13 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::ItemConst(self.lower_ty(t), self.lower_expr(e))
|
||||
}
|
||||
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
|
||||
let body = self.lower_block(body);
|
||||
hir::ItemFn(self.lower_fn_decl(decl),
|
||||
self.lower_unsafety(unsafety),
|
||||
self.lower_constness(constness),
|
||||
abi,
|
||||
self.lower_generics(generics),
|
||||
self.lower_block(body))
|
||||
self.expr_block(body, ThinVec::new()))
|
||||
}
|
||||
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
|
||||
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
|
||||
@ -665,7 +666,10 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
TraitItemKind::Method(ref sig, ref body) => {
|
||||
hir::MethodTraitItem(this.lower_method_sig(sig),
|
||||
body.as_ref().map(|x| this.lower_block(x)))
|
||||
body.as_ref().map(|x| {
|
||||
let body = this.lower_block(x);
|
||||
this.expr_block(body, ThinVec::new())
|
||||
}))
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
hir::TypeTraitItem(this.lower_bounds(bounds),
|
||||
@ -691,8 +695,9 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr))
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
let body = this.lower_block(body);
|
||||
hir::ImplItemKind::Method(this.lower_method_sig(sig),
|
||||
this.lower_block(body))
|
||||
this.expr_block(body, ThinVec::new()))
|
||||
}
|
||||
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
|
||||
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
|
||||
@ -1110,7 +1115,7 @@ impl<'a> LoweringContext<'a> {
|
||||
self.with_parent_def(e.id, |this| {
|
||||
hir::ExprClosure(this.lower_capture_clause(capture_clause),
|
||||
this.lower_fn_decl(decl),
|
||||
this.lower_block(body),
|
||||
this.lower_expr(body),
|
||||
fn_decl_span)
|
||||
})
|
||||
}
|
||||
|
@ -21,11 +21,9 @@
|
||||
//! nested within a uniquely determined `FnLike`), and users can ask
|
||||
//! for the `Code` associated with a particular NodeId.
|
||||
|
||||
pub use self::Code::*;
|
||||
|
||||
use hir as ast;
|
||||
use hir::map::{self, Node};
|
||||
use hir::{Block, FnDecl};
|
||||
use hir::{Expr, FnDecl};
|
||||
use hir::intravisit::FnKind;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{Attribute, Name, NodeId};
|
||||
@ -50,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
|
||||
/// Components shared by fn-like things (fn items, methods, closures).
|
||||
pub struct FnParts<'a> {
|
||||
pub decl: &'a FnDecl,
|
||||
pub body: &'a Block,
|
||||
pub body: &'a Expr,
|
||||
pub kind: FnKind<'a>,
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -77,29 +75,32 @@ impl MaybeFnLike for ast::Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/// Carries either an FnLikeNode or a Block, as these are the two
|
||||
/// Carries either an FnLikeNode or a Expr, as these are the two
|
||||
/// constructs that correspond to "code" (as in, something from which
|
||||
/// we can construct a control-flow graph).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Code<'a> {
|
||||
FnLikeCode(FnLikeNode<'a>),
|
||||
BlockCode(&'a Block),
|
||||
FnLike(FnLikeNode<'a>),
|
||||
Expr(&'a Expr),
|
||||
}
|
||||
|
||||
impl<'a> Code<'a> {
|
||||
pub fn id(&self) -> NodeId {
|
||||
match *self {
|
||||
FnLikeCode(node) => node.id(),
|
||||
BlockCode(block) => block.id,
|
||||
Code::FnLike(node) => node.id(),
|
||||
Code::Expr(block) => block.id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to construct a Code from presumed FnLike or Block node input.
|
||||
pub fn from_node(node: Node) -> Option<Code> {
|
||||
if let map::NodeBlock(block) = node {
|
||||
Some(BlockCode(block))
|
||||
} else {
|
||||
FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like))
|
||||
/// Attempts to construct a Code from presumed FnLike or Expr node input.
|
||||
pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option<Code<'a>> {
|
||||
match map.get(id) {
|
||||
map::NodeBlock(_) => {
|
||||
// Use the parent, hopefully an expression node.
|
||||
Code::from_node(map, map.get_parent_node(id))
|
||||
}
|
||||
map::NodeExpr(expr) => Some(Code::Expr(expr)),
|
||||
node => FnLikeNode::from_node(node).map(Code::FnLike)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +115,7 @@ struct ItemFnParts<'a> {
|
||||
abi: abi::Abi,
|
||||
vis: &'a ast::Visibility,
|
||||
generics: &'a ast::Generics,
|
||||
body: &'a Block,
|
||||
body: &'a Expr,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
attrs: &'a [Attribute],
|
||||
@ -124,14 +125,14 @@ struct ItemFnParts<'a> {
|
||||
/// for use when implementing FnLikeNode operations.
|
||||
struct ClosureParts<'a> {
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
body: &'a Expr,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
attrs: &'a [Attribute],
|
||||
}
|
||||
|
||||
impl<'a> ClosureParts<'a> {
|
||||
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
|
||||
fn new(d: &'a FnDecl, b: &'a Expr, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
|
||||
ClosureParts {
|
||||
decl: d,
|
||||
body: b,
|
||||
@ -171,9 +172,9 @@ impl<'a> FnLikeNode<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(self) -> &'a Block {
|
||||
pub fn body(self) -> &'a Expr {
|
||||
self.handle(|i: ItemFnParts<'a>| &*i.body,
|
||||
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body,
|
||||
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Expr, _, _| body,
|
||||
|c: ClosureParts<'a>| c.body)
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ impl<'a> FnLikeNode<'a> {
|
||||
Name,
|
||||
&'a ast::MethodSig,
|
||||
Option<&'a ast::Visibility>,
|
||||
&'a ast::Block,
|
||||
&'a ast::Expr,
|
||||
Span,
|
||||
&'a [Attribute])
|
||||
-> A,
|
||||
|
@ -211,7 +211,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
|
||||
b: &'ast Block, s: Span, id: NodeId) {
|
||||
b: &'ast Expr, s: Span, id: NodeId) {
|
||||
assert_eq!(self.parent_node, id);
|
||||
intravisit::walk_fn(self, fk, fd, b, s, id);
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ pub enum Expr_ {
|
||||
/// A closure (for example, `move |a, b, c| {a + b + c}`).
|
||||
///
|
||||
/// The final span is the span of the argument block `|...|`
|
||||
ExprClosure(CaptureClause, P<FnDecl>, P<Block>, Span),
|
||||
ExprClosure(CaptureClause, P<FnDecl>, P<Expr>, Span),
|
||||
/// A block (`{ ... }`)
|
||||
ExprBlock(P<Block>),
|
||||
|
||||
@ -1035,7 +1035,7 @@ pub enum TraitItem_ {
|
||||
/// must contain a value)
|
||||
ConstTraitItem(P<Ty>, Option<P<Expr>>),
|
||||
/// A method with an optional body
|
||||
MethodTraitItem(MethodSig, Option<P<Block>>),
|
||||
MethodTraitItem(MethodSig, Option<P<Expr>>),
|
||||
/// An associated type with (possibly empty) bounds and optional concrete
|
||||
/// type
|
||||
TypeTraitItem(TyParamBounds, Option<P<Ty>>),
|
||||
@ -1060,7 +1060,7 @@ pub enum ImplItemKind {
|
||||
/// of the expression
|
||||
Const(P<Ty>, P<Expr>),
|
||||
/// A method implementation with the given signature and body
|
||||
Method(MethodSig, P<Block>),
|
||||
Method(MethodSig, P<Expr>),
|
||||
/// An associated type
|
||||
Type(P<Ty>),
|
||||
}
|
||||
@ -1501,7 +1501,7 @@ pub enum Item_ {
|
||||
/// A `const` item
|
||||
ItemConst(P<Ty>, P<Expr>),
|
||||
/// A function declaration
|
||||
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
|
||||
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Expr>),
|
||||
/// A module
|
||||
ItemMod(Mod),
|
||||
/// An external module
|
||||
|
@ -713,7 +713,9 @@ impl<'a> State<'a> {
|
||||
typarams,
|
||||
&item.vis)?;
|
||||
word(&mut self.s, " ")?;
|
||||
self.print_block_with_attrs(&body, &item.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(&body)?;
|
||||
}
|
||||
hir::ItemMod(ref _mod) => {
|
||||
self.head(&visibility_qualified(&item.vis, "mod"))?;
|
||||
@ -1002,7 +1004,9 @@ impl<'a> State<'a> {
|
||||
self.print_method_sig(ti.name, sig, &hir::Inherited)?;
|
||||
if let Some(ref body) = *body {
|
||||
self.nbsp()?;
|
||||
self.print_block_with_attrs(body, &ti.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(body)?;
|
||||
} else {
|
||||
word(&mut self.s, ";")?;
|
||||
}
|
||||
@ -1034,7 +1038,9 @@ impl<'a> State<'a> {
|
||||
self.head("")?;
|
||||
self.print_method_sig(ii.name, sig, &ii.vis)?;
|
||||
self.nbsp()?;
|
||||
self.print_block_with_attrs(body, &ii.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(body)?;
|
||||
}
|
||||
hir::ImplItemKind::Type(ref ty) => {
|
||||
self.print_associated_type(ii.name, None, Some(ty))?;
|
||||
@ -1402,26 +1408,10 @@ impl<'a> State<'a> {
|
||||
self.print_fn_block_args(&decl)?;
|
||||
space(&mut self.s)?;
|
||||
|
||||
let default_return = match decl.output {
|
||||
hir::DefaultReturn(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
// this is a bare expression
|
||||
self.print_expr(body)?;
|
||||
self.end()?; // need to close a box
|
||||
|
||||
if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
|
||||
self.print_block_unclosed(&body)?;
|
||||
} else {
|
||||
// we extract the block, so as not to create another set of boxes
|
||||
match body.expr.as_ref().unwrap().node {
|
||||
hir::ExprBlock(ref blk) => {
|
||||
self.print_block_unclosed(&blk)?;
|
||||
}
|
||||
_ => {
|
||||
// this is a bare expression
|
||||
self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?;
|
||||
self.end()?; // need to close a box
|
||||
}
|
||||
}
|
||||
}
|
||||
// a box will be closed by print_expr, but we didn't want an overall
|
||||
// wrapper so we closed the corresponding opening. so create an
|
||||
// empty box to satisfy the close.
|
||||
|
@ -838,7 +838,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl,
|
||||
body: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
body: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
|
||||
hir_visit::walk_fn(self, fk, decl, body, span, id);
|
||||
run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
|
||||
@ -994,10 +994,10 @@ impl<'a> ast_visit::Visitor for EarlyContext<'a> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind, decl: &ast::FnDecl,
|
||||
body: &ast::Block, span: Span, id: ast::NodeId) {
|
||||
run_lints!(self, check_fn, early_passes, fk, decl, body, span, id);
|
||||
ast_visit::walk_fn(self, fk, decl, body, span);
|
||||
run_lints!(self, check_fn_post, early_passes, fk, decl, body, span, id);
|
||||
span: Span, id: ast::NodeId) {
|
||||
run_lints!(self, check_fn, early_passes, fk, decl, span, id);
|
||||
ast_visit::walk_fn(self, fk, decl, span);
|
||||
run_lints!(self, check_fn_post, early_passes, fk, decl, span, id);
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self,
|
||||
|
@ -151,9 +151,9 @@ pub trait LateLintPass: LintPass {
|
||||
fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { }
|
||||
fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { }
|
||||
fn check_fn(&mut self, _: &LateContext,
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { }
|
||||
fn check_fn_post(&mut self, _: &LateContext,
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { }
|
||||
fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { }
|
||||
fn check_trait_item_post(&mut self, _: &LateContext, _: &hir::TraitItem) { }
|
||||
fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { }
|
||||
@ -200,9 +200,9 @@ pub trait EarlyLintPass: LintPass {
|
||||
fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { }
|
||||
fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { }
|
||||
fn check_fn(&mut self, _: &EarlyContext,
|
||||
_: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
|
||||
_: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { }
|
||||
fn check_fn_post(&mut self, _: &EarlyContext,
|
||||
_: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
|
||||
_: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { }
|
||||
fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
|
||||
fn check_trait_item_post(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
|
||||
fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { }
|
||||
|
@ -147,7 +147,7 @@ pub trait CrateStore<'tcx> {
|
||||
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
|
||||
|
||||
// impl info
|
||||
fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId>;
|
||||
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>;
|
||||
fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::TraitRef<'tcx>>;
|
||||
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity;
|
||||
@ -157,8 +157,8 @@ pub trait CrateStore<'tcx> {
|
||||
|
||||
// trait/impl-item info
|
||||
fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
|
||||
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::ImplOrTraitItem<'tcx>>;
|
||||
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::AssociatedItem>;
|
||||
|
||||
// flags
|
||||
fn is_const_fn(&self, did: DefId) -> bool;
|
||||
@ -311,8 +311,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
}
|
||||
|
||||
// impl info
|
||||
fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId>
|
||||
{ bug!("impl_or_trait_items") }
|
||||
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>
|
||||
{ bug!("associated_items") }
|
||||
fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::TraitRef<'tcx>> { bug!("impl_trait_ref") }
|
||||
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") }
|
||||
@ -323,8 +323,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
|
||||
// trait/impl-item info
|
||||
fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
|
||||
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
|
||||
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::AssociatedItem> { bug!("associated_item") }
|
||||
|
||||
// flags
|
||||
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
|
||||
|
@ -498,7 +498,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
|
||||
|
||||
impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
|
||||
// ^^^^^^^^^^^^^ only needed for pretty printing
|
||||
pub fn propagate(&mut self, cfg: &cfg::CFG, blk: &hir::Block) {
|
||||
pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
|
||||
//! Performs the data flow analysis.
|
||||
|
||||
if self.bits_per_id == 0 {
|
||||
@ -524,17 +524,17 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
|
||||
debug!("Dataflow result for {}:", self.analysis_name);
|
||||
debug!("{}", {
|
||||
let mut v = Vec::new();
|
||||
self.pretty_print_to(box &mut v, blk).unwrap();
|
||||
self.pretty_print_to(box &mut v, body).unwrap();
|
||||
String::from_utf8(v).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
|
||||
blk: &hir::Block) -> io::Result<()> {
|
||||
body: &hir::Expr) -> io::Result<()> {
|
||||
let mut ps = pprust::rust_printer_annotated(wr, self, None);
|
||||
ps.cbox(pprust::indent_unit)?;
|
||||
ps.ibox(0)?;
|
||||
ps.print_block(blk)?;
|
||||
ps.print_expr(body)?;
|
||||
pp::eof(&mut ps.s)
|
||||
}
|
||||
}
|
||||
|
@ -471,11 +471,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
|
||||
// This is done to handle the case where, for example, the static
|
||||
// method of a private type is used, but the type itself is never
|
||||
// called directly.
|
||||
let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow();
|
||||
if let Some(impl_list) =
|
||||
self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) {
|
||||
for impl_did in impl_list.iter() {
|
||||
for &item_did in &impl_items[impl_did][..] {
|
||||
for &impl_did in impl_list.iter() {
|
||||
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
|
||||
if let Some(item_node_id) = self.tcx.map.as_local_node_id(item_did) {
|
||||
if self.live_symbols.contains(&item_node_id) {
|
||||
return true;
|
||||
@ -567,7 +566,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
self.warn_dead_code(impl_item.id, impl_item.span,
|
||||
impl_item.name, "method");
|
||||
}
|
||||
intravisit::walk_block(self, body)
|
||||
intravisit::walk_expr(self, body)
|
||||
}
|
||||
hir::ImplItemKind::Type(..) => {}
|
||||
}
|
||||
@ -576,11 +575,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
// Overwrite so that we don't warn the trait item itself.
|
||||
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
|
||||
match trait_item.node {
|
||||
hir::ConstTraitItem(_, Some(ref expr)) => {
|
||||
intravisit::walk_expr(self, expr)
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref body))|
|
||||
hir::MethodTraitItem(_, Some(ref body)) => {
|
||||
intravisit::walk_block(self, body)
|
||||
intravisit::walk_expr(self, body)
|
||||
}
|
||||
hir::ConstTraitItem(_, None) |
|
||||
hir::MethodTraitItem(_, None) |
|
||||
|
@ -94,7 +94,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
|
||||
block: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
block: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
|
||||
let (is_item_fn, is_unsafe_fn) = match fn_kind {
|
||||
FnKind::ItemFn(_, _, unsafety, ..) =>
|
||||
|
@ -227,8 +227,8 @@ impl OverloadedCallType {
|
||||
}
|
||||
|
||||
fn from_method_id(tcx: TyCtxt, method_id: DefId) -> OverloadedCallType {
|
||||
let method = tcx.impl_or_trait_item(method_id);
|
||||
OverloadedCallType::from_trait_id(tcx, method.container().id())
|
||||
let method = tcx.associated_item(method_id);
|
||||
OverloadedCallType::from_trait_id(tcx, method.container.id())
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,14 +290,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn walk_fn(&mut self,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
self.walk_arg_patterns(decl, body);
|
||||
self.walk_block(body);
|
||||
self.consume_expr(body);
|
||||
}
|
||||
|
||||
fn walk_arg_patterns(&mut self,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
for arg in &decl.inputs {
|
||||
let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
|
||||
|
||||
|
@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
if let FnKind::Closure(..) = fk {
|
||||
span_bug!(s, "intrinsicck: closure outside of function")
|
||||
}
|
||||
|
@ -123,10 +123,9 @@ use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::codemap::original_sp;
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{BytePos, Span};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use hir::Expr;
|
||||
use hir;
|
||||
@ -187,7 +186,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String {
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: NodeId) {
|
||||
visit_fn(self, fk, fd, b, s, id);
|
||||
}
|
||||
fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); }
|
||||
@ -352,9 +351,9 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, n: NodeId) {
|
||||
check_fn(self, fk, fd, b, s, n);
|
||||
fn visit_fn(&mut self, _: FnKind<'v>, _: &'v hir::FnDecl,
|
||||
_: &'v hir::Expr, _: Span, _: NodeId) {
|
||||
// do not check contents of nested fns
|
||||
}
|
||||
fn visit_local(&mut self, l: &hir::Local) {
|
||||
check_local(self, l);
|
||||
@ -370,7 +369,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> {
|
||||
fn visit_fn(ir: &mut IrMaps,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
debug!("visit_fn");
|
||||
@ -405,10 +404,10 @@ fn visit_fn(ir: &mut IrMaps,
|
||||
|
||||
// compute liveness
|
||||
let mut lsets = Liveness::new(&mut fn_maps, specials);
|
||||
let entry_ln = lsets.compute(decl, body);
|
||||
let entry_ln = lsets.compute(body);
|
||||
|
||||
// check for various error conditions
|
||||
lsets.visit_block(body);
|
||||
lsets.visit_expr(body);
|
||||
lsets.check_ret(id, sp, fk, entry_ln, body);
|
||||
lsets.warn_about_unused_args(decl, entry_ln);
|
||||
}
|
||||
@ -821,17 +820,23 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
// _______________________________________________________________________
|
||||
|
||||
fn compute(&mut self, decl: &hir::FnDecl, body: &hir::Block) -> LiveNode {
|
||||
fn compute(&mut self, body: &hir::Expr) -> LiveNode {
|
||||
// if there is a `break` or `again` at the top level, then it's
|
||||
// effectively a return---this only occurs in `for` loops,
|
||||
// where the body is really a closure.
|
||||
|
||||
debug!("compute: using id for block, {}", block_to_string(body));
|
||||
debug!("compute: using id for body, {}", expr_to_string(body));
|
||||
|
||||
let exit_ln = self.s.exit_ln;
|
||||
let entry_ln: LiveNode =
|
||||
self.with_loop_nodes(body.id, exit_ln, exit_ln,
|
||||
|this| this.propagate_through_fn_block(decl, body));
|
||||
let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| {
|
||||
// the fallthrough exit is only for those cases where we do not
|
||||
// explicitly return:
|
||||
let s = this.s;
|
||||
this.init_from_succ(s.fallthrough_ln, s.exit_ln);
|
||||
this.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
|
||||
|
||||
this.propagate_through_expr(body, s.fallthrough_ln)
|
||||
});
|
||||
|
||||
// hack to skip the loop unless debug! is enabled:
|
||||
debug!("^^ liveness computation results for body {} (entry={:?})",
|
||||
@ -846,20 +851,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
entry_ln
|
||||
}
|
||||
|
||||
fn propagate_through_fn_block(&mut self, _: &hir::FnDecl, blk: &hir::Block)
|
||||
-> LiveNode {
|
||||
// the fallthrough exit is only for those cases where we do not
|
||||
// explicitly return:
|
||||
let s = self.s;
|
||||
self.init_from_succ(s.fallthrough_ln, s.exit_ln);
|
||||
if blk.expr.is_none() {
|
||||
self.acc(s.fallthrough_ln, s.no_ret_var, ACC_READ)
|
||||
}
|
||||
self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
|
||||
|
||||
self.propagate_through_block(blk, s.fallthrough_ln)
|
||||
}
|
||||
|
||||
fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
|
||||
-> LiveNode {
|
||||
let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
|
||||
@ -1448,15 +1439,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fn(_v: &Liveness,
|
||||
_fk: FnKind,
|
||||
_decl: &hir::FnDecl,
|
||||
_body: &hir::Block,
|
||||
_sp: Span,
|
||||
_id: NodeId) {
|
||||
// do not check contents of nested fns
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
fn fn_ret(&self, id: NodeId) -> ty::Binder<Ty<'tcx>> {
|
||||
let fn_ty = self.ir.tcx.tables().node_id_to_type(id);
|
||||
@ -1472,7 +1454,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
sp: Span,
|
||||
_fk: FnKind,
|
||||
entry_ln: LiveNode,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
{
|
||||
// within the fn body, late-bound regions are liberated
|
||||
// and must outlive the *call-site* of the function.
|
||||
@ -1481,13 +1463,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
self.ir.tcx.region_maps.call_site_extent(id, body.id),
|
||||
&self.fn_ret(id));
|
||||
|
||||
if fn_ret.is_never() {
|
||||
// FIXME(durka) this rejects code like `fn foo(x: !) -> ! { x }`
|
||||
if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() {
|
||||
span_err!(self.ir.tcx.sess, sp, E0270,
|
||||
"computation may converge in a function marked as diverging");
|
||||
}
|
||||
} else if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
|
||||
if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
|
||||
let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
|
||||
let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs);
|
||||
let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env),
|
||||
@ -1498,32 +1474,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
// for nil return types, it is ok to not return a value expl.
|
||||
if !is_nil {
|
||||
let ends_with_stmt = match body.expr {
|
||||
None if !body.stmts.is_empty() =>
|
||||
match body.stmts.last().unwrap().node {
|
||||
hir::StmtSemi(ref e, _) => {
|
||||
self.ir.tcx.tables().expr_ty(&e) == fn_ret
|
||||
},
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
let mut err = struct_span_err!(self.ir.tcx.sess,
|
||||
sp,
|
||||
E0269,
|
||||
"not all control paths return a value");
|
||||
if ends_with_stmt {
|
||||
let last_stmt = body.stmts.last().unwrap();
|
||||
let original_span = original_sp(self.ir.tcx.sess.codemap(),
|
||||
last_stmt.span, sp);
|
||||
let span_semicolon = Span {
|
||||
lo: original_span.hi - BytePos(1),
|
||||
hi: original_span.hi,
|
||||
expn_id: original_span.expn_id
|
||||
};
|
||||
err.span_help(span_semicolon, "consider removing this semicolon:");
|
||||
}
|
||||
err.emit();
|
||||
span_bug!(sp, "not all control paths return a value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +248,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
match *node {
|
||||
ast_map::NodeItem(item) => {
|
||||
match item.node {
|
||||
hir::ItemFn(.., ref search_block) => {
|
||||
hir::ItemFn(.., ref body) => {
|
||||
if item_might_be_inlined(&item) {
|
||||
intravisit::walk_block(self, &search_block)
|
||||
self.visit_expr(body);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,11 +278,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
hir::MethodTraitItem(_, None) => {
|
||||
// Keep going, nothing to get exported
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref expr)) => {
|
||||
self.visit_expr(&expr);
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref body)) |
|
||||
hir::MethodTraitItem(_, Some(ref body)) => {
|
||||
intravisit::walk_block(self, body);
|
||||
self.visit_expr(body);
|
||||
}
|
||||
hir::TypeTraitItem(..) => {}
|
||||
}
|
||||
@ -295,7 +293,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
let did = self.tcx.map.get_parent_did(search_item);
|
||||
if method_might_be_inlined(self.tcx, sig, impl_item, did) {
|
||||
intravisit::walk_block(self, body)
|
||||
self.visit_expr(body)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {}
|
||||
|
@ -490,12 +490,7 @@ impl RegionMaps {
|
||||
// if there's one. Static items, for instance, won't
|
||||
// have an enclosing scope, hence no scope will be
|
||||
// returned.
|
||||
let expr_extent = self.node_extent(expr_id);
|
||||
// For some reason, the expr's scope itself is skipped here.
|
||||
let mut id = match scope_map[expr_extent.0 as usize].into_option() {
|
||||
Some(i) => i,
|
||||
_ => return None
|
||||
};
|
||||
let mut id = self.node_extent(expr_id);
|
||||
|
||||
while let Some(p) = scope_map[id.0 as usize].into_option() {
|
||||
match code_extents[p.0 as usize] {
|
||||
@ -1086,7 +1081,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) {
|
||||
fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
||||
kind: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
debug!("region::resolve_fn(id={:?}, \
|
||||
@ -1128,7 +1123,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
||||
parent: fn_decl_scope,
|
||||
var_parent: fn_decl_scope
|
||||
};
|
||||
visitor.visit_block(body);
|
||||
visitor.visit_expr(body);
|
||||
|
||||
// Restore context we had at the start.
|
||||
visitor.cx = outer_cx;
|
||||
@ -1191,7 +1186,7 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
|
||||
b: &'v Block, s: Span, n: NodeId) {
|
||||
b: &'v Expr, s: Span, n: NodeId) {
|
||||
resolve_fn(self, fk, fd, b, s, n);
|
||||
}
|
||||
fn visit_arm(&mut self, a: &Arm) {
|
||||
|
@ -202,7 +202,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, fn_id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::ItemFn(_, generics, ..) => {
|
||||
self.visit_early_late(fn_id,decl, generics, |this| {
|
||||
@ -403,7 +403,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
|
||||
|
||||
// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
|
||||
// if one of the label shadows a lifetime or another label.
|
||||
fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) {
|
||||
fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) {
|
||||
struct GatherLabels<'a> {
|
||||
sess: &'a Session,
|
||||
scope: Scope<'a>,
|
||||
@ -415,7 +415,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) {
|
||||
scope: ctxt.scope,
|
||||
labels_in_fn: &mut ctxt.labels_in_fn,
|
||||
};
|
||||
gather.visit_block(b);
|
||||
gather.visit_expr(b);
|
||||
return;
|
||||
|
||||
impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
|
||||
@ -493,7 +493,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
fn add_scope_and_walk_fn<'b>(&mut self,
|
||||
fk: FnKind,
|
||||
fd: &hir::FnDecl,
|
||||
fb: &'b hir::Block,
|
||||
fb: &'b hir::Expr,
|
||||
_span: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
|
||||
@ -516,7 +516,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
extract_labels(self, fb);
|
||||
|
||||
self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope },
|
||||
|_old_scope, this| this.visit_block(fb))
|
||||
|_old_scope, this| this.visit_expr(fb))
|
||||
}
|
||||
|
||||
fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
|
||||
|
@ -529,14 +529,11 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// items.
|
||||
hir::ItemImpl(.., Some(ref t), _, ref impl_items) => {
|
||||
let trait_did = tcx.expect_def(t.ref_id).def_id();
|
||||
let trait_items = tcx.trait_items(trait_did);
|
||||
|
||||
for impl_item in impl_items {
|
||||
let item = trait_items.iter().find(|item| {
|
||||
item.name() == impl_item.name
|
||||
}).unwrap();
|
||||
let item = tcx.associated_items(trait_did)
|
||||
.find(|item| item.name == impl_item.name).unwrap();
|
||||
if warn_about_defns {
|
||||
maybe_do_stability_check(tcx, item.def_id(), impl_item.span, cb);
|
||||
maybe_do_stability_check(tcx, item.def_id, impl_item.span, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -685,15 +682,8 @@ fn is_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) -> bool {
|
||||
}
|
||||
|
||||
fn is_staged_api<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> bool {
|
||||
match tcx.trait_item_of_item(id) {
|
||||
Some(trait_method_id) if trait_method_id != id => {
|
||||
is_staged_api(tcx, trait_method_id)
|
||||
}
|
||||
_ => {
|
||||
*tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
|
||||
|| tcx.sess.cstore.is_staged_api(id.krate))
|
||||
}
|
||||
}
|
||||
*tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
|
||||
|| tcx.sess.cstore.is_staged_api(id.krate))
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
|
@ -663,25 +663,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
in the supertrait listing"
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
ObjectSafetyViolation::Method(name,
|
||||
MethodViolationCode::StaticMethod) => {
|
||||
buf = format!("method `{}` has no receiver",
|
||||
method.name);
|
||||
buf = format!("method `{}` has no receiver", name);
|
||||
&buf
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
ObjectSafetyViolation::Method(name,
|
||||
MethodViolationCode::ReferencesSelf) => {
|
||||
buf = format!("method `{}` references the `Self` type \
|
||||
in its arguments or return type",
|
||||
method.name);
|
||||
name);
|
||||
&buf
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
ObjectSafetyViolation::Method(name,
|
||||
MethodViolationCode::Generic) => {
|
||||
buf = format!("method `{}` has generic type parameters",
|
||||
method.name);
|
||||
buf = format!("method `{}` has generic type parameters", name);
|
||||
&buf
|
||||
}
|
||||
};
|
||||
|
@ -578,18 +578,14 @@ pub fn get_vtable_methods<'a, 'tcx>(
|
||||
supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
|
||||
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
|
||||
|
||||
let trait_item_def_ids = tcx.impl_or_trait_items(trait_ref.def_id());
|
||||
let trait_methods = (0..trait_item_def_ids.len()).filter_map(move |i| {
|
||||
match tcx.impl_or_trait_item(trait_item_def_ids[i]) {
|
||||
ty::MethodTraitItem(m) => Some(m),
|
||||
_ => None
|
||||
}
|
||||
});
|
||||
let trait_methods = tcx.associated_items(trait_ref.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Method);
|
||||
|
||||
// Now list each method's DefId and Substs (for within its trait).
|
||||
// If the method can never be called from this object, produce None.
|
||||
trait_methods.map(move |trait_method| {
|
||||
debug!("get_vtable_methods: trait_method={:?}", trait_method);
|
||||
let def_id = trait_method.def_id;
|
||||
|
||||
// Some methods cannot be called on an object; skip those.
|
||||
if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) {
|
||||
@ -599,21 +595,21 @@ pub fn get_vtable_methods<'a, 'tcx>(
|
||||
|
||||
// the method may have some early-bound lifetimes, add
|
||||
// regions for those
|
||||
let substs = Substs::for_item(tcx, trait_method.def_id,
|
||||
|_, _| tcx.mk_region(ty::ReErased),
|
||||
|def, _| trait_ref.substs().type_for_def(def));
|
||||
let substs = Substs::for_item(tcx, def_id,
|
||||
|_, _| tcx.mk_region(ty::ReErased),
|
||||
|def, _| trait_ref.substs().type_for_def(def));
|
||||
|
||||
// It's possible that the method relies on where clauses that
|
||||
// do not hold for this particular set of type parameters.
|
||||
// Note that this method could then never be called, so we
|
||||
// do not want to try and trans it, in that case (see #23435).
|
||||
let predicates = trait_method.predicates.instantiate_own(tcx, substs);
|
||||
let predicates = tcx.lookup_predicates(def_id).instantiate_own(tcx, substs);
|
||||
if !normalize_and_test_predicates(tcx, predicates.predicates) {
|
||||
debug!("get_vtable_methods: predicates do not hold");
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((trait_method.def_id, substs))
|
||||
Some((def_id, substs))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -22,11 +22,10 @@ use super::elaborate_predicates;
|
||||
use hir::def_id::DefId;
|
||||
use traits;
|
||||
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ObjectSafetyViolation<'tcx> {
|
||||
pub enum ObjectSafetyViolation {
|
||||
/// Self : Sized declared on the trait
|
||||
SizedSelf,
|
||||
|
||||
@ -35,7 +34,7 @@ pub enum ObjectSafetyViolation<'tcx> {
|
||||
SupertraitSelf,
|
||||
|
||||
/// Method has something illegal
|
||||
Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
|
||||
Method(ast::Name, MethodViolationCode),
|
||||
}
|
||||
|
||||
/// Reasons a method might not be object-safe.
|
||||
@ -77,7 +76,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// because `object_safety_violations` can't be used during
|
||||
/// type collection.
|
||||
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
|
||||
-> Vec<ObjectSafetyViolation<'tcx>>
|
||||
-> Vec<ObjectSafetyViolation>
|
||||
{
|
||||
let mut violations = vec![];
|
||||
|
||||
@ -93,7 +92,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn object_safety_violations(self, trait_def_id: DefId)
|
||||
-> Vec<ObjectSafetyViolation<'tcx>>
|
||||
-> Vec<ObjectSafetyViolation>
|
||||
{
|
||||
traits::supertrait_def_ids(self, trait_def_id)
|
||||
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
|
||||
@ -101,21 +100,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn object_safety_violations_for_trait(self, trait_def_id: DefId)
|
||||
-> Vec<ObjectSafetyViolation<'tcx>>
|
||||
-> Vec<ObjectSafetyViolation>
|
||||
{
|
||||
// Check methods for violations.
|
||||
let mut violations: Vec<_> =
|
||||
self.trait_items(trait_def_id).iter()
|
||||
let mut violations: Vec<_> = self.associated_items(trait_def_id)
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Method)
|
||||
.filter_map(|item| {
|
||||
match *item {
|
||||
ty::MethodTraitItem(ref m) => {
|
||||
self.object_safety_violation_for_method(trait_def_id, &m)
|
||||
.map(|code| ObjectSafetyViolation::Method(m.clone(), code))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
self.object_safety_violation_for_method(trait_def_id, &item)
|
||||
.map(|code| ObjectSafetyViolation::Method(item.name, code))
|
||||
}).collect();
|
||||
|
||||
// Check the trait itself.
|
||||
if self.trait_has_sized_self(trait_def_id) {
|
||||
@ -198,7 +191,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// Returns `Some(_)` if this method makes the containing trait not object safe.
|
||||
fn object_safety_violation_for_method(self,
|
||||
trait_def_id: DefId,
|
||||
method: &ty::Method<'gcx>)
|
||||
method: &ty::AssociatedItem)
|
||||
-> Option<MethodViolationCode>
|
||||
{
|
||||
// Any method that has a `Self : Sized` requisite is otherwise
|
||||
@ -216,7 +209,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// otherwise ensure that they cannot be used when `Self=Trait`.
|
||||
pub fn is_vtable_safe_method(self,
|
||||
trait_def_id: DefId,
|
||||
method: &ty::Method<'gcx>)
|
||||
method: &ty::AssociatedItem)
|
||||
-> bool
|
||||
{
|
||||
// Any method that has a `Self : Sized` requisite can't be called.
|
||||
@ -233,26 +226,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// `Self:Sized`.
|
||||
fn virtual_call_violation_for_method(self,
|
||||
trait_def_id: DefId,
|
||||
method: &ty::Method<'tcx>)
|
||||
method: &ty::AssociatedItem)
|
||||
-> Option<MethodViolationCode>
|
||||
{
|
||||
// The method's first parameter must be something that derefs (or
|
||||
// autorefs) to `&self`. For now, we only accept `self`, `&self`
|
||||
// and `Box<Self>`.
|
||||
match method.explicit_self {
|
||||
ty::ExplicitSelfCategory::Static => {
|
||||
return Some(MethodViolationCode::StaticMethod);
|
||||
}
|
||||
|
||||
ty::ExplicitSelfCategory::ByValue |
|
||||
ty::ExplicitSelfCategory::ByReference(..) |
|
||||
ty::ExplicitSelfCategory::ByBox => {
|
||||
}
|
||||
if !method.method_has_self_argument {
|
||||
return Some(MethodViolationCode::StaticMethod);
|
||||
}
|
||||
|
||||
// The `Self` type is erased, so it should not appear in list of
|
||||
// arguments or return type apart from the receiver.
|
||||
let ref sig = method.fty.sig;
|
||||
let ref sig = self.lookup_item_type(method.def_id).ty.fn_sig();
|
||||
for &input_ty in &sig.0.inputs[1..] {
|
||||
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
|
||||
return Some(MethodViolationCode::ReferencesSelf);
|
||||
@ -263,7 +249,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// We can't monomorphize things like `fn foo<A>(...)`.
|
||||
if !method.generics.types.is_empty() {
|
||||
if !self.lookup_generics(method.def_id).types.is_empty() {
|
||||
return Some(MethodViolationCode::Generic);
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,6 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
|
||||
use ty::fold::{TypeFoldable, TypeFolder};
|
||||
use util::common::FN_OUTPUT_NAME;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Depending on the stage of compilation, we want projection to be
|
||||
/// more or less conservative.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
@ -945,7 +943,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
|
||||
// an error when we confirm the candidate
|
||||
// (which will ultimately lead to `normalize_to_error`
|
||||
// being invoked).
|
||||
node_item.item.ty.is_some()
|
||||
node_item.item.has_value
|
||||
} else {
|
||||
node_item.item.defaultness.is_default()
|
||||
};
|
||||
@ -1305,7 +1303,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
|
||||
|
||||
match assoc_ty {
|
||||
Some(node_item) => {
|
||||
let ty = node_item.item.ty.unwrap_or_else(|| {
|
||||
let ty = if !node_item.item.has_value {
|
||||
// This means that the impl is missing a definition for the
|
||||
// associated type. This error will be reported by the type
|
||||
// checker method `check_impl_items_against_trait`, so here we
|
||||
@ -1314,7 +1312,9 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
|
||||
node_item.item.name,
|
||||
obligation.predicate.trait_ref);
|
||||
tcx.types.err
|
||||
});
|
||||
} else {
|
||||
tcx.lookup_item_type(node_item.item.def_id).ty
|
||||
};
|
||||
let substs = translate_substs(selcx.infcx(), impl_def_id, substs, node_item.node);
|
||||
Progress {
|
||||
ty: ty.subst(tcx, substs),
|
||||
@ -1339,27 +1339,25 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
|
||||
selcx: &SelectionContext<'cx, 'gcx, 'tcx>,
|
||||
impl_def_id: DefId,
|
||||
assoc_ty_name: ast::Name)
|
||||
-> Option<specialization_graph::NodeItem<Rc<ty::AssociatedType<'tcx>>>>
|
||||
-> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
|
||||
{
|
||||
let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
|
||||
|
||||
if selcx.projection_mode() == Reveal::ExactMatch {
|
||||
let impl_node = specialization_graph::Node::Impl(impl_def_id);
|
||||
for item in impl_node.items(selcx.tcx()) {
|
||||
if let ty::TypeTraitItem(assoc_ty) = item {
|
||||
if assoc_ty.name == assoc_ty_name {
|
||||
return Some(specialization_graph::NodeItem {
|
||||
node: specialization_graph::Node::Impl(impl_def_id),
|
||||
item: assoc_ty,
|
||||
});
|
||||
}
|
||||
if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
|
||||
return Some(specialization_graph::NodeItem {
|
||||
node: specialization_graph::Node::Impl(impl_def_id),
|
||||
item: item,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
} else {
|
||||
selcx.tcx().lookup_trait_def(trait_def_id)
|
||||
.ancestors(impl_def_id)
|
||||
.type_defs(selcx.tcx(), assoc_ty_name)
|
||||
.defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,8 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||
let trait_def = tcx.lookup_trait_def(trait_def_id);
|
||||
|
||||
match trait_def.ancestors(impl_data.impl_def_id).fn_defs(tcx, name).next() {
|
||||
let ancestors = trait_def.ancestors(impl_data.impl_def_id);
|
||||
match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() {
|
||||
Some(node_item) => {
|
||||
let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
|
@ -8,13 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{OverlapError, specializes};
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use traits::{self, Reveal};
|
||||
use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable};
|
||||
use ty::{self, TyCtxt, TraitDef, TypeFoldable};
|
||||
use ty::fast_reject::{self, SimplifiedType};
|
||||
use syntax::ast::Name;
|
||||
use util::nodemap::{DefIdMap, FxHashMap};
|
||||
@ -285,12 +283,10 @@ impl<'a, 'gcx, 'tcx> Node {
|
||||
}
|
||||
|
||||
/// Iterate over the items defined directly by the given (impl or trait) node.
|
||||
pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeItems<'a, 'gcx> {
|
||||
NodeItems {
|
||||
tcx: tcx.global_tcx(),
|
||||
items: tcx.impl_or_trait_items(self.def_id()),
|
||||
idx: 0,
|
||||
}
|
||||
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
|
||||
pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> impl Iterator<Item = ty::AssociatedItem> + 'a {
|
||||
tcx.associated_items(self.def_id())
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> DefId {
|
||||
@ -301,28 +297,6 @@ impl<'a, 'gcx, 'tcx> Node {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the items defined within a trait or impl.
|
||||
pub struct NodeItems<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
items: Rc<Vec<DefId>>,
|
||||
idx: usize
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> {
|
||||
type Item = ImplOrTraitItem<'tcx>;
|
||||
fn next(&mut self) -> Option<ImplOrTraitItem<'tcx>> {
|
||||
if self.idx < self.items.len() {
|
||||
let item_def_id = self.items[self.idx];
|
||||
let items_table = self.tcx.impl_or_trait_items.borrow();
|
||||
let item = items_table[&item_def_id].clone();
|
||||
self.idx += 1;
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Ancestors<'a, 'tcx: 'a> {
|
||||
trait_def: &'a TraitDef<'tcx>,
|
||||
current_source: Option<Node>,
|
||||
@ -358,104 +332,16 @@ impl<T> NodeItem<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TypeDefs<'a, 'tcx: 'a> {
|
||||
// generally only invoked once or twice, so the box doesn't hurt
|
||||
iter: Box<Iterator<Item = NodeItem<Rc<ty::AssociatedType<'tcx>>>> + 'a>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for TypeDefs<'a, 'tcx> {
|
||||
type Item = NodeItem<Rc<ty::AssociatedType<'tcx>>>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnDefs<'a, 'tcx: 'a> {
|
||||
// generally only invoked once or twice, so the box doesn't hurt
|
||||
iter: Box<Iterator<Item = NodeItem<Rc<ty::Method<'tcx>>>> + 'a>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for FnDefs<'a, 'tcx> {
|
||||
type Item = NodeItem<Rc<ty::Method<'tcx>>>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConstDefs<'a, 'tcx: 'a> {
|
||||
// generally only invoked once or twice, so the box doesn't hurt
|
||||
iter: Box<Iterator<Item = NodeItem<Rc<ty::AssociatedConst<'tcx>>>> + 'a>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for ConstDefs<'a, 'tcx> {
|
||||
type Item = NodeItem<Rc<ty::AssociatedConst<'tcx>>>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Ancestors<'a, 'tcx> {
|
||||
/// Search the items from the given ancestors, returning each type definition
|
||||
/// with the given name.
|
||||
pub fn type_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> TypeDefs<'a, 'gcx> {
|
||||
let iter = self.flat_map(move |node| {
|
||||
node.items(tcx)
|
||||
.filter_map(move |item| {
|
||||
if let ty::TypeTraitItem(assoc_ty) = item {
|
||||
if assoc_ty.name == name {
|
||||
return Some(NodeItem {
|
||||
node: node,
|
||||
item: assoc_ty,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
|
||||
});
|
||||
TypeDefs { iter: Box::new(iter) }
|
||||
}
|
||||
|
||||
/// Search the items from the given ancestors, returning each fn definition
|
||||
/// with the given name.
|
||||
pub fn fn_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> FnDefs<'a, 'gcx> {
|
||||
let iter = self.flat_map(move |node| {
|
||||
node.items(tcx)
|
||||
.filter_map(move |item| {
|
||||
if let ty::MethodTraitItem(method) = item {
|
||||
if method.name == name {
|
||||
return Some(NodeItem {
|
||||
node: node,
|
||||
item: method,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
|
||||
});
|
||||
FnDefs { iter: Box::new(iter) }
|
||||
}
|
||||
|
||||
/// Search the items from the given ancestors, returning each const
|
||||
/// definition with the given name.
|
||||
pub fn const_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> ConstDefs<'a, 'gcx> {
|
||||
let iter = self.flat_map(move |node| {
|
||||
node.items(tcx)
|
||||
.filter_map(move |item| {
|
||||
if let ty::ConstTraitItem(konst) = item {
|
||||
if konst.name == name {
|
||||
return Some(NodeItem {
|
||||
node: node,
|
||||
item: konst,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
|
||||
});
|
||||
ConstDefs { iter: Box::new(iter) }
|
||||
/// Search the items from the given ancestors, returning each definition
|
||||
/// with the given name and the given kind.
|
||||
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
|
||||
pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name, kind: ty::AssociatedKind)
|
||||
-> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + 'a {
|
||||
self.flat_map(move |node| {
|
||||
node.items(tcx).filter(move |item| item.kind == kind && item.name == name)
|
||||
.map(move |item| NodeItem { node: node, item: item })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,8 +477,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
let mut entries = 0;
|
||||
// Count number of methods and add them to the total offset.
|
||||
// Skip over associated types and constants.
|
||||
for trait_item in &self.trait_items(trait_ref.def_id())[..] {
|
||||
if let ty::MethodTraitItem(_) = *trait_item {
|
||||
for trait_item in self.associated_items(trait_ref.def_id()) {
|
||||
if trait_item.kind == ty::AssociatedKind::Method {
|
||||
entries += 1;
|
||||
}
|
||||
}
|
||||
@ -495,17 +495,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// add them to the total offset.
|
||||
// Skip over associated types and constants.
|
||||
let mut entries = object.vtable_base;
|
||||
for trait_item in &self.trait_items(object.upcast_trait_ref.def_id())[..] {
|
||||
if trait_item.def_id() == method_def_id {
|
||||
for trait_item in self.associated_items(object.upcast_trait_ref.def_id()) {
|
||||
if trait_item.def_id == method_def_id {
|
||||
// The item with the ID we were given really ought to be a method.
|
||||
assert!(match *trait_item {
|
||||
ty::MethodTraitItem(_) => true,
|
||||
_ => false
|
||||
});
|
||||
|
||||
assert_eq!(trait_item.kind, ty::AssociatedKind::Method);
|
||||
return entries;
|
||||
}
|
||||
if let ty::MethodTraitItem(_) = *trait_item {
|
||||
if trait_item.kind == ty::AssociatedKind::Method {
|
||||
entries += 1;
|
||||
}
|
||||
}
|
||||
|
@ -403,14 +403,10 @@ pub struct GlobalCtxt<'tcx> {
|
||||
pub tables: RefCell<Tables<'tcx>>,
|
||||
|
||||
/// Maps from a trait item to the trait item "descriptor"
|
||||
pub impl_or_trait_items: RefCell<DepTrackingMap<maps::ImplOrTraitItems<'tcx>>>,
|
||||
pub associated_items: RefCell<DepTrackingMap<maps::AssociatedItems<'tcx>>>,
|
||||
|
||||
/// Maps from an impl/trait def-id to a list of the def-ids of its items
|
||||
pub impl_or_trait_item_def_ids: RefCell<DepTrackingMap<maps::ImplOrTraitItemDefIds<'tcx>>>,
|
||||
|
||||
/// A cache for the trait_items() routine; note that the routine
|
||||
/// itself pushes the `TraitItems` dependency node.
|
||||
trait_items_cache: RefCell<DepTrackingMap<maps::TraitItems<'tcx>>>,
|
||||
pub associated_item_def_ids: RefCell<DepTrackingMap<maps::AssociatedItemDefIds<'tcx>>>,
|
||||
|
||||
pub impl_trait_refs: RefCell<DepTrackingMap<maps::ImplTraitRefs<'tcx>>>,
|
||||
pub trait_defs: RefCell<DepTrackingMap<maps::TraitDefs<'tcx>>>,
|
||||
@ -822,9 +818,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
rcache: RefCell::new(FxHashMap()),
|
||||
tc_cache: RefCell::new(FxHashMap()),
|
||||
impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
impl_or_trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
ty_param_defs: RefCell::new(NodeMap()),
|
||||
normalized_cache: RefCell::new(FxHashMap()),
|
||||
lang_items: lang_items,
|
||||
@ -1539,15 +1534,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
|
||||
}
|
||||
|
||||
pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
|
||||
self.trait_items_cache.memoize(trait_did, || {
|
||||
let def_ids = self.impl_or_trait_items(trait_did);
|
||||
Rc::new(def_ids.iter()
|
||||
.map(|&def_id| self.impl_or_trait_item(def_id))
|
||||
.collect())
|
||||
})
|
||||
}
|
||||
|
||||
/// Obtain the representation annotation for a struct definition.
|
||||
pub fn lookup_repr_hints(self, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
|
||||
self.repr_hint_cache.memoize(did, || {
|
||||
|
@ -16,7 +16,7 @@ use ty::{self, Ty};
|
||||
use std::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use syntax::{attr, ast};
|
||||
use syntax::attr;
|
||||
|
||||
macro_rules! dep_map_ty {
|
||||
($ty_name:ident : $node_name:ident ($key:ty) -> $value:ty) => {
|
||||
@ -32,18 +32,16 @@ macro_rules! dep_map_ty {
|
||||
}
|
||||
}
|
||||
|
||||
dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> }
|
||||
dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem }
|
||||
dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> }
|
||||
dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
|
||||
dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
|
||||
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
|
||||
dep_map_ty! { ImplOrTraitItemDefIds: ImplOrTraitItemDefIds(DefId) -> Rc<Vec<DefId>> }
|
||||
dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>> }
|
||||
dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>> }
|
||||
dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> }
|
||||
dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
|
||||
dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
|
||||
dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
|
||||
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
|
||||
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
|
||||
dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }
|
||||
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
pub use self::Variance::*;
|
||||
pub use self::DtorKind::*;
|
||||
pub use self::ImplOrTraitItemContainer::*;
|
||||
pub use self::AssociatedItemContainer::*;
|
||||
pub use self::BorrowKind::*;
|
||||
pub use self::ImplOrTraitItem::*;
|
||||
pub use self::IntVarValue::*;
|
||||
pub use self::LvaluePreference::*;
|
||||
pub use self::fold::TypeFoldable;
|
||||
@ -135,12 +134,12 @@ impl DtorKind {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum ImplOrTraitItemContainer {
|
||||
pub enum AssociatedItemContainer {
|
||||
TraitContainer(DefId),
|
||||
ImplContainer(DefId),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItemContainer {
|
||||
impl AssociatedItemContainer {
|
||||
pub fn id(&self) -> DefId {
|
||||
match *self {
|
||||
TraitContainer(id) => id,
|
||||
@ -183,58 +182,34 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ImplOrTraitItem<'tcx> {
|
||||
ConstTraitItem(Rc<AssociatedConst<'tcx>>),
|
||||
MethodTraitItem(Rc<Method<'tcx>>),
|
||||
TypeTraitItem(Rc<AssociatedType<'tcx>>),
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct AssociatedItem {
|
||||
pub def_id: DefId,
|
||||
pub name: Name,
|
||||
pub kind: AssociatedKind,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub has_value: bool,
|
||||
pub container: AssociatedItemContainer,
|
||||
|
||||
/// Whether this is a method with an explicit self
|
||||
/// as its first argument, allowing method calls.
|
||||
pub method_has_self_argument: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> ImplOrTraitItem<'tcx> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum AssociatedKind {
|
||||
Const,
|
||||
Method,
|
||||
Type
|
||||
}
|
||||
|
||||
impl AssociatedItem {
|
||||
pub fn def(&self) -> Def {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id),
|
||||
MethodTraitItem(ref method) => Def::Method(method.def_id),
|
||||
TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> DefId {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.def_id,
|
||||
MethodTraitItem(ref method) => method.def_id,
|
||||
TypeTraitItem(ref associated_type) => associated_type.def_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Name {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.name,
|
||||
MethodTraitItem(ref method) => method.name,
|
||||
TypeTraitItem(ref associated_type) => associated_type.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vis(&self) -> Visibility {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.vis,
|
||||
MethodTraitItem(ref method) => method.vis,
|
||||
TypeTraitItem(ref associated_type) => associated_type.vis,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container(&self) -> ImplOrTraitItemContainer {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.container,
|
||||
MethodTraitItem(ref method) => method.container,
|
||||
TypeTraitItem(ref associated_type) => associated_type.container,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
|
||||
match *self {
|
||||
MethodTraitItem(ref m) => Some((*m).clone()),
|
||||
_ => None,
|
||||
match self.kind {
|
||||
AssociatedKind::Const => Def::AssociatedConst(self.def_id),
|
||||
AssociatedKind::Method => Def::Method(self.def_id),
|
||||
AssociatedKind::Type => Def::AssociatedTy(self.def_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -308,64 +283,6 @@ impl Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Method<'tcx> {
|
||||
pub name: Name,
|
||||
pub generics: &'tcx Generics<'tcx>,
|
||||
pub predicates: GenericPredicates<'tcx>,
|
||||
pub fty: &'tcx BareFnTy<'tcx>,
|
||||
pub explicit_self: ExplicitSelfCategory<'tcx>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub has_body: bool,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
}
|
||||
|
||||
impl<'tcx> Method<'tcx> {
|
||||
pub fn container_id(&self) -> DefId {
|
||||
match self.container {
|
||||
TraitContainer(id) => id,
|
||||
ImplContainer(id) => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PartialEq for Method<'tcx> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id }
|
||||
}
|
||||
|
||||
impl<'tcx> Eq for Method<'tcx> {}
|
||||
|
||||
impl<'tcx> Hash for Method<'tcx> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
self.def_id.hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AssociatedConst<'tcx> {
|
||||
pub name: Name,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
pub has_value: bool
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AssociatedType<'tcx> {
|
||||
pub name: Name,
|
||||
pub ty: Option<Ty<'tcx>>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
|
||||
pub enum Variance {
|
||||
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
|
||||
@ -1288,19 +1205,10 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
||||
tcx.region_maps.item_extent(id))
|
||||
}
|
||||
hir::ImplItemKind::Method(_, ref body) => {
|
||||
let method_def_id = tcx.map.local_def_id(id);
|
||||
match tcx.impl_or_trait_item(method_def_id) {
|
||||
MethodTraitItem(ref method_ty) => {
|
||||
tcx.construct_parameter_environment(
|
||||
impl_item.span,
|
||||
method_ty.def_id,
|
||||
tcx.region_maps.call_site_extent(id, body.id))
|
||||
}
|
||||
_ => {
|
||||
bug!("ParameterEnvironment::for_item(): \
|
||||
got non-method item from impl method?!")
|
||||
}
|
||||
}
|
||||
tcx.construct_parameter_environment(
|
||||
impl_item.span,
|
||||
tcx.map.local_def_id(id),
|
||||
tcx.region_maps.call_site_extent(id, body.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1319,27 +1227,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
||||
// Use call-site for extent (unless this is a
|
||||
// trait method with no default; then fallback
|
||||
// to the method id).
|
||||
let method_def_id = tcx.map.local_def_id(id);
|
||||
match tcx.impl_or_trait_item(method_def_id) {
|
||||
MethodTraitItem(ref method_ty) => {
|
||||
let extent = if let Some(ref body) = *body {
|
||||
// default impl: use call_site extent as free_id_outlive bound.
|
||||
tcx.region_maps.call_site_extent(id, body.id)
|
||||
} else {
|
||||
// no default impl: use item extent as free_id_outlive bound.
|
||||
tcx.region_maps.item_extent(id)
|
||||
};
|
||||
tcx.construct_parameter_environment(
|
||||
trait_item.span,
|
||||
method_ty.def_id,
|
||||
extent)
|
||||
}
|
||||
_ => {
|
||||
bug!("ParameterEnvironment::for_item(): \
|
||||
got non-method item from provided \
|
||||
method?!")
|
||||
}
|
||||
}
|
||||
let extent = if let Some(ref body) = *body {
|
||||
// default impl: use call_site extent as free_id_outlive bound.
|
||||
tcx.region_maps.call_site_extent(id, body.id)
|
||||
} else {
|
||||
// no default impl: use item extent as free_id_outlive bound.
|
||||
tcx.region_maps.item_extent(id)
|
||||
};
|
||||
tcx.construct_parameter_environment(
|
||||
trait_item.span,
|
||||
tcx.map.local_def_id(id),
|
||||
extent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2065,7 +1963,7 @@ impl LvaluePreference {
|
||||
}
|
||||
|
||||
/// Helper for looking things up in the various maps that are populated during
|
||||
/// typeck::collect (e.g., `tcx.impl_or_trait_items`, `tcx.tcache`, etc). All of
|
||||
/// typeck::collect (e.g., `tcx.associated_items`, `tcx.tcache`, etc). All of
|
||||
/// these share the pattern that if the id is local, it should have been loaded
|
||||
/// into the map by the `typeck::collect` phase. If the def-id is external,
|
||||
/// then we have to go consult the crate loading code (and cache the result for
|
||||
@ -2204,13 +2102,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provided_trait_methods(self, id: DefId) -> Vec<Rc<Method<'gcx>>> {
|
||||
self.impl_or_trait_items(id).iter().filter_map(|&def_id| {
|
||||
match self.impl_or_trait_item(def_id) {
|
||||
MethodTraitItem(ref m) if m.has_body => Some(m.clone()),
|
||||
_ => None
|
||||
}
|
||||
}).collect()
|
||||
pub fn provided_trait_methods(self, id: DefId) -> Vec<AssociatedItem> {
|
||||
self.associated_items(id)
|
||||
.filter(|item| item.kind == AssociatedKind::Method && item.has_value)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
|
||||
@ -2243,17 +2138,105 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_or_trait_items", id, &self.impl_or_trait_items,
|
||||
|| self.sess.cstore.impl_or_trait_item(self.global_tcx(), id)
|
||||
.expect("missing ImplOrTraitItem in metadata"))
|
||||
pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
|
||||
self.associated_items.memoize(def_id, || {
|
||||
if !def_id.is_local() {
|
||||
return self.sess.cstore.associated_item(self.global_tcx(), def_id)
|
||||
.expect("missing AssociatedItem in metadata");
|
||||
}
|
||||
|
||||
let id = self.map.as_local_node_id(def_id).unwrap();
|
||||
let parent_id = self.map.get_parent(id);
|
||||
let parent_def_id = self.map.local_def_id(parent_id);
|
||||
match self.map.get(id) {
|
||||
ast_map::NodeTraitItem(trait_item) => {
|
||||
let (kind, has_self, has_value) = match trait_item.node {
|
||||
hir::MethodTraitItem(ref sig, ref body) => {
|
||||
(AssociatedKind::Method, sig.decl.get_self().is_some(),
|
||||
body.is_some())
|
||||
}
|
||||
hir::ConstTraitItem(_, ref value) => {
|
||||
(AssociatedKind::Const, false, value.is_some())
|
||||
}
|
||||
hir::TypeTraitItem(_, ref ty) => {
|
||||
(AssociatedKind::Type, false, ty.is_some())
|
||||
}
|
||||
};
|
||||
|
||||
AssociatedItem {
|
||||
name: trait_item.name,
|
||||
kind: kind,
|
||||
vis: Visibility::from_hir(&hir::Inherited, id, self),
|
||||
defaultness: hir::Defaultness::Default,
|
||||
has_value: has_value,
|
||||
def_id: def_id,
|
||||
container: TraitContainer(parent_def_id),
|
||||
method_has_self_argument: has_self
|
||||
}
|
||||
}
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
let (kind, has_self) = match impl_item.node {
|
||||
hir::ImplItemKind::Method(ref sig, _) => {
|
||||
(AssociatedKind::Method, sig.decl.get_self().is_some())
|
||||
}
|
||||
hir::ImplItemKind::Const(..) => (AssociatedKind::Const, false),
|
||||
hir::ImplItemKind::Type(..) => (AssociatedKind::Type, false)
|
||||
};
|
||||
|
||||
// Trait impl items are always public.
|
||||
let public = hir::Public;
|
||||
let parent_item = self.map.expect_item(parent_id);
|
||||
let vis = if let hir::ItemImpl(.., Some(_), _, _) = parent_item.node {
|
||||
&public
|
||||
} else {
|
||||
&impl_item.vis
|
||||
};
|
||||
|
||||
AssociatedItem {
|
||||
name: impl_item.name,
|
||||
kind: kind,
|
||||
vis: Visibility::from_hir(vis, id, self),
|
||||
defaultness: impl_item.defaultness,
|
||||
has_value: true,
|
||||
def_id: def_id,
|
||||
container: ImplContainer(parent_def_id),
|
||||
method_has_self_argument: has_self
|
||||
}
|
||||
}
|
||||
item => bug!("associated_item: {:?} not an associated item", item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn impl_or_trait_items(self, id: DefId) -> Rc<Vec<DefId>> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_or_trait_items", id, &self.impl_or_trait_item_def_ids,
|
||||
|| Rc::new(self.sess.cstore.impl_or_trait_items(id)))
|
||||
pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
|
||||
self.associated_item_def_ids.memoize(def_id, || {
|
||||
if !def_id.is_local() {
|
||||
return Rc::new(self.sess.cstore.associated_item_def_ids(def_id));
|
||||
}
|
||||
|
||||
let id = self.map.as_local_node_id(def_id).unwrap();
|
||||
let item = self.map.expect_item(id);
|
||||
match item.node {
|
||||
hir::ItemTrait(.., ref trait_items) => {
|
||||
Rc::new(trait_items.iter().map(|trait_item| {
|
||||
self.map.local_def_id(trait_item.id)
|
||||
}).collect())
|
||||
}
|
||||
hir::ItemImpl(.., ref impl_items) => {
|
||||
Rc::new(impl_items.iter().map(|impl_item| {
|
||||
self.map.local_def_id(impl_item.id)
|
||||
}).collect())
|
||||
}
|
||||
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
|
||||
pub fn associated_items(self, def_id: DefId)
|
||||
-> impl Iterator<Item = ty::AssociatedItem> + 'a {
|
||||
let def_ids = self.associated_item_def_ids(def_id);
|
||||
(0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
|
||||
}
|
||||
|
||||
/// Returns the trait-ref corresponding to a given impl, or None if it is
|
||||
@ -2539,31 +2522,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
|
||||
}
|
||||
|
||||
/// Load primitive inherent implementations if necessary
|
||||
pub fn populate_implementations_for_primitive_if_necessary(self,
|
||||
primitive_def_id: DefId) {
|
||||
if primitive_def_id.is_local() {
|
||||
return
|
||||
}
|
||||
|
||||
// The primitive is not local, hence we are reading this out
|
||||
// of metadata.
|
||||
let _ignore = self.dep_graph.in_ignore();
|
||||
|
||||
if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
|
||||
return
|
||||
}
|
||||
|
||||
debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
|
||||
primitive_def_id);
|
||||
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id);
|
||||
|
||||
// Store the implementation info.
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items));
|
||||
self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
|
||||
}
|
||||
|
||||
/// Populates the type context with all the inherent implementations for
|
||||
/// the given type if necessary.
|
||||
pub fn populate_inherent_implementations_for_type_if_necessary(self,
|
||||
@ -2584,11 +2542,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
type_id);
|
||||
|
||||
let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
|
||||
for &impl_def_id in &inherent_impls {
|
||||
// Store the implementation info.
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
|
||||
}
|
||||
|
||||
self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
|
||||
self.populated_external_types.borrow_mut().insert(type_id);
|
||||
@ -2617,23 +2570,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
|
||||
let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
|
||||
|
||||
// Record the trait->implementation mapping.
|
||||
let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id);
|
||||
def.record_remote_impl(self, impl_def_id, trait_ref, parent);
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for &impl_item_def_id in &impl_items {
|
||||
// load impl items eagerly for convenience
|
||||
// FIXME: we may want to load these lazily
|
||||
self.impl_or_trait_item(impl_item_def_id);
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
|
||||
}
|
||||
|
||||
def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
|
||||
@ -2679,17 +2620,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// ID of the impl that the method belongs to. Otherwise, return `None`.
|
||||
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
|
||||
if def_id.krate != LOCAL_CRATE {
|
||||
return self.sess.cstore.impl_or_trait_item(self.global_tcx(), def_id)
|
||||
return self.sess.cstore.associated_item(self.global_tcx(), def_id)
|
||||
.and_then(|item| {
|
||||
match item.container() {
|
||||
match item.container {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
}
|
||||
});
|
||||
}
|
||||
match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
|
||||
match self.associated_items.borrow().get(&def_id).cloned() {
|
||||
Some(trait_item) => {
|
||||
match trait_item.container() {
|
||||
match trait_item.container {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
}
|
||||
@ -2705,9 +2646,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
if def_id.krate != LOCAL_CRATE {
|
||||
return self.sess.cstore.trait_of_item(def_id);
|
||||
}
|
||||
match self.impl_or_trait_items.borrow().get(&def_id) {
|
||||
Some(impl_or_trait_item) => {
|
||||
match impl_or_trait_item.container() {
|
||||
match self.associated_items.borrow().get(&def_id) {
|
||||
Some(associated_item) => {
|
||||
match associated_item.container {
|
||||
TraitContainer(def_id) => Some(def_id),
|
||||
ImplContainer(_) => None
|
||||
}
|
||||
@ -2716,30 +2657,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// If the given def ID describes an item belonging to a trait, (either a
|
||||
/// default method or an implementation of a trait method), return the ID of
|
||||
/// the method inside trait definition (this means that if the given def ID
|
||||
/// is already that of the original trait method, then the return value is
|
||||
/// the same).
|
||||
/// Otherwise, return `None`.
|
||||
pub fn trait_item_of_item(self, def_id: DefId) -> Option<DefId> {
|
||||
let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) {
|
||||
Some(m) => m.clone(),
|
||||
None => return None,
|
||||
};
|
||||
match impl_or_trait_item.container() {
|
||||
TraitContainer(_) => Some(impl_or_trait_item.def_id()),
|
||||
ImplContainer(def_id) => {
|
||||
self.trait_id_of_impl(def_id).and_then(|trait_did| {
|
||||
let name = impl_or_trait_item.name();
|
||||
self.trait_items(trait_did).iter()
|
||||
.find(|item| item.name() == name)
|
||||
.map(|item| item.def_id())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a parameter environment suitable for static contexts or other contexts where there
|
||||
/// are no free type/lifetime parameters in scope.
|
||||
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
||||
@ -2856,15 +2773,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The category of explicit self.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ExplicitSelfCategory<'tcx> {
|
||||
Static,
|
||||
ByValue,
|
||||
ByReference(&'tcx Region, hir::Mutability),
|
||||
ByBox,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
|
||||
F: FnOnce(&[hir::Freevar]) -> T,
|
||||
|
@ -670,18 +670,6 @@ impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "ImplOrTraitItem(")?;
|
||||
match *self {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
|
||||
ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
|
||||
ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
|
||||
}?;
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "fn")?;
|
||||
@ -995,20 +983,6 @@ impl fmt::Display for ty::InferTy {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for ty::ExplicitSelfCategory<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
ty::ExplicitSelfCategory::Static => "static",
|
||||
ty::ExplicitSelfCategory::ByValue => "self",
|
||||
ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => {
|
||||
"&mut self"
|
||||
}
|
||||
ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self",
|
||||
ty::ExplicitSelfCategory::ByBox => "Box<self>",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ty::ParamTy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
|
@ -190,7 +190,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
all_loans: &[Loan<'tcx>],
|
||||
fn_id: ast::NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
debug!("check_loans(body id={})", body.id);
|
||||
|
||||
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
|
||||
|
@ -42,7 +42,7 @@ mod move_error;
|
||||
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
fn_id: NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
-> (Vec<Loan<'tcx>>,
|
||||
move_data::MoveData<'tcx>) {
|
||||
let mut glcx = GatherLoanCtxt {
|
||||
|
@ -58,7 +58,7 @@ pub struct MoveDataParamEnv<'tcx> {
|
||||
pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
|
||||
fk: FnKind,
|
||||
_decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
_sp: Span,
|
||||
id: ast::NodeId,
|
||||
attributes: &[ast::Attribute]) {
|
||||
|
@ -47,9 +47,7 @@ use syntax_pos::{MultiSpan, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{FnDecl, Block};
|
||||
use rustc::hir::intravisit;
|
||||
use rustc::hir::intravisit::{Visitor, FnKind};
|
||||
use rustc::hir::intravisit::{self, Visitor, FnKind};
|
||||
|
||||
pub mod check_loans;
|
||||
|
||||
@ -65,8 +63,8 @@ pub struct LoanDataFlowOperator;
|
||||
pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
|
||||
b: &'v Block, s: Span, id: ast::NodeId) {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::ItemFn(..) |
|
||||
FnKind::Method(..) => {
|
||||
@ -159,7 +157,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
|
||||
fn borrowck_fn(this: &mut BorrowckCtxt,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId,
|
||||
attributes: &[ast::Attribute]) {
|
||||
@ -200,7 +198,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
cfg: &cfg::CFG,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId)
|
||||
-> AnalysisData<'a, 'tcx>
|
||||
|
@ -656,7 +656,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
|
||||
cfg: &cfg::CFG,
|
||||
id_range: IdRange,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
-> FlowedMoveData<'a, 'tcx> {
|
||||
let mut dfcx_moves =
|
||||
DataFlowContext::new(tcx,
|
||||
|
@ -65,7 +65,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for OuterVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
if let FnKind::Closure(..) = fk {
|
||||
span_bug!(s, "check_match: closure outside of function")
|
||||
}
|
||||
@ -113,7 +113,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, n: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, n: ast::NodeId) {
|
||||
intravisit::walk_fn(self, fk, fd, b, s, n);
|
||||
|
||||
for input in &fd.inputs {
|
||||
|
@ -857,11 +857,10 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
callee => signal!(e, CallOn(callee)),
|
||||
};
|
||||
let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
|
||||
(fn_like.decl(), &fn_like.body().expr)
|
||||
(fn_like.decl(), fn_like.body())
|
||||
} else {
|
||||
signal!(e, NonConstPath)
|
||||
};
|
||||
let result = result.as_ref().expect("const fn has no result expression");
|
||||
assert_eq!(decl.inputs.len(), args.len());
|
||||
|
||||
let mut call_args = DefIdMap();
|
||||
@ -1091,13 +1090,8 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// when constructing the inference context above.
|
||||
match selection {
|
||||
traits::VtableImpl(ref impl_data) => {
|
||||
let ac = tcx.impl_or_trait_items(impl_data.impl_def_id)
|
||||
.iter().filter_map(|&def_id| {
|
||||
match tcx.impl_or_trait_item(def_id) {
|
||||
ty::ConstTraitItem(ic) => Some(ic),
|
||||
_ => None
|
||||
}
|
||||
}).find(|ic| ic.name == ti.name);
|
||||
let ac = tcx.associated_items(impl_data.impl_def_id)
|
||||
.find(|item| item.kind == ty::AssociatedKind::Const && item.name == ti.name);
|
||||
match ac {
|
||||
Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
|
||||
None => match ti.node {
|
||||
|
@ -455,8 +455,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
1 => panic!("make_input should have provided valid inputs"),
|
||||
_ => early_error(sopts.error_format, "multiple input filenames provided"),
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn late_callback(&mut self,
|
||||
|
@ -701,8 +701,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
|
||||
mut out: W)
|
||||
-> io::Result<()> {
|
||||
let cfg = match code {
|
||||
blocks::BlockCode(block) => cfg::CFG::new(tcx, &block),
|
||||
blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &fn_like.body()),
|
||||
blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr),
|
||||
blocks::Code::FnLike(fn_like) => cfg::CFG::new(tcx, fn_like.body()),
|
||||
};
|
||||
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
|
||||
let lcfg = LabelledCFG {
|
||||
@ -717,12 +717,12 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
|
||||
let r = dot::render(&lcfg, &mut out);
|
||||
return expand_err_details(r);
|
||||
}
|
||||
blocks::BlockCode(_) => {
|
||||
blocks::Code::Expr(_) => {
|
||||
tcx.sess.err("--pretty flowgraph with -Z flowgraph-print annotations requires \
|
||||
fn-like node id.");
|
||||
return Ok(());
|
||||
}
|
||||
blocks::FnLikeCode(fn_like) => {
|
||||
blocks::Code::FnLike(fn_like) => {
|
||||
let (bccx, analysis_data) =
|
||||
borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg);
|
||||
|
||||
@ -990,8 +990,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid))
|
||||
});
|
||||
|
||||
let code = blocks::Code::from_node(node);
|
||||
match code {
|
||||
match blocks::Code::from_node(&tcx.map, nodeid) {
|
||||
Some(code) => {
|
||||
let variants = gather_flowgraph_variants(tcx.sess);
|
||||
|
||||
|
@ -29,10 +29,10 @@ pub enum MethodLateContext {
|
||||
|
||||
pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext {
|
||||
let def_id = cx.tcx.map.local_def_id(id);
|
||||
match cx.tcx.impl_or_trait_items.borrow().get(&def_id) {
|
||||
match cx.tcx.associated_items.borrow().get(&def_id) {
|
||||
None => span_bug!(span, "missing method descriptor?!"),
|
||||
Some(item) => {
|
||||
match item.container() {
|
||||
match item.container {
|
||||
ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match cx.tcx.impl_trait_ref(cid) {
|
||||
@ -250,7 +250,7 @@ impl LateLintPass for NonSnakeCase {
|
||||
cx: &LateContext,
|
||||
fk: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId) {
|
||||
match fk {
|
||||
|
@ -222,7 +222,7 @@ impl LateLintPass for UnsafeCode {
|
||||
cx: &LateContext,
|
||||
fk: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
span: Span,
|
||||
_: ast::NodeId) {
|
||||
match fk {
|
||||
@ -812,13 +812,13 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
cx: &LateContext,
|
||||
fn_kind: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
blk: &hir::Block,
|
||||
blk: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
let method = match fn_kind {
|
||||
FnKind::ItemFn(..) => None,
|
||||
FnKind::Method(..) => {
|
||||
cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method()
|
||||
Some(cx.tcx.associated_item(cx.tcx.map.local_def_id(id)))
|
||||
}
|
||||
// closures can't recur, so they don't matter.
|
||||
FnKind::Closure(_) => return,
|
||||
@ -937,7 +937,7 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
|
||||
// Check if the expression `id` performs a call to `method`.
|
||||
fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
method: &ty::Method,
|
||||
method: &ty::AssociatedItem,
|
||||
id: ast::NodeId)
|
||||
-> bool {
|
||||
use rustc::ty::adjustment::*;
|
||||
@ -986,14 +986,14 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
// Check if the method call to the method with the ID `callee_id`
|
||||
// and instantiated with `callee_substs` refers to method `method`.
|
||||
fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
method: &ty::Method,
|
||||
method: &ty::AssociatedItem,
|
||||
callee_id: DefId,
|
||||
callee_substs: &Substs<'tcx>,
|
||||
expr_id: ast::NodeId)
|
||||
-> bool {
|
||||
let callee_item = tcx.impl_or_trait_item(callee_id);
|
||||
let callee_item = tcx.associated_item(callee_id);
|
||||
|
||||
match callee_item.container() {
|
||||
match callee_item.container {
|
||||
// This is an inherent method, so the `def_id` refers
|
||||
// directly to the method definition.
|
||||
ty::ImplContainer(_) => callee_id == method.def_id,
|
||||
@ -1034,7 +1034,7 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
let container = ty::ImplContainer(vtable_impl.impl_def_id);
|
||||
// It matches if it comes from the same impl,
|
||||
// and has the same method name.
|
||||
container == method.container && callee_item.name() == method.name
|
||||
container == method.container && callee_item.name == method.name
|
||||
}
|
||||
|
||||
// There's no way to know if this call is
|
||||
|
@ -99,7 +99,7 @@ impl LateLintPass for UnusedMut {
|
||||
cx: &LateContext,
|
||||
_: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
_: Span,
|
||||
_: ast::NodeId) {
|
||||
for a in &decl.inputs {
|
||||
|
@ -136,7 +136,7 @@ fn main() {
|
||||
let mut parts = version_output.split('.');
|
||||
if let (Some(major), Some(minor)) = (parts.next().and_then(|s| s.parse::<u32>().ok()),
|
||||
parts.next().and_then(|s| s.parse::<u32>().ok())) {
|
||||
if major > 3 || (major == 3 && minor >= 8) {
|
||||
if major > 3 || (major == 3 && minor >= 9) {
|
||||
cmd.arg("--link-static");
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
result
|
||||
}
|
||||
|
||||
fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId> {
|
||||
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId> {
|
||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||
let mut result = vec![];
|
||||
self.get_crate_data(def_id.krate)
|
||||
@ -182,11 +182,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index)
|
||||
}
|
||||
|
||||
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::ImplOrTraitItem<'tcx>>
|
||||
fn associated_item<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::AssociatedItem>
|
||||
{
|
||||
self.dep_graph.read(DepNode::MetaData(def));
|
||||
self.get_crate_data(def.krate).get_impl_or_trait_item(def.index, tcx)
|
||||
self.get_crate_data(def.krate).get_associated_item(def.index)
|
||||
}
|
||||
|
||||
fn is_const_fn(&self, did: DefId) -> bool
|
||||
@ -427,9 +427,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
// the logic to do that already exists in `middle`. In order to
|
||||
// reuse that code, it needs to be able to look up the traits for
|
||||
// inlined items.
|
||||
let ty_trait_item = tcx.impl_or_trait_item(def_id).clone();
|
||||
let ty_trait_item = tcx.associated_item(def_id).clone();
|
||||
let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
|
||||
tcx.impl_or_trait_items.borrow_mut()
|
||||
tcx.associated_items.borrow_mut()
|
||||
.insert(trait_item_def_id, ty_trait_item);
|
||||
}
|
||||
Some(&InlinedItem::ImplItem(_, ref impl_item)) => {
|
||||
|
@ -36,7 +36,6 @@ use std::borrow::Cow;
|
||||
use std::cell::Ref;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::u32;
|
||||
|
||||
@ -792,10 +791,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
self.entry(id).mir.map(|mir| mir.decode((self, tcx)))
|
||||
}
|
||||
|
||||
pub fn get_impl_or_trait_item(&self,
|
||||
id: DefIndex,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Option<ty::ImplOrTraitItem<'tcx>> {
|
||||
pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
||||
let item = self.entry(id);
|
||||
let parent_and_name = || {
|
||||
let def_key = item.def_key.decode(self);
|
||||
@ -806,52 +802,43 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
Some(match item.kind {
|
||||
EntryKind::AssociatedConst(container) => {
|
||||
let (parent, name) = parent_and_name();
|
||||
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
|
||||
ty::AssociatedItem {
|
||||
name: name,
|
||||
ty: item.ty.unwrap().decode((self, tcx)),
|
||||
kind: ty::AssociatedKind::Const,
|
||||
vis: item.visibility,
|
||||
defaultness: container.defaultness(),
|
||||
has_value: container.has_value(),
|
||||
def_id: self.local_def_id(id),
|
||||
container: container.with_def_id(parent),
|
||||
has_value: container.has_body(),
|
||||
}))
|
||||
method_has_self_argument: false
|
||||
}
|
||||
}
|
||||
EntryKind::Method(data) => {
|
||||
let (parent, name) = parent_and_name();
|
||||
let ity = item.ty.unwrap().decode((self, tcx));
|
||||
let fty = match ity.sty {
|
||||
ty::TyFnDef(.., fty) => fty,
|
||||
_ => {
|
||||
bug!("the type {:?} of the method {:?} is not a function?",
|
||||
ity,
|
||||
name)
|
||||
}
|
||||
};
|
||||
|
||||
let data = data.decode(self);
|
||||
ty::MethodTraitItem(Rc::new(ty::Method {
|
||||
ty::AssociatedItem {
|
||||
name: name,
|
||||
generics: tcx.lookup_generics(self.local_def_id(id)),
|
||||
predicates: item.predicates.unwrap().decode((self, tcx)),
|
||||
fty: fty,
|
||||
explicit_self: data.explicit_self.decode((self, tcx)),
|
||||
kind: ty::AssociatedKind::Method,
|
||||
vis: item.visibility,
|
||||
defaultness: data.container.defaultness(),
|
||||
has_body: data.container.has_body(),
|
||||
has_value: data.container.has_value(),
|
||||
def_id: self.local_def_id(id),
|
||||
container: data.container.with_def_id(parent),
|
||||
}))
|
||||
method_has_self_argument: data.has_self
|
||||
}
|
||||
}
|
||||
EntryKind::AssociatedType(container) => {
|
||||
let (parent, name) = parent_and_name();
|
||||
ty::TypeTraitItem(Rc::new(ty::AssociatedType {
|
||||
ty::AssociatedItem {
|
||||
name: name,
|
||||
ty: item.ty.map(|ty| ty.decode((self, tcx))),
|
||||
kind: ty::AssociatedKind::Type,
|
||||
vis: item.visibility,
|
||||
defaultness: container.defaultness(),
|
||||
has_value: container.has_value(),
|
||||
def_id: self.local_def_id(id),
|
||||
container: container.with_def_id(parent),
|
||||
}))
|
||||
method_has_self_argument: false
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
|
@ -457,19 +457,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
let node_id = tcx.map.as_local_node_id(def_id).unwrap();
|
||||
let ast_item = tcx.map.expect_trait_item(node_id);
|
||||
let trait_item = tcx.impl_or_trait_item(def_id);
|
||||
let trait_item = tcx.associated_item(def_id);
|
||||
|
||||
let container = |has_body| if has_body {
|
||||
let container = if trait_item.has_value {
|
||||
AssociatedContainer::TraitWithDefault
|
||||
} else {
|
||||
AssociatedContainer::TraitRequired
|
||||
};
|
||||
|
||||
let kind = match trait_item {
|
||||
ty::ConstTraitItem(ref associated_const) => {
|
||||
EntryKind::AssociatedConst(container(associated_const.has_value))
|
||||
}
|
||||
ty::MethodTraitItem(ref method_ty) => {
|
||||
let kind = match trait_item.kind {
|
||||
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
|
||||
ty::AssociatedKind::Method => {
|
||||
let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node {
|
||||
FnData {
|
||||
constness: hir::Constness::NotConst,
|
||||
@ -478,30 +476,35 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
} else {
|
||||
bug!()
|
||||
};
|
||||
let data = MethodData {
|
||||
EntryKind::Method(self.lazy(&MethodData {
|
||||
fn_data: fn_data,
|
||||
container: container(method_ty.has_body),
|
||||
explicit_self: self.lazy(&method_ty.explicit_self),
|
||||
};
|
||||
EntryKind::Method(self.lazy(&data))
|
||||
container: container,
|
||||
has_self: trait_item.method_has_self_argument,
|
||||
}))
|
||||
}
|
||||
ty::TypeTraitItem(_) => EntryKind::AssociatedType(container(false)),
|
||||
ty::AssociatedKind::Type => EntryKind::AssociatedType(container),
|
||||
};
|
||||
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: trait_item.vis().simplify(),
|
||||
visibility: trait_item.vis.simplify(),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
deprecation: self.encode_deprecation(def_id),
|
||||
|
||||
ty: match trait_item {
|
||||
ty::ConstTraitItem(_) |
|
||||
ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)),
|
||||
ty::TypeTraitItem(ref associated_type) => {
|
||||
associated_type.ty.map(|ty| self.lazy(&ty))
|
||||
ty: match trait_item.kind {
|
||||
ty::AssociatedKind::Const |
|
||||
ty::AssociatedKind::Method => {
|
||||
Some(self.encode_item_type(def_id))
|
||||
}
|
||||
ty::AssociatedKind::Type => {
|
||||
if trait_item.has_value {
|
||||
Some(self.encode_item_type(def_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
},
|
||||
inherent_impls: LazySeq::empty(),
|
||||
@ -509,8 +512,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
generics: Some(self.encode_generics(def_id)),
|
||||
predicates: Some(self.encode_predicates(def_id)),
|
||||
|
||||
ast: if let ty::ConstTraitItem(_) = trait_item {
|
||||
let trait_def_id = trait_item.container().id();
|
||||
ast: if trait_item.kind == ty::AssociatedKind::Const {
|
||||
let trait_def_id = trait_item.container.id();
|
||||
Some(self.encode_inlined_item(InlinedItemRef::TraitItem(trait_def_id, ast_item)))
|
||||
} else {
|
||||
None
|
||||
@ -522,17 +525,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
|
||||
let ast_item = self.tcx.map.expect_impl_item(node_id);
|
||||
let impl_item = self.tcx.impl_or_trait_item(def_id);
|
||||
let impl_def_id = impl_item.container().id();
|
||||
let impl_item = self.tcx.associated_item(def_id);
|
||||
let impl_def_id = impl_item.container.id();
|
||||
|
||||
let container = match ast_item.defaultness {
|
||||
let container = match impl_item.defaultness {
|
||||
hir::Defaultness::Default => AssociatedContainer::ImplDefault,
|
||||
hir::Defaultness::Final => AssociatedContainer::ImplFinal,
|
||||
};
|
||||
|
||||
let kind = match impl_item {
|
||||
ty::ConstTraitItem(_) => EntryKind::AssociatedConst(container),
|
||||
ty::MethodTraitItem(ref method_ty) => {
|
||||
let kind = match impl_item.kind {
|
||||
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
|
||||
ty::AssociatedKind::Method => {
|
||||
let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
|
||||
FnData {
|
||||
constness: sig.constness,
|
||||
@ -541,17 +544,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
} else {
|
||||
bug!()
|
||||
};
|
||||
let data = MethodData {
|
||||
EntryKind::Method(self.lazy(&MethodData {
|
||||
fn_data: fn_data,
|
||||
container: container,
|
||||
explicit_self: self.lazy(&method_ty.explicit_self),
|
||||
};
|
||||
EntryKind::Method(self.lazy(&data))
|
||||
has_self: impl_item.method_has_self_argument,
|
||||
}))
|
||||
}
|
||||
ty::TypeTraitItem(_) => EntryKind::AssociatedType(container),
|
||||
ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
|
||||
};
|
||||
|
||||
let (ast, mir) = if let ty::ConstTraitItem(_) = impl_item {
|
||||
let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const {
|
||||
(true, true)
|
||||
} else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
|
||||
let generics = self.tcx.lookup_generics(def_id);
|
||||
@ -565,20 +567,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
Entry {
|
||||
kind: kind,
|
||||
visibility: impl_item.vis().simplify(),
|
||||
visibility: impl_item.vis.simplify(),
|
||||
def_key: self.encode_def_key(def_id),
|
||||
attributes: self.encode_attributes(&ast_item.attrs),
|
||||
children: LazySeq::empty(),
|
||||
stability: self.encode_stability(def_id),
|
||||
deprecation: self.encode_deprecation(def_id),
|
||||
|
||||
ty: match impl_item {
|
||||
ty::ConstTraitItem(_) |
|
||||
ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)),
|
||||
ty::TypeTraitItem(ref associated_type) => {
|
||||
associated_type.ty.map(|ty| self.lazy(&ty))
|
||||
}
|
||||
},
|
||||
ty: Some(self.encode_item_type(def_id)),
|
||||
inherent_impls: LazySeq::empty(),
|
||||
variances: LazySeq::empty(),
|
||||
generics: Some(self.encode_generics(def_id)),
|
||||
@ -758,7 +754,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
}
|
||||
hir::ItemImpl(..) |
|
||||
hir::ItemTrait(..) => {
|
||||
self.lazy_seq(tcx.impl_or_trait_items(def_id).iter().map(|&def_id| {
|
||||
self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| {
|
||||
assert!(def_id.is_local());
|
||||
def_id.index
|
||||
}))
|
||||
@ -880,14 +876,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||
self.encode_fields(def_id);
|
||||
}
|
||||
hir::ItemImpl(..) => {
|
||||
for &trait_item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] {
|
||||
for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
|
||||
self.record(trait_item_def_id,
|
||||
EncodeContext::encode_info_for_impl_item,
|
||||
trait_item_def_id);
|
||||
}
|
||||
}
|
||||
hir::ItemTrait(..) => {
|
||||
for &item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] {
|
||||
for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
|
||||
self.record(item_def_id,
|
||||
EncodeContext::encode_info_for_trait_item,
|
||||
item_def_id);
|
||||
|
@ -245,7 +245,7 @@ pub enum EntryKind<'tcx> {
|
||||
Trait(Lazy<TraitData<'tcx>>),
|
||||
Impl(Lazy<ImplData<'tcx>>),
|
||||
DefaultImpl(Lazy<ImplData<'tcx>>),
|
||||
Method(Lazy<MethodData<'tcx>>),
|
||||
Method(Lazy<MethodData>),
|
||||
AssociatedType(AssociatedContainer),
|
||||
AssociatedConst(AssociatedContainer),
|
||||
}
|
||||
@ -300,7 +300,7 @@ pub enum AssociatedContainer {
|
||||
}
|
||||
|
||||
impl AssociatedContainer {
|
||||
pub fn with_def_id(&self, def_id: DefId) -> ty::ImplOrTraitItemContainer {
|
||||
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
|
||||
match *self {
|
||||
AssociatedContainer::TraitRequired |
|
||||
AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
|
||||
@ -310,7 +310,7 @@ impl AssociatedContainer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_body(&self) -> bool {
|
||||
pub fn has_value(&self) -> bool {
|
||||
match *self {
|
||||
AssociatedContainer::TraitRequired => false,
|
||||
|
||||
@ -332,10 +332,10 @@ impl AssociatedContainer {
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct MethodData<'tcx> {
|
||||
pub struct MethodData {
|
||||
pub fn_data: FnData,
|
||||
pub container: AssociatedContainer,
|
||||
pub explicit_self: Lazy<ty::ExplicitSelfCategory<'tcx>>,
|
||||
pub has_self: bool,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
|
@ -156,7 +156,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
fn_id: ast::NodeId,
|
||||
arguments: A,
|
||||
return_ty: Ty<'gcx>,
|
||||
ast_block: &'gcx hir::Block)
|
||||
ast_body: &'gcx hir::Expr)
|
||||
-> (Mir<'tcx>, ScopeAuxiliaryVec)
|
||||
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
|
||||
{
|
||||
@ -166,7 +166,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let span = tcx.map.span(fn_id);
|
||||
let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
|
||||
|
||||
let body_id = ast_block.id;
|
||||
let body_id = ast_body.id;
|
||||
let call_site_extent =
|
||||
tcx.region_maps.lookup_code_extent(
|
||||
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
|
||||
@ -176,7 +176,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let mut block = START_BLOCK;
|
||||
unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
|
||||
unpack!(block = builder.in_scope(arg_extent, block, |builder| {
|
||||
builder.args_and_body(block, return_ty, &arguments, arg_extent, ast_block)
|
||||
builder.args_and_body(block, &arguments, arg_extent, ast_body)
|
||||
}));
|
||||
// Attribute epilogue to function's closing brace
|
||||
let fn_end = Span { lo: span.hi, ..span };
|
||||
@ -310,10 +310,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn args_and_body(&mut self,
|
||||
mut block: BasicBlock,
|
||||
return_ty: Ty<'tcx>,
|
||||
arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'gcx hir::Block)
|
||||
ast_body: &'gcx hir::Expr)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
// Allocate locals for the function arguments
|
||||
@ -342,12 +341,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = Pattern::from_hir(self.hir.tcx(), pattern);
|
||||
scope = self.declare_bindings(scope, ast_block.span, &pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span, &pattern);
|
||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||
}
|
||||
|
||||
// Make sure we drop (parts of) the argument even when not matched on.
|
||||
self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
|
||||
self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
||||
argument_extent, &lvalue, ty);
|
||||
|
||||
}
|
||||
@ -357,13 +356,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
self.visibility_scope = visibility_scope;
|
||||
}
|
||||
|
||||
// FIXME(#32959): temporary hack for the issue at hand
|
||||
let return_is_unit = return_ty.is_nil();
|
||||
// start the first basic block and translate the body
|
||||
unpack!(block = self.ast_block(&Lvalue::Local(RETURN_POINTER),
|
||||
return_is_unit, block, ast_block));
|
||||
|
||||
block.unit()
|
||||
let body = self.hir.mirror(ast_body);
|
||||
self.into(&Lvalue::Local(RETURN_POINTER), block, body)
|
||||
}
|
||||
|
||||
fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
|
||||
|
@ -147,20 +147,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
-> (Ty<'tcx>, Literal<'tcx>) {
|
||||
let method_name = token::intern(method_name);
|
||||
let substs = self.tcx.mk_substs_trait(self_ty, params);
|
||||
for trait_item in self.tcx.trait_items(trait_def_id).iter() {
|
||||
match *trait_item {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
|
||||
if method.name == method_name {
|
||||
let method_ty = self.tcx.lookup_item_type(method.def_id);
|
||||
let method_ty = method_ty.ty.subst(self.tcx, substs);
|
||||
return (method_ty, Literal::Item {
|
||||
def_id: method.def_id,
|
||||
substs: substs,
|
||||
});
|
||||
}
|
||||
}
|
||||
ty::ImplOrTraitItem::ConstTraitItem(..) |
|
||||
ty::ImplOrTraitItem::TypeTraitItem(..) => {}
|
||||
for item in self.tcx.associated_items(trait_def_id) {
|
||||
if item.kind == ty::AssociatedKind::Method && item.name == method_name {
|
||||
let method_ty = self.tcx.lookup_item_type(item.def_id);
|
||||
let method_ty = method_ty.ty.subst(self.tcx, substs);
|
||||
return (method_ty, Literal::Item {
|
||||
def_id: item.def_id,
|
||||
substs: substs,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: FnKind<'tcx>,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block,
|
||||
body: &'tcx hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId) {
|
||||
// fetch the fully liberated fn signature (that is, all bound
|
||||
|
@ -134,7 +134,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
|
||||
fn fn_like(&mut self,
|
||||
fk: FnKind,
|
||||
fd: &hir::FnDecl,
|
||||
b: &hir::Block,
|
||||
b: &hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId)
|
||||
-> ConstQualif {
|
||||
@ -265,7 +265,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
self.fn_like(fk, fd, b, s, fn_id);
|
||||
@ -542,7 +542,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
|
||||
v.handle_const_fn_call(e, did, node_ty)
|
||||
}
|
||||
Some(Def::Method(did)) => {
|
||||
match v.tcx.impl_or_trait_item(did).container() {
|
||||
match v.tcx.associated_item(did).container {
|
||||
ty::ImplContainer(_) => {
|
||||
v.handle_const_fn_call(e, did, node_ty)
|
||||
}
|
||||
@ -557,7 +557,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
|
||||
}
|
||||
hir::ExprMethodCall(..) => {
|
||||
let method = v.tcx.tables().method_map[&method_call];
|
||||
let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
|
||||
let is_const = match v.tcx.associated_item(method.def_id).container {
|
||||
ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
|
||||
ty::TraitContainer(_) => false
|
||||
};
|
||||
|
@ -164,7 +164,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: hir_visit::FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
id: NodeId) {
|
||||
self.record("FnDecl", Id::None, fd);
|
||||
@ -295,11 +295,10 @@ impl<'v> ast_visit::Visitor for StatCollector<'v> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: ast_visit::FnKind,
|
||||
fd: &ast::FnDecl,
|
||||
b: &ast::Block,
|
||||
s: Span,
|
||||
_: NodeId) {
|
||||
self.record("FnDecl", Id::None, fd);
|
||||
ast_visit::walk_fn(self, fk, fd, b, s)
|
||||
ast_visit::walk_fn(self, fk, fd, s)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
|
||||
|
@ -54,7 +54,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
|
||||
self.with_context(Loop, |v| v.visit_block(&b));
|
||||
}
|
||||
hir::ExprClosure(.., ref b, _) => {
|
||||
self.with_context(Closure, |v| v.visit_block(&b));
|
||||
self.with_context(Closure, |v| v.visit_expr(&b));
|
||||
}
|
||||
hir::ExprBreak(_) => self.require_loop("break", e.span),
|
||||
hir::ExprAgain(_) => self.require_loop("continue", e.span),
|
||||
|
@ -35,7 +35,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: intravisit::FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
// FIXME (@jroesch) change this to be an inference context
|
||||
|
@ -399,7 +399,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
|
||||
// Checks that a method is in scope.
|
||||
fn check_method(&mut self, span: Span, method_def_id: DefId) {
|
||||
match self.tcx.impl_or_trait_item(method_def_id).container() {
|
||||
match self.tcx.associated_item(method_def_id).container {
|
||||
// Trait methods are always all public. The only controlling factor
|
||||
// is whether the trait itself is accessible or not.
|
||||
ty::TraitContainer(trait_def_id) if !self.item_is_accessible(trait_def_id) => {
|
||||
|
@ -456,7 +456,7 @@ impl<'b> Resolver<'b> {
|
||||
self.define(parent, name, TypeNS, (module, DUMMY_SP, vis));
|
||||
|
||||
// If this is a trait, add all the trait item names to the trait info.
|
||||
let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id);
|
||||
let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
|
||||
for trait_item_def_id in trait_item_def_ids {
|
||||
let trait_item_name = self.session.cstore.def_key(trait_item_def_id)
|
||||
.disambiguated_data.data.get_opt_name()
|
||||
|
@ -596,7 +596,6 @@ impl<'a> Visitor for Resolver<'a> {
|
||||
fn visit_fn(&mut self,
|
||||
function_kind: FnKind,
|
||||
declaration: &FnDecl,
|
||||
block: &Block,
|
||||
_: Span,
|
||||
node_id: NodeId) {
|
||||
let rib_kind = match function_kind {
|
||||
@ -604,13 +603,45 @@ impl<'a> Visitor for Resolver<'a> {
|
||||
self.visit_generics(generics);
|
||||
ItemRibKind
|
||||
}
|
||||
FnKind::Method(_, sig, _) => {
|
||||
FnKind::Method(_, sig, _, _) => {
|
||||
self.visit_generics(&sig.generics);
|
||||
MethodRibKind(!sig.decl.has_self())
|
||||
}
|
||||
FnKind::Closure => ClosureRibKind(node_id),
|
||||
FnKind::Closure(_) => ClosureRibKind(node_id),
|
||||
};
|
||||
self.resolve_function(rib_kind, declaration, block);
|
||||
|
||||
// Create a value rib for the function.
|
||||
self.value_ribs.push(Rib::new(rib_kind));
|
||||
|
||||
// Create a label rib for the function.
|
||||
self.label_ribs.push(Rib::new(rib_kind));
|
||||
|
||||
// Add each argument to the rib.
|
||||
let mut bindings_list = FxHashMap();
|
||||
for argument in &declaration.inputs {
|
||||
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
||||
|
||||
self.visit_ty(&argument.ty);
|
||||
|
||||
debug!("(resolving function) recorded argument");
|
||||
}
|
||||
visit::walk_fn_ret_ty(self, &declaration.output);
|
||||
|
||||
// Resolve the function body.
|
||||
match function_kind {
|
||||
FnKind::ItemFn(.., body) |
|
||||
FnKind::Method(.., body) => {
|
||||
self.visit_block(body);
|
||||
}
|
||||
FnKind::Closure(body) => {
|
||||
self.visit_expr(body);
|
||||
}
|
||||
};
|
||||
|
||||
debug!("(resolving function) leaving function");
|
||||
|
||||
self.label_ribs.pop();
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1856,36 +1887,6 @@ impl<'a> Resolver<'a> {
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
|
||||
fn resolve_function(&mut self,
|
||||
rib_kind: RibKind<'a>,
|
||||
declaration: &FnDecl,
|
||||
block: &Block) {
|
||||
// Create a value rib for the function.
|
||||
self.value_ribs.push(Rib::new(rib_kind));
|
||||
|
||||
// Create a label rib for the function.
|
||||
self.label_ribs.push(Rib::new(rib_kind));
|
||||
|
||||
// Add each argument to the rib.
|
||||
let mut bindings_list = FxHashMap();
|
||||
for argument in &declaration.inputs {
|
||||
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
||||
|
||||
self.visit_ty(&argument.ty);
|
||||
|
||||
debug!("(resolving function) recorded argument");
|
||||
}
|
||||
visit::walk_fn_ret_ty(self, &declaration.output);
|
||||
|
||||
// Resolve the function body.
|
||||
self.visit_block(block);
|
||||
|
||||
debug!("(resolving function) leaving function");
|
||||
|
||||
self.label_ribs.pop();
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
|
||||
fn resolve_trait_reference(&mut self,
|
||||
id: NodeId,
|
||||
trait_path: &Path,
|
||||
|
@ -32,7 +32,7 @@ use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::hir::map::{Node, NodeItem};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer};
|
||||
use rustc::ty::{self, TyCtxt, AssociatedItemContainer};
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
@ -402,19 +402,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
// with the right name.
|
||||
if !self.span.filter_generated(Some(method_data.span), span) {
|
||||
let container =
|
||||
self.tcx.impl_or_trait_item(self.tcx.map.local_def_id(id)).container();
|
||||
self.tcx.associated_item(self.tcx.map.local_def_id(id)).container;
|
||||
let mut trait_id;
|
||||
let mut decl_id = None;
|
||||
match container {
|
||||
ImplOrTraitItemContainer::ImplContainer(id) => {
|
||||
AssociatedItemContainer::ImplContainer(id) => {
|
||||
trait_id = self.tcx.trait_id_of_impl(id);
|
||||
|
||||
match trait_id {
|
||||
Some(id) => {
|
||||
for item in &**self.tcx.trait_items(id) {
|
||||
if let &ImplOrTraitItem::MethodTraitItem(ref m) = item {
|
||||
if m.name == name {
|
||||
decl_id = Some(m.def_id);
|
||||
for item in self.tcx.associated_items(id) {
|
||||
if item.kind == ty::AssociatedKind::Method {
|
||||
if item.name == name {
|
||||
decl_id = Some(item.def_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ImplOrTraitItemContainer::TraitContainer(id) => {
|
||||
AssociatedItemContainer::TraitContainer(id) => {
|
||||
trait_id = Some(id);
|
||||
}
|
||||
}
|
||||
@ -916,11 +916,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
// Modules or types in the path prefix.
|
||||
match self.tcx.expect_def(id) {
|
||||
Def::Method(did) => {
|
||||
let ti = self.tcx.impl_or_trait_item(did);
|
||||
if let ty::MethodTraitItem(m) = ti {
|
||||
if m.explicit_self == ty::ExplicitSelfCategory::Static {
|
||||
self.write_sub_path_trait_truncated(path);
|
||||
}
|
||||
let ti = self.tcx.associated_item(did);
|
||||
if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument {
|
||||
self.write_sub_path_trait_truncated(path);
|
||||
}
|
||||
}
|
||||
Def::Fn(..) |
|
||||
@ -1414,7 +1412,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
|
||||
}
|
||||
|
||||
// walk the body
|
||||
self.nest(ex.id, |v| v.visit_block(&body));
|
||||
self.nest(ex.id, |v| v.visit_expr(body));
|
||||
}
|
||||
ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
|
||||
ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {
|
||||
|
@ -313,7 +313,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
name: ast::Name, span: Span) -> Option<FunctionData> {
|
||||
// The qualname for a method is the trait name or name of the struct in an impl in
|
||||
// which the method is declared in, followed by the method's name.
|
||||
let (qualname, parent_scope, vis, docs) =
|
||||
let (qualname, parent_scope, decl_id, vis, docs) =
|
||||
match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
|
||||
Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
|
||||
Some(NodeItem(item)) => {
|
||||
@ -323,12 +323,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
result.push_str(&rustc::hir::print::ty_to_string(&ty));
|
||||
|
||||
let trait_id = self.tcx.trait_id_of_impl(impl_id);
|
||||
let mut decl_id = None;
|
||||
if let Some(def_id) = trait_id {
|
||||
result.push_str(" as ");
|
||||
result.push_str(&self.tcx.item_path_str(def_id));
|
||||
self.tcx.associated_items(def_id)
|
||||
.find(|item| item.name == name)
|
||||
.map(|item| decl_id = Some(item.def_id));
|
||||
}
|
||||
result.push_str(">");
|
||||
(result, trait_id, From::from(&item.vis), docs_for_attrs(&item.attrs))
|
||||
|
||||
(result, trait_id, decl_id,
|
||||
From::from(&item.vis),
|
||||
docs_for_attrs(&item.attrs))
|
||||
}
|
||||
_ => {
|
||||
span_bug!(span,
|
||||
@ -351,7 +358,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
match self.tcx.map.get_if_local(def_id) {
|
||||
Some(NodeItem(item)) => {
|
||||
(format!("::{}", self.tcx.item_path_str(def_id)),
|
||||
Some(def_id),
|
||||
Some(def_id), None,
|
||||
From::from(&item.vis),
|
||||
docs_for_attrs(&item.attrs))
|
||||
}
|
||||
@ -373,15 +380,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
|
||||
let qualname = format!("{}::{}", qualname, name);
|
||||
|
||||
let def_id = self.tcx.map.local_def_id(id);
|
||||
let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_def_id| {
|
||||
if new_def_id != def_id {
|
||||
Some(new_def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
|
||||
filter!(self.span_utils, sub_span, span, None);
|
||||
Some(FunctionData {
|
||||
@ -473,7 +471,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
ast::ExprKind::MethodCall(..) => {
|
||||
let method_call = ty::MethodCall::expr(expr.id);
|
||||
let method_id = self.tcx.tables().method_map[&method_call].def_id;
|
||||
let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() {
|
||||
let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
|
||||
ty::ImplContainer(_) => (Some(method_id), None),
|
||||
ty::TraitContainer(_) => (None, Some(method_id)),
|
||||
};
|
||||
@ -535,21 +533,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
|
||||
filter!(self.span_utils, sub_span, path.span, None);
|
||||
let def_id = if decl_id.is_local() {
|
||||
let ti = self.tcx.impl_or_trait_item(decl_id);
|
||||
match ti.container() {
|
||||
ty::TraitContainer(def_id) => {
|
||||
self.tcx
|
||||
.trait_items(def_id)
|
||||
.iter()
|
||||
.find(|mr| mr.name() == ti.name() && self.trait_method_has_body(mr))
|
||||
.map(|mr| mr.def_id())
|
||||
}
|
||||
ty::ImplContainer(def_id) => {
|
||||
Some(*self.tcx.impl_or_trait_items(def_id).iter().find(|&&mr| {
|
||||
self.tcx.impl_or_trait_item(mr).name() == ti.name()
|
||||
}).unwrap())
|
||||
}
|
||||
}
|
||||
let ti = self.tcx.associated_item(decl_id);
|
||||
self.tcx.associated_items(ti.container.id())
|
||||
.find(|item| item.name == ti.name && item.has_value)
|
||||
.map(|item| item.def_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -582,20 +569,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool {
|
||||
let def_id = mr.def_id();
|
||||
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
|
||||
let trait_item = self.tcx.map.expect_trait_item(node_id);
|
||||
if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field_ref_data(&self,
|
||||
field_ref: &ast::Field,
|
||||
variant: ty::VariantDef,
|
||||
|
@ -844,17 +844,12 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
param_substs);
|
||||
|
||||
if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) {
|
||||
match scx.tcx().impl_or_trait_item(fn_def_id) {
|
||||
ty::MethodTraitItem(ref method) => {
|
||||
debug!(" => trait method, attempting to find impl");
|
||||
do_static_trait_method_dispatch(scx,
|
||||
method,
|
||||
trait_def_id,
|
||||
fn_substs,
|
||||
param_substs)
|
||||
}
|
||||
_ => bug!()
|
||||
}
|
||||
debug!(" => trait method, attempting to find impl");
|
||||
do_static_trait_method_dispatch(scx,
|
||||
&scx.tcx().associated_item(fn_def_id),
|
||||
trait_def_id,
|
||||
fn_substs,
|
||||
param_substs)
|
||||
} else {
|
||||
debug!(" => regular function");
|
||||
// The function is not part of an impl or trait, no dispatching
|
||||
@ -866,7 +861,7 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
// Given a trait-method and substitution information, find out the actual
|
||||
// implementation of the trait method.
|
||||
fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
trait_method: &ty::Method,
|
||||
trait_method: &ty::AssociatedItem,
|
||||
trait_id: DefId,
|
||||
callee_substs: &'tcx Substs<'tcx>,
|
||||
param_substs: &'tcx Substs<'tcx>)
|
||||
@ -1187,7 +1182,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
|
||||
continue;
|
||||
}
|
||||
|
||||
if !method.generics.types.is_empty() {
|
||||
if !tcx.lookup_generics(method.def_id).types.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -248,13 +248,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
|
||||
if let traits::VtableImpl(vtable_impl) = vtable {
|
||||
let name = ccx.tcx().item_name(instance.def);
|
||||
let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id)
|
||||
.iter().filter_map(|&def_id| {
|
||||
match ccx.tcx().impl_or_trait_item(def_id) {
|
||||
ty::ConstTraitItem(ac) => Some(ac),
|
||||
_ => None
|
||||
}
|
||||
}).find(|ic| ic.name == name);
|
||||
let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id)
|
||||
.find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
|
||||
if let Some(ac) = ac {
|
||||
instance = Instance::new(ac.def_id, vtable_impl.substs);
|
||||
}
|
||||
|
@ -107,11 +107,6 @@ pub trait AstConv<'gcx, 'tcx> {
|
||||
fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
|
||||
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
|
||||
|
||||
/// Returns true if the trait with id `trait_def_id` defines an
|
||||
/// associated type with the name `name`.
|
||||
fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Name)
|
||||
-> bool;
|
||||
|
||||
/// Return an (optional) substitution to convert bound type parameters that
|
||||
/// are in scope into free ones. This function should only return Some
|
||||
/// within a fn body.
|
||||
@ -831,6 +826,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
Some(self_ty))
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(&self,
|
||||
trait_def_id: DefId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
self.tcx().associated_items(trait_def_id).any(|item| {
|
||||
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
|
||||
})
|
||||
}
|
||||
|
||||
fn ast_type_binding_to_poly_projection_predicate(
|
||||
&self,
|
||||
path_id: ast::NodeId,
|
||||
@ -1144,20 +1149,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
let mut associated_types = FxHashSet::default();
|
||||
for tr in traits::supertraits(tcx, principal) {
|
||||
if let Some(trait_id) = tcx.map.as_local_node_id(tr.def_id()) {
|
||||
use collect::trait_associated_type_names;
|
||||
|
||||
associated_types.extend(trait_associated_type_names(tcx, trait_id)
|
||||
.map(|name| (tr.def_id(), name)))
|
||||
} else {
|
||||
let trait_items = tcx.impl_or_trait_items(tr.def_id());
|
||||
associated_types.extend(trait_items.iter().filter_map(|&def_id| {
|
||||
match tcx.impl_or_trait_item(def_id) {
|
||||
ty::TypeTraitItem(ref item) => Some(item.name),
|
||||
_ => None
|
||||
}
|
||||
}).map(|name| (tr.def_id(), name)));
|
||||
}
|
||||
associated_types.extend(tcx.associated_items(tr.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.map(|item| (tr.def_id(), item.name)));
|
||||
}
|
||||
|
||||
for projection_bound in &projection_bounds {
|
||||
@ -1260,14 +1254,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
if bounds.len() > 1 {
|
||||
let spans = bounds.iter().map(|b| {
|
||||
self.tcx().impl_or_trait_items(b.def_id()).iter()
|
||||
.find(|&&def_id| {
|
||||
match self.tcx().impl_or_trait_item(def_id) {
|
||||
ty::TypeTraitItem(ref item) => item.name.as_str() == assoc_name,
|
||||
_ => false
|
||||
}
|
||||
self.tcx().associated_items(b.def_id()).find(|item| {
|
||||
item.kind == ty::AssociatedKind::Type && item.name.as_str() == assoc_name
|
||||
})
|
||||
.and_then(|&def_id| self.tcx().map.as_local_node_id(def_id))
|
||||
.and_then(|item| self.tcx().map.as_local_node_id(item.def_id))
|
||||
.and_then(|node_id| self.tcx().map.opt_span(node_id))
|
||||
});
|
||||
|
||||
@ -1383,25 +1373,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
let trait_did = bound.0.def_id;
|
||||
let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
|
||||
|
||||
let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) {
|
||||
// `ty::trait_items` used below requires information generated
|
||||
// by type collection, which may be in progress at this point.
|
||||
match tcx.map.expect_item(trait_id).node {
|
||||
hir::ItemTrait(.., ref trait_items) => {
|
||||
let item = trait_items.iter()
|
||||
.find(|i| i.name == assoc_name)
|
||||
.expect("missing associated type");
|
||||
tcx.map.local_def_id(item.id)
|
||||
}
|
||||
_ => bug!()
|
||||
}
|
||||
} else {
|
||||
let trait_items = tcx.trait_items(trait_did);
|
||||
let item = trait_items.iter().find(|i| i.name() == assoc_name);
|
||||
item.expect("missing associated type").def_id()
|
||||
};
|
||||
|
||||
(ty, Def::AssociatedTy(item_did))
|
||||
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name);
|
||||
(ty, Def::AssociatedTy(item.expect("missing associated type").def_id))
|
||||
}
|
||||
|
||||
fn qpath_to_ty(&self,
|
||||
@ -1694,13 +1667,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
hir::TyBareFn(ref bf) => {
|
||||
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
|
||||
let anon_scope = rscope.anon_type_scope();
|
||||
let (bare_fn_ty, _) =
|
||||
self.ty_of_method_or_bare_fn(bf.unsafety,
|
||||
bf.abi,
|
||||
None,
|
||||
&bf.decl,
|
||||
anon_scope,
|
||||
anon_scope);
|
||||
let bare_fn_ty = self.ty_of_method_or_bare_fn(bf.unsafety,
|
||||
bf.abi,
|
||||
None,
|
||||
&bf.decl,
|
||||
anon_scope,
|
||||
anon_scope);
|
||||
|
||||
// Find any late-bound regions declared in return type that do
|
||||
// not appear in the arguments. These are not wellformed.
|
||||
@ -1842,7 +1814,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
sig: &hir::MethodSig,
|
||||
untransformed_self_ty: Ty<'tcx>,
|
||||
anon_scope: Option<AnonTypeScope>)
|
||||
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>) {
|
||||
-> &'tcx ty::BareFnTy<'tcx> {
|
||||
self.ty_of_method_or_bare_fn(sig.unsafety,
|
||||
sig.abi,
|
||||
Some(untransformed_self_ty),
|
||||
@ -1857,7 +1829,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
decl: &hir::FnDecl,
|
||||
anon_scope: Option<AnonTypeScope>)
|
||||
-> &'tcx ty::BareFnTy<'tcx> {
|
||||
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
|
||||
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope)
|
||||
}
|
||||
|
||||
fn ty_of_method_or_bare_fn(&self,
|
||||
@ -1867,7 +1839,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
decl: &hir::FnDecl,
|
||||
arg_anon_scope: Option<AnonTypeScope>,
|
||||
ret_anon_scope: Option<AnonTypeScope>)
|
||||
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>)
|
||||
-> &'tcx ty::BareFnTy<'tcx>
|
||||
{
|
||||
debug!("ty_of_method_or_bare_fn");
|
||||
|
||||
@ -1880,13 +1852,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
// lifetime elision, we can determine it in two ways. First (determined
|
||||
// here), if self is by-reference, then the implied output region is the
|
||||
// region of the self parameter.
|
||||
let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) {
|
||||
let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) {
|
||||
(Some(untransformed_self_ty), Some(explicit_self)) => {
|
||||
let self_type = self.determine_self_type(&rb, untransformed_self_ty,
|
||||
&explicit_self);
|
||||
(Some(self_type.0), self_type.1)
|
||||
(Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type)))
|
||||
}
|
||||
_ => (None, ty::ExplicitSelfCategory::Static),
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
// HACK(eddyb) replace the fake self type in the AST with the actual type.
|
||||
@ -1901,8 +1873,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
// Second, if there was exactly one lifetime (either a substitution or a
|
||||
// reference) in the arguments, then any anonymous regions in the output
|
||||
// have that lifetime.
|
||||
let implied_output_region = match explicit_self_category {
|
||||
ty::ExplicitSelfCategory::ByReference(region, _) => Ok(*region),
|
||||
let implied_output_region = match explicit_self {
|
||||
Some(ExplicitSelf::ByReference(region, _)) => Ok(*region),
|
||||
_ => {
|
||||
// `pat_to_string` is expensive and
|
||||
// `find_implied_output_region` only needs its result when
|
||||
@ -1928,7 +1900,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
debug!("ty_of_method_or_bare_fn: input_tys={:?}", input_tys);
|
||||
debug!("ty_of_method_or_bare_fn: output_ty={:?}", output_ty);
|
||||
|
||||
(self.tcx().mk_bare_fn(ty::BareFnTy {
|
||||
self.tcx().mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: unsafety,
|
||||
abi: abi,
|
||||
sig: ty::Binder(ty::FnSig {
|
||||
@ -1936,95 +1908,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
output: output_ty,
|
||||
variadic: decl.variadic
|
||||
}),
|
||||
}), explicit_self_category)
|
||||
})
|
||||
}
|
||||
|
||||
fn determine_self_type<'a>(&self,
|
||||
rscope: &RegionScope,
|
||||
untransformed_self_ty: Ty<'tcx>,
|
||||
explicit_self: &hir::ExplicitSelf)
|
||||
-> (Ty<'tcx>, ty::ExplicitSelfCategory<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
return match explicit_self.node {
|
||||
SelfKind::Value(..) => {
|
||||
(untransformed_self_ty, ty::ExplicitSelfCategory::ByValue)
|
||||
}
|
||||
match explicit_self.node {
|
||||
SelfKind::Value(..) => untransformed_self_ty,
|
||||
SelfKind::Region(ref lifetime, mutability) => {
|
||||
let region =
|
||||
self.opt_ast_region_to_region(
|
||||
rscope,
|
||||
explicit_self.span,
|
||||
lifetime);
|
||||
(self.tcx().mk_ref(region,
|
||||
self.tcx().mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: untransformed_self_ty,
|
||||
mutbl: mutability
|
||||
}),
|
||||
ty::ExplicitSelfCategory::ByReference(region, mutability))
|
||||
}
|
||||
SelfKind::Explicit(ref ast_type, _) => {
|
||||
let explicit_type = self.ast_ty_to_ty(rscope, &ast_type);
|
||||
|
||||
// We wish to (for now) categorize an explicit self
|
||||
// declaration like `self: SomeType` into either `self`,
|
||||
// `&self`, `&mut self`, or `Box<self>`. We do this here
|
||||
// by some simple pattern matching. A more precise check
|
||||
// is done later in `check_method_self_type()`.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ```
|
||||
// impl Foo for &T {
|
||||
// // Legal declarations:
|
||||
// fn method1(self: &&T); // ExplicitSelfCategory::ByReference
|
||||
// fn method2(self: &T); // ExplicitSelfCategory::ByValue
|
||||
// fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
|
||||
//
|
||||
// // Invalid cases will be caught later by `check_method_self_type`:
|
||||
// fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// To do the check we just count the number of "modifiers"
|
||||
// on each type and compare them. If they are the same or
|
||||
// the impl has more, we call it "by value". Otherwise, we
|
||||
// look at the outermost modifier on the method decl and
|
||||
// call it by-ref, by-box as appropriate. For method1, for
|
||||
// example, the impl type has one modifier, but the method
|
||||
// type has two, so we end up with
|
||||
// ExplicitSelfCategory::ByReference.
|
||||
|
||||
let impl_modifiers = count_modifiers(untransformed_self_ty);
|
||||
let method_modifiers = count_modifiers(explicit_type);
|
||||
|
||||
debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
|
||||
explicit_type={:?} \
|
||||
modifiers=({},{})",
|
||||
untransformed_self_ty,
|
||||
explicit_type,
|
||||
impl_modifiers,
|
||||
method_modifiers);
|
||||
|
||||
let category = if impl_modifiers >= method_modifiers {
|
||||
ty::ExplicitSelfCategory::ByValue
|
||||
} else {
|
||||
match explicit_type.sty {
|
||||
ty::TyRef(r, mt) => ty::ExplicitSelfCategory::ByReference(r, mt.mutbl),
|
||||
ty::TyBox(_) => ty::ExplicitSelfCategory::ByBox,
|
||||
_ => ty::ExplicitSelfCategory::ByValue,
|
||||
}
|
||||
};
|
||||
|
||||
(explicit_type, category)
|
||||
}
|
||||
};
|
||||
|
||||
fn count_modifiers(ty: Ty) -> usize {
|
||||
match ty.sty {
|
||||
ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
|
||||
ty::TyBox(t) => count_modifiers(t) + 1,
|
||||
_ => 0,
|
||||
})
|
||||
}
|
||||
SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2334,3 +2241,64 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ExplicitSelf<'tcx> {
|
||||
ByValue,
|
||||
ByReference(&'tcx ty::Region, hir::Mutability),
|
||||
ByBox
|
||||
}
|
||||
|
||||
impl<'tcx> ExplicitSelf<'tcx> {
|
||||
/// We wish to (for now) categorize an explicit self
|
||||
/// declaration like `self: SomeType` into either `self`,
|
||||
/// `&self`, `&mut self`, or `Box<self>`. We do this here
|
||||
/// by some simple pattern matching. A more precise check
|
||||
/// is done later in `check_method_self_type()`.
|
||||
///
|
||||
/// Examples:
|
||||
///
|
||||
/// ```
|
||||
/// impl Foo for &T {
|
||||
/// // Legal declarations:
|
||||
/// fn method1(self: &&T); // ExplicitSelf::ByReference
|
||||
/// fn method2(self: &T); // ExplicitSelf::ByValue
|
||||
/// fn method3(self: Box<&T>); // ExplicitSelf::ByBox
|
||||
///
|
||||
/// // Invalid cases will be caught later by `check_method_self_type`:
|
||||
/// fn method_err1(self: &mut T); // ExplicitSelf::ByReference
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// To do the check we just count the number of "modifiers"
|
||||
/// on each type and compare them. If they are the same or
|
||||
/// the impl has more, we call it "by value". Otherwise, we
|
||||
/// look at the outermost modifier on the method decl and
|
||||
/// call it by-ref, by-box as appropriate. For method1, for
|
||||
/// example, the impl type has one modifier, but the method
|
||||
/// type has two, so we end up with
|
||||
/// ExplicitSelf::ByReference.
|
||||
pub fn determine(untransformed_self_ty: Ty<'tcx>,
|
||||
self_arg_ty: Ty<'tcx>)
|
||||
-> ExplicitSelf<'tcx> {
|
||||
fn count_modifiers(ty: Ty) -> usize {
|
||||
match ty.sty {
|
||||
ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
|
||||
ty::TyBox(t) => count_modifiers(t) + 1,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
let impl_modifiers = count_modifiers(untransformed_self_ty);
|
||||
let method_modifiers = count_modifiers(self_arg_ty);
|
||||
|
||||
if impl_modifiers >= method_modifiers {
|
||||
ExplicitSelf::ByValue
|
||||
} else {
|
||||
match self_arg_ty.sty {
|
||||
ty::TyRef(r, mt) => ExplicitSelf::ByReference(r, mt.mutbl),
|
||||
ty::TyBox(_) => ExplicitSelf::ByBox,
|
||||
_ => ExplicitSelf::ByValue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
|
||||
use check::{FnCtxt, Expectation};
|
||||
use check::{FnCtxt, Expectation, Diverges};
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
@ -360,9 +360,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn check_match(&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
discrim: &'gcx hir::Expr,
|
||||
@ -390,14 +388,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
discrim_ty = self.next_ty_var();
|
||||
self.check_expr_has_type(discrim, discrim_ty);
|
||||
};
|
||||
let discrim_diverges = self.diverges.get();
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
|
||||
// Typecheck the patterns first, so that we get types for all the
|
||||
// bindings.
|
||||
for arm in arms {
|
||||
let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
|
||||
let mut all_pats_diverge = Diverges::WarnedAlways;
|
||||
for p in &arm.pats {
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
self.check_pat(&p, discrim_ty);
|
||||
all_pats_diverge &= self.diverges.get();
|
||||
}
|
||||
}
|
||||
all_pats_diverge
|
||||
}).collect();
|
||||
|
||||
// Now typecheck the blocks.
|
||||
//
|
||||
@ -410,6 +414,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// type in that case)
|
||||
let expected = expected.adjust_for_branches(self);
|
||||
let mut result_ty = self.next_diverging_ty_var();
|
||||
let mut all_arms_diverge = Diverges::WarnedAlways;
|
||||
let coerce_first = match expected {
|
||||
// We don't coerce to `()` so that if the match expression is a
|
||||
// statement it's branches can have any consistent type. That allows
|
||||
@ -422,11 +427,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
_ => result_ty
|
||||
};
|
||||
|
||||
for (i, arm) in arms.iter().enumerate() {
|
||||
for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
|
||||
if let Some(ref e) = arm.guard {
|
||||
self.diverges.set(pats_diverge);
|
||||
self.check_expr_has_type(e, tcx.types.bool);
|
||||
}
|
||||
|
||||
self.diverges.set(pats_diverge);
|
||||
let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
|
||||
all_arms_diverge &= self.diverges.get();
|
||||
|
||||
if result_ty.references_error() || arm_ty.references_error() {
|
||||
result_ty = tcx.types.err;
|
||||
@ -476,11 +485,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
}
|
||||
|
||||
// We won't diverge unless the discriminant or all arms diverge.
|
||||
self.diverges.set(discrim_diverges | all_arms_diverge);
|
||||
|
||||
result_ty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn check_pat_struct(&self,
|
||||
pat: &'gcx hir::Pat,
|
||||
path: &hir::Path,
|
||||
|
@ -23,7 +23,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
expr: &hir::Expr,
|
||||
_capture: hir::CaptureClause,
|
||||
decl: &'gcx hir::FnDecl,
|
||||
body: &'gcx hir::Block,
|
||||
body: &'gcx hir::Expr,
|
||||
expected: Expectation<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
debug!("check_expr_closure(expr={:?},expected={:?})",
|
||||
@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
expr: &hir::Expr,
|
||||
opt_kind: Option<ty::ClosureKind>,
|
||||
decl: &'gcx hir::FnDecl,
|
||||
body: &'gcx hir::Block,
|
||||
body: &'gcx hir::Expr,
|
||||
expected_sig: Option<ty::FnSig<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
let expr_def_id = self.tcx.map.local_def_id(expr.id);
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::ty;
|
||||
@ -23,6 +24,7 @@ use syntax_pos::Span;
|
||||
use CrateCtxt;
|
||||
use super::assoc;
|
||||
use super::{Inherited, FnCtxt};
|
||||
use astconv::ExplicitSelf;
|
||||
|
||||
/// Checks that a method from an impl conforms to the signature of
|
||||
/// the same method as declared in the trait.
|
||||
@ -36,11 +38,11 @@ use super::{Inherited, FnCtxt};
|
||||
/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
|
||||
|
||||
pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::Method<'tcx>,
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
trait_item_span: Option<Span>,
|
||||
old_broken_mode: bool) {
|
||||
debug!("compare_impl_method(impl_trait_ref={:?})",
|
||||
@ -49,7 +51,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
if let Err(ErrorReported) = compare_self_type(ccx,
|
||||
impl_m,
|
||||
impl_m_span,
|
||||
trait_m) {
|
||||
trait_m,
|
||||
impl_trait_ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -81,16 +84,16 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::Method<'tcx>,
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
old_broken_mode: bool)
|
||||
-> Result<(), ErrorReported> {
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
let trait_to_impl_substs = &impl_trait_ref.substs;
|
||||
let trait_to_impl_substs = impl_trait_ref.substs;
|
||||
|
||||
// This code is best explained by example. Consider a trait:
|
||||
//
|
||||
@ -165,18 +168,23 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
// Create mapping from trait to skolemized.
|
||||
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
|
||||
impl_m.container_id(),
|
||||
impl_m.container.id(),
|
||||
trait_to_impl_substs.subst(tcx,
|
||||
impl_to_skol_substs));
|
||||
debug!("compare_impl_method: trait_to_skol_substs={:?}",
|
||||
trait_to_skol_substs);
|
||||
|
||||
let impl_m_generics = tcx.lookup_generics(impl_m.def_id);
|
||||
let trait_m_generics = tcx.lookup_generics(trait_m.def_id);
|
||||
let impl_m_predicates = tcx.lookup_predicates(impl_m.def_id);
|
||||
let trait_m_predicates = tcx.lookup_predicates(trait_m.def_id);
|
||||
|
||||
// Check region bounds.
|
||||
check_region_bounds_on_impl_method(ccx,
|
||||
impl_m_span,
|
||||
impl_m,
|
||||
&trait_m.generics,
|
||||
&impl_m.generics,
|
||||
&trait_m_generics,
|
||||
&impl_m_generics,
|
||||
trait_to_skol_substs,
|
||||
impl_to_skol_substs)?;
|
||||
|
||||
@ -185,7 +193,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
// environment. We can't just use `impl_env.caller_bounds`,
|
||||
// however, because we want to replace all late-bound regions with
|
||||
// region variables.
|
||||
let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
|
||||
let impl_predicates = tcx.lookup_predicates(impl_m_predicates.parent.unwrap());
|
||||
let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
|
||||
|
||||
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
|
||||
@ -198,7 +206,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
// We then register the obligations from the impl_m and check to see
|
||||
// if all constraints hold.
|
||||
hybrid_preds.predicates
|
||||
.extend(trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
|
||||
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
|
||||
|
||||
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
|
||||
// The key step here is to update the caller_bounds's predicates to be
|
||||
@ -219,7 +227,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
|
||||
let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
|
||||
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
|
||||
let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
|
||||
infer::HigherRankedType,
|
||||
&ty::Binder(impl_m_own_bounds.predicates));
|
||||
@ -260,10 +268,19 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let tcx = infcx.tcx;
|
||||
let origin = TypeOrigin::MethodCompatCheck(impl_m_span);
|
||||
|
||||
let m_fty = |method: &ty::AssociatedItem| {
|
||||
match tcx.lookup_item_type(method.def_id).ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => bug!()
|
||||
}
|
||||
};
|
||||
let impl_m_fty = m_fty(impl_m);
|
||||
let trait_m_fty = m_fty(trait_m);
|
||||
|
||||
let (impl_sig, _) =
|
||||
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
|
||||
infer::HigherRankedType,
|
||||
&impl_m.fty.sig);
|
||||
&impl_m_fty.sig);
|
||||
let impl_sig =
|
||||
impl_sig.subst(tcx, impl_to_skol_substs);
|
||||
let impl_sig =
|
||||
@ -273,15 +290,15 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m_body_id,
|
||||
&impl_sig);
|
||||
let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: impl_m.fty.unsafety,
|
||||
abi: impl_m.fty.abi,
|
||||
unsafety: impl_m_fty.unsafety,
|
||||
abi: impl_m_fty.abi,
|
||||
sig: ty::Binder(impl_sig.clone()),
|
||||
}));
|
||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||
|
||||
let trait_sig = tcx.liberate_late_bound_regions(
|
||||
infcx.parameter_environment.free_id_outlive,
|
||||
&trait_m.fty.sig);
|
||||
&trait_m_fty.sig);
|
||||
let trait_sig =
|
||||
trait_sig.subst(tcx, trait_to_skol_substs);
|
||||
let trait_sig =
|
||||
@ -291,8 +308,8 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m_body_id,
|
||||
&trait_sig);
|
||||
let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: trait_m.fty.unsafety,
|
||||
abi: trait_m.fty.abi,
|
||||
unsafety: trait_m_fty.unsafety,
|
||||
abi: trait_m_fty.abi,
|
||||
sig: ty::Binder(trait_sig.clone()),
|
||||
}));
|
||||
|
||||
@ -367,7 +384,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
trait_generics: &ty::Generics<'tcx>,
|
||||
impl_generics: &ty::Generics<'tcx>,
|
||||
trait_to_skol_substs: &Substs<'tcx>,
|
||||
@ -413,9 +430,9 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||
terr: &TypeError,
|
||||
origin: TypeOrigin,
|
||||
impl_m: &ty::Method,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_sig: ty::FnSig<'tcx>,
|
||||
trait_m: &ty::Method,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
trait_sig: ty::FnSig<'tcx>)
|
||||
-> (Span, Option<Span>) {
|
||||
let tcx = infcx.tcx;
|
||||
@ -505,9 +522,10 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
|
||||
}
|
||||
|
||||
fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
trait_m: &ty::Method<'tcx>)
|
||||
trait_m: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>)
|
||||
-> Result<(), ErrorReported>
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
@ -518,58 +536,75 @@ fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
// that the error messages you get out of this code are a bit more
|
||||
// inscrutable, particularly for cases where one method has no
|
||||
// self.
|
||||
match (&trait_m.explicit_self, &impl_m.explicit_self) {
|
||||
(&ty::ExplicitSelfCategory::Static, &ty::ExplicitSelfCategory::Static) => {}
|
||||
(&ty::ExplicitSelfCategory::Static, _) => {
|
||||
|
||||
let self_string = |method: &ty::AssociatedItem| {
|
||||
let untransformed_self_ty = match method.container {
|
||||
ty::ImplContainer(_) => impl_trait_ref.self_ty(),
|
||||
ty::TraitContainer(_) => tcx.mk_self_type()
|
||||
};
|
||||
let method_ty = tcx.lookup_item_type(method.def_id).ty;
|
||||
let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder();
|
||||
match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
|
||||
ExplicitSelf::ByValue => "self".to_string(),
|
||||
ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
|
||||
ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(),
|
||||
_ => format!("self: {}", self_arg_ty)
|
||||
}
|
||||
};
|
||||
|
||||
match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) {
|
||||
(false, false) | (true, true) => {}
|
||||
|
||||
(false, true) => {
|
||||
let self_descr = self_string(impl_m);
|
||||
let mut err = struct_span_err!(tcx.sess,
|
||||
impl_m_span,
|
||||
E0185,
|
||||
"method `{}` has a `{}` declaration in the impl, but \
|
||||
not in the trait",
|
||||
trait_m.name,
|
||||
impl_m.explicit_self);
|
||||
err.span_label(impl_m_span,
|
||||
&format!("`{}` used in impl", impl_m.explicit_self));
|
||||
self_descr);
|
||||
err.span_label(impl_m_span, &format!("`{}` used in impl", self_descr));
|
||||
if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
|
||||
err.span_label(span,
|
||||
&format!("trait declared without `{}`", impl_m.explicit_self));
|
||||
err.span_label(span, &format!("trait declared without `{}`", self_descr));
|
||||
}
|
||||
err.emit();
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
(_, &ty::ExplicitSelfCategory::Static) => {
|
||||
|
||||
(true, false) => {
|
||||
let self_descr = self_string(trait_m);
|
||||
let mut err = struct_span_err!(tcx.sess,
|
||||
impl_m_span,
|
||||
E0186,
|
||||
"method `{}` has a `{}` declaration in the trait, but \
|
||||
not in the impl",
|
||||
trait_m.name,
|
||||
trait_m.explicit_self);
|
||||
self_descr);
|
||||
err.span_label(impl_m_span,
|
||||
&format!("expected `{}` in impl", trait_m.explicit_self));
|
||||
&format!("expected `{}` in impl", self_descr));
|
||||
if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
|
||||
err.span_label(span, &format!("`{}` used in trait", trait_m.explicit_self));
|
||||
err.span_label(span, &format!("`{}` used in trait", self_descr));
|
||||
}
|
||||
err.emit();
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
_ => {
|
||||
// Let the type checker catch other errors below
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
trait_m: &ty::Method<'tcx>,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
trait_item_span: Option<Span>)
|
||||
-> Result<(), ErrorReported> {
|
||||
let tcx = ccx.tcx;
|
||||
let num_impl_m_type_params = impl_m.generics.types.len();
|
||||
let num_trait_m_type_params = trait_m.generics.types.len();
|
||||
let impl_m_generics = tcx.lookup_generics(impl_m.def_id);
|
||||
let trait_m_generics = tcx.lookup_generics(trait_m.def_id);
|
||||
let num_impl_m_type_params = impl_m_generics.types.len();
|
||||
let num_trait_m_type_params = trait_m_generics.types.len();
|
||||
if num_impl_m_type_params != num_trait_m_type_params {
|
||||
let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap();
|
||||
let span = match tcx.map.expect_impl_item(impl_m_node_id).node {
|
||||
@ -630,15 +665,23 @@ fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
trait_m: &ty::Method<'tcx>,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
trait_item_span: Option<Span>)
|
||||
-> Result<(), ErrorReported> {
|
||||
let tcx = ccx.tcx;
|
||||
if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
|
||||
let trait_number_args = trait_m.fty.sig.0.inputs.len();
|
||||
let impl_number_args = impl_m.fty.sig.0.inputs.len();
|
||||
let m_fty = |method: &ty::AssociatedItem| {
|
||||
match tcx.lookup_item_type(method.def_id).ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => bug!()
|
||||
}
|
||||
};
|
||||
let impl_m_fty = m_fty(impl_m);
|
||||
let trait_m_fty = m_fty(trait_m);
|
||||
if impl_m_fty.sig.0.inputs.len() != trait_m_fty.sig.0.inputs.len() {
|
||||
let trait_number_args = trait_m_fty.sig.0.inputs.len();
|
||||
let impl_number_args = impl_m_fty.sig.0.inputs.len();
|
||||
let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id);
|
||||
let trait_span = if let Some(trait_id) = trait_m_node_id {
|
||||
match tcx.map.expect_trait_item(trait_id).node {
|
||||
@ -708,10 +751,10 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_c: &ty::AssociatedConst<'tcx>,
|
||||
impl_c: &ty::AssociatedItem,
|
||||
impl_c_span: Span,
|
||||
trait_c: &ty::AssociatedConst<'tcx>,
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>) {
|
||||
trait_c: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>) {
|
||||
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
|
||||
|
||||
let tcx = ccx.tcx;
|
||||
@ -723,7 +766,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
// because we shouldn't really have to deal with lifetimes or
|
||||
// predicates. In fact some of this should probably be put into
|
||||
// shared functions because of DRY violations...
|
||||
let trait_to_impl_substs = &impl_trait_ref.substs;
|
||||
let trait_to_impl_substs = impl_trait_ref.substs;
|
||||
|
||||
// Create a parameter environment that represents the implementation's
|
||||
// method.
|
||||
@ -742,8 +785,8 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
trait_to_skol_substs);
|
||||
|
||||
// Compute skolemized form of impl and trait const tys.
|
||||
let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
|
||||
let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs);
|
||||
let impl_ty = tcx.lookup_item_type(impl_c.def_id).ty.subst(tcx, impl_to_skol_substs);
|
||||
let trait_ty = tcx.lookup_item_type(trait_c.def_id).ty.subst(tcx, trait_to_skol_substs);
|
||||
let mut origin = TypeOrigin::Misc(impl_c_span);
|
||||
|
||||
let err = infcx.commit_if_ok(|_| {
|
||||
|
@ -553,9 +553,9 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
// attributes attached to the impl's generics.
|
||||
let dtor_method = adt_def.destructor()
|
||||
.expect("dtorck type without destructor impossible");
|
||||
let method = tcx.impl_or_trait_item(dtor_method);
|
||||
let impl_id: DefId = method.container().id();
|
||||
let revised_ty = revise_self_ty(tcx, adt_def, impl_id, substs);
|
||||
let method = tcx.associated_item(dtor_method);
|
||||
let impl_def_id = method.container.id();
|
||||
let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
|
||||
return DropckKind::RevisedSelf(revised_ty);
|
||||
}
|
||||
ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
|
||||
|
@ -37,16 +37,6 @@ impl<'a, 'gcx, 'tcx> Deref for ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
struct InstantiatedMethodSig<'tcx> {
|
||||
/// Function signature of the method being invoked. The 0th
|
||||
/// argument is the receiver.
|
||||
method_sig: ty::FnSig<'tcx>,
|
||||
|
||||
/// Generic bounds on the method's parameters which must be added
|
||||
/// as pending obligations.
|
||||
method_predicates: ty::InstantiatedPredicates<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn confirm_method(&self,
|
||||
span: Span,
|
||||
@ -98,31 +88,18 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
debug!("all_substs={:?}", all_substs);
|
||||
|
||||
// Create the final signature for the method, replacing late-bound regions.
|
||||
let InstantiatedMethodSig { method_sig, method_predicates } =
|
||||
self.instantiate_method_sig(&pick, all_substs);
|
||||
let method_self_ty = method_sig.inputs[0];
|
||||
let (method_ty, method_predicates) = self.instantiate_method_sig(&pick, all_substs);
|
||||
|
||||
// Unify the (adjusted) self type with what the method expects.
|
||||
self.unify_receivers(self_ty, method_self_ty);
|
||||
|
||||
// Create the method type
|
||||
let def_id = pick.item.def_id();
|
||||
let method_ty = pick.item.as_opt_method().unwrap();
|
||||
let fty = self.tcx.mk_fn_def(def_id,
|
||||
all_substs,
|
||||
self.tcx.mk_bare_fn(ty::BareFnTy {
|
||||
sig: ty::Binder(method_sig),
|
||||
unsafety: method_ty.fty.unsafety,
|
||||
abi: method_ty.fty.abi.clone(),
|
||||
}));
|
||||
self.unify_receivers(self_ty, method_ty.fn_sig().input(0).skip_binder());
|
||||
|
||||
// Add any trait/regions obligations specified on the method's type parameters.
|
||||
self.add_obligations(fty, all_substs, &method_predicates);
|
||||
self.add_obligations(method_ty, all_substs, &method_predicates);
|
||||
|
||||
// Create the final `MethodCallee`.
|
||||
let callee = ty::MethodCallee {
|
||||
def_id: def_id,
|
||||
ty: fty,
|
||||
def_id: pick.item.def_id,
|
||||
ty: method_ty,
|
||||
substs: all_substs,
|
||||
};
|
||||
|
||||
@ -193,7 +170,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
-> &'tcx Substs<'tcx> {
|
||||
match pick.kind {
|
||||
probe::InherentImplPick => {
|
||||
let impl_def_id = pick.item.container().id();
|
||||
let impl_def_id = pick.item.container.id();
|
||||
assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
|
||||
"impl {:?} is not an inherent impl",
|
||||
impl_def_id);
|
||||
@ -201,7 +178,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
probe::ObjectPick => {
|
||||
let trait_def_id = pick.item.container().id();
|
||||
let trait_def_id = pick.item.container.id();
|
||||
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
|
||||
// The object data has no entry for the Self
|
||||
// Type. For the purposes of this method call, we
|
||||
@ -244,7 +221,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
probe::TraitPick => {
|
||||
let trait_def_id = pick.item.container().id();
|
||||
let trait_def_id = pick.item.container.id();
|
||||
|
||||
// Make a trait reference `$0 : Trait<$1...$n>`
|
||||
// consisting entirely of type variables. Later on in
|
||||
@ -299,8 +276,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
// variables.
|
||||
let num_supplied_types = supplied_method_types.len();
|
||||
let method = pick.item.as_opt_method().unwrap();
|
||||
let num_method_types = method.generics.types.len();
|
||||
let method_generics = self.tcx.lookup_generics(pick.item.def_id);
|
||||
let num_method_types = method_generics.types.len();
|
||||
|
||||
if num_supplied_types > 0 && num_supplied_types != num_method_types {
|
||||
if num_method_types == 0 {
|
||||
@ -332,18 +309,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
// parameters from the type and those from the method.
|
||||
//
|
||||
// FIXME -- permit users to manually specify lifetimes
|
||||
let supplied_start = substs.params().len() + method.generics.regions.len();
|
||||
Substs::for_item(self.tcx,
|
||||
method.def_id,
|
||||
|def, _| {
|
||||
let supplied_start = substs.params().len() + method_generics.regions.len();
|
||||
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
|
||||
let i = def.index as usize;
|
||||
if i < substs.params().len() {
|
||||
substs.region_at(i)
|
||||
} else {
|
||||
self.region_var_for_def(self.span, def)
|
||||
}
|
||||
},
|
||||
|def, cur_substs| {
|
||||
}, |def, cur_substs| {
|
||||
let i = def.index as usize;
|
||||
if i < substs.params().len() {
|
||||
substs.type_at(i)
|
||||
@ -376,7 +350,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
fn instantiate_method_sig(&mut self,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
all_substs: &'tcx Substs<'tcx>)
|
||||
-> InstantiatedMethodSig<'tcx> {
|
||||
-> (Ty<'tcx>, ty::InstantiatedPredicates<'tcx>) {
|
||||
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
|
||||
pick,
|
||||
all_substs);
|
||||
@ -384,36 +358,40 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
// Instantiate the bounds on the method with the
|
||||
// type/early-bound-regions substitutions performed. There can
|
||||
// be no late-bound regions appearing here.
|
||||
let method_predicates = pick.item
|
||||
.as_opt_method()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.instantiate(self.tcx, all_substs);
|
||||
let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates);
|
||||
let def_id = pick.item.def_id;
|
||||
let method_predicates = self.tcx.lookup_predicates(def_id)
|
||||
.instantiate(self.tcx, all_substs);
|
||||
let method_predicates = self.normalize_associated_types_in(self.span,
|
||||
&method_predicates);
|
||||
|
||||
debug!("method_predicates after subst = {:?}", method_predicates);
|
||||
|
||||
let fty = match self.tcx.lookup_item_type(def_id).ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => bug!()
|
||||
};
|
||||
|
||||
// Instantiate late-bound regions and substitute the trait
|
||||
// parameters into the method type to get the actual method type.
|
||||
//
|
||||
// NB: Instantiate late-bound regions first so that
|
||||
// `instantiate_type_scheme` can normalize associated types that
|
||||
// may reference those regions.
|
||||
let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.item
|
||||
.as_opt_method()
|
||||
.unwrap()
|
||||
.fty
|
||||
.sig);
|
||||
let method_sig = self.replace_late_bound_regions_with_fresh_var(&fty.sig);
|
||||
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
|
||||
method_sig);
|
||||
|
||||
let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
|
||||
debug!("type scheme substituted, method_sig={:?}", method_sig);
|
||||
|
||||
InstantiatedMethodSig {
|
||||
method_sig: method_sig,
|
||||
method_predicates: method_predicates,
|
||||
}
|
||||
let method_ty = self.tcx.mk_fn_def(def_id, all_substs,
|
||||
self.tcx.mk_bare_fn(ty::BareFnTy {
|
||||
sig: ty::Binder(method_sig),
|
||||
unsafety: fty.unsafety,
|
||||
abi: fty.abi,
|
||||
}));
|
||||
|
||||
(method_ty, method_predicates)
|
||||
}
|
||||
|
||||
fn add_obligations(&mut self,
|
||||
@ -587,7 +565,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
|
||||
// Disallow calls to the method `drop` defined in the `Drop` trait.
|
||||
match pick.item.container() {
|
||||
match pick.item.container {
|
||||
ty::TraitContainer(trait_def_id) => {
|
||||
callee::check_legal_trait_for_method_call(self.ccx, self.span, trait_def_id)
|
||||
}
|
||||
|
@ -228,14 +228,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Trait must have a method named `m_name` and it should not have
|
||||
// type parameters or early-bound regions.
|
||||
let tcx = self.tcx;
|
||||
let method_item = self.impl_or_trait_item(trait_def_id, m_name).unwrap();
|
||||
let method_ty = method_item.as_opt_method().unwrap();
|
||||
assert_eq!(method_ty.generics.types.len(), 0);
|
||||
assert_eq!(method_ty.generics.regions.len(), 0);
|
||||
let method_item = self.associated_item(trait_def_id, m_name).unwrap();
|
||||
let def_id = method_item.def_id;
|
||||
let generics = tcx.lookup_generics(def_id);
|
||||
assert_eq!(generics.types.len(), 0);
|
||||
assert_eq!(generics.regions.len(), 0);
|
||||
|
||||
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
|
||||
method_item,
|
||||
method_ty);
|
||||
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
||||
|
||||
// Instantiate late-bound regions and substitute the trait
|
||||
// parameters into the method type to get the actual method type.
|
||||
@ -243,22 +242,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// NB: Instantiate late-bound regions first so that
|
||||
// `instantiate_type_scheme` can normalize associated types that
|
||||
// may reference those regions.
|
||||
let fn_sig =
|
||||
self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig)
|
||||
.0;
|
||||
let original_method_ty = tcx.lookup_item_type(def_id).ty;
|
||||
let fty = match original_method_ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => bug!()
|
||||
};
|
||||
let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
|
||||
infer::FnCall,
|
||||
&fty.sig).0;
|
||||
let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
|
||||
let transformed_self_ty = fn_sig.inputs[0];
|
||||
let def_id = method_item.def_id();
|
||||
let fty = tcx.mk_fn_def(def_id,
|
||||
trait_ref.substs,
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
sig: ty::Binder(fn_sig),
|
||||
unsafety: method_ty.fty.unsafety,
|
||||
abi: method_ty.fty.abi.clone(),
|
||||
}));
|
||||
let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs,
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
sig: ty::Binder(fn_sig),
|
||||
unsafety: fty.unsafety,
|
||||
abi: fty.abi
|
||||
}));
|
||||
|
||||
debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
|
||||
fty,
|
||||
debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
|
||||
method_ty,
|
||||
obligation);
|
||||
|
||||
// Register obligations for the parameters. This will include the
|
||||
@ -269,13 +271,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
//
|
||||
// Note that as the method comes from a trait, it should not have
|
||||
// any late-bound regions appearing in its bounds.
|
||||
let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
|
||||
let method_bounds = self.instantiate_bounds(span, def_id, trait_ref.substs);
|
||||
assert!(!method_bounds.has_escaping_regions());
|
||||
self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
|
||||
&method_bounds);
|
||||
|
||||
// Also register an obligation for the method type being well-formed.
|
||||
self.register_wf_obligation(fty, span, traits::MiscObligation);
|
||||
self.register_wf_obligation(method_ty, span, traits::MiscObligation);
|
||||
|
||||
// FIXME(#18653) -- Try to resolve obligations, giving us more
|
||||
// typing information, which can sometimes be needed to avoid
|
||||
@ -283,61 +285,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
self.select_obligations_where_possible();
|
||||
|
||||
// Insert any adjustments needed (always an autoref of some mutability).
|
||||
match self_expr {
|
||||
None => {}
|
||||
if let Some(self_expr) = self_expr {
|
||||
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
|
||||
(self-id={}, autoderefs={}, unsize={}, fty={:?})",
|
||||
self_expr.id, autoderefs, unsize, original_method_ty);
|
||||
|
||||
Some(self_expr) => {
|
||||
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
|
||||
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
|
||||
self_expr.id,
|
||||
autoderefs,
|
||||
unsize,
|
||||
method_ty.explicit_self);
|
||||
let original_sig = original_method_ty.fn_sig();
|
||||
let autoref = match (&original_sig.input(0).skip_binder().sty,
|
||||
&transformed_self_ty.sty) {
|
||||
(&ty::TyRef(..), &ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ })) => {
|
||||
// Trait method is fn(&self) or fn(&mut self), need an
|
||||
// autoref. Pull the region etc out of the type of first argument.
|
||||
Some(AutoBorrow::Ref(region, mutbl))
|
||||
}
|
||||
_ => {
|
||||
// Trait method is fn(self), no transformation needed.
|
||||
assert!(!unsize);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let autoref = match method_ty.explicit_self {
|
||||
ty::ExplicitSelfCategory::ByValue => {
|
||||
// Trait method is fn(self), no transformation needed.
|
||||
assert!(!unsize);
|
||||
None
|
||||
}
|
||||
|
||||
ty::ExplicitSelfCategory::ByReference(..) => {
|
||||
// Trait method is fn(&self) or fn(&mut self), need an
|
||||
// autoref. Pull the region etc out of the type of first argument.
|
||||
match transformed_self_ty.sty {
|
||||
ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
|
||||
Some(AutoBorrow::Ref(region, mutbl))
|
||||
}
|
||||
|
||||
_ => {
|
||||
span_bug!(span,
|
||||
"trait method is &self but first arg is: {}",
|
||||
transformed_self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
span_bug!(span,
|
||||
"unexpected explicit self type in operator method: {:?}",
|
||||
method_ty.explicit_self);
|
||||
}
|
||||
};
|
||||
|
||||
self.write_adjustment(self_expr.id, Adjustment {
|
||||
kind: Adjust::DerefRef {
|
||||
autoderefs: autoderefs,
|
||||
autoref: autoref,
|
||||
unsize: unsize
|
||||
},
|
||||
target: transformed_self_ty
|
||||
});
|
||||
}
|
||||
self.write_adjustment(self_expr.id, Adjustment {
|
||||
kind: Adjust::DerefRef {
|
||||
autoderefs: autoderefs,
|
||||
autoref: autoref,
|
||||
unsize: unsize
|
||||
},
|
||||
target: transformed_self_ty
|
||||
});
|
||||
}
|
||||
|
||||
let callee = ty::MethodCallee {
|
||||
def_id: def_id,
|
||||
ty: fty,
|
||||
ty: method_ty,
|
||||
substs: trait_ref.substs,
|
||||
};
|
||||
|
||||
@ -361,7 +341,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
let def = pick.item.def();
|
||||
if let probe::InherentImplPick = pick.kind {
|
||||
if !pick.item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
|
||||
if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
|
||||
let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str());
|
||||
self.tcx.sess.span_err(span, &msg);
|
||||
}
|
||||
@ -371,14 +351,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
/// Find item with name `item_name` defined in impl/trait `def_id`
|
||||
/// and return it, or `None`, if no such item was defined there.
|
||||
pub fn impl_or_trait_item(&self,
|
||||
def_id: DefId,
|
||||
item_name: ast::Name)
|
||||
-> Option<ty::ImplOrTraitItem<'tcx>> {
|
||||
self.tcx
|
||||
.impl_or_trait_items(def_id)
|
||||
.iter()
|
||||
.map(|&did| self.tcx.impl_or_trait_item(did))
|
||||
.find(|m| m.name() == item_name)
|
||||
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name)
|
||||
-> Option<ty::AssociatedItem> {
|
||||
self.tcx.associated_items(def_id).find(|item| item.name == item_name)
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ struct CandidateStep<'tcx> {
|
||||
#[derive(Debug)]
|
||||
struct Candidate<'tcx> {
|
||||
xform_self_ty: Ty<'tcx>,
|
||||
item: ty::ImplOrTraitItem<'tcx>,
|
||||
item: ty::AssociatedItem,
|
||||
kind: CandidateKind<'tcx>,
|
||||
import_id: Option<ast::NodeId>,
|
||||
}
|
||||
@ -95,7 +95,7 @@ enum CandidateKind<'tcx> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Pick<'tcx> {
|
||||
pub item: ty::ImplOrTraitItem<'tcx>,
|
||||
pub item: ty::AssociatedItem,
|
||||
pub kind: PickKind<'tcx>,
|
||||
pub import_id: Option<ast::NodeId>,
|
||||
|
||||
@ -384,8 +384,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) {
|
||||
if let Some(impl_def_id) = lang_def_id {
|
||||
self.tcx.populate_implementations_for_primitive_if_necessary(impl_def_id);
|
||||
|
||||
self.assemble_inherent_impl_probe(impl_def_id);
|
||||
}
|
||||
}
|
||||
@ -409,7 +407,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
|
||||
|
||||
let item = match self.impl_or_trait_item(impl_def_id) {
|
||||
let item = match self.associated_item(impl_def_id) {
|
||||
Some(m) => m,
|
||||
None => {
|
||||
return;
|
||||
@ -421,7 +419,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
return self.record_static_candidate(ImplSource(impl_def_id));
|
||||
}
|
||||
|
||||
if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
|
||||
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
|
||||
self.private_candidate = Some(item.def());
|
||||
return;
|
||||
}
|
||||
@ -512,17 +510,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);
|
||||
|
||||
if let Some(ref m) = item.as_opt_method() {
|
||||
debug!("found match: trait_ref={:?} substs={:?} m={:?}",
|
||||
trait_ref,
|
||||
trait_ref.substs,
|
||||
m);
|
||||
assert_eq!(m.generics.parent_types as usize,
|
||||
trait_ref.substs.types().count());
|
||||
assert_eq!(m.generics.parent_regions as usize,
|
||||
trait_ref.substs.regions().count());
|
||||
}
|
||||
|
||||
// Because this trait derives from a where-clause, it
|
||||
// should not contain any inference variables or other
|
||||
// artifacts. This means it is safe to put into the
|
||||
@ -544,13 +531,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F)
|
||||
where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>,
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
ty::ImplOrTraitItem<'tcx>)
|
||||
ty::AssociatedItem)
|
||||
{
|
||||
debug!("elaborate_bounds(bounds={:?})", bounds);
|
||||
|
||||
let tcx = self.tcx;
|
||||
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
|
||||
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
|
||||
let item = match self.associated_item(bound_trait_ref.def_id()) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
continue;
|
||||
@ -601,9 +588,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
trait_def_id);
|
||||
|
||||
// Check whether `trait_def_id` defines a method with suitable name:
|
||||
let trait_items = self.tcx.trait_items(trait_def_id);
|
||||
let maybe_item = trait_items.iter()
|
||||
.find(|item| item.name() == self.item_name);
|
||||
let maybe_item = self.tcx.associated_items(trait_def_id)
|
||||
.find(|item| item.name == self.item_name);
|
||||
let item = match maybe_item {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
@ -612,7 +598,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
// Check whether `trait_def_id` defines a method with suitable name:
|
||||
if !self.has_applicable_self(item) {
|
||||
if !self.has_applicable_self(&item) {
|
||||
debug!("method has inapplicable self");
|
||||
self.record_static_candidate(TraitSource(trait_def_id));
|
||||
return Ok(());
|
||||
@ -631,7 +617,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn assemble_extension_candidates_for_trait_impls(&mut self,
|
||||
trait_def_id: DefId,
|
||||
item: ty::ImplOrTraitItem<'tcx>) {
|
||||
item: ty::AssociatedItem) {
|
||||
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
||||
|
||||
// FIXME(arielb1): can we use for_each_relevant_impl here?
|
||||
@ -700,7 +686,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn assemble_closure_candidates(&mut self,
|
||||
trait_def_id: DefId,
|
||||
item: ty::ImplOrTraitItem<'tcx>)
|
||||
item: ty::AssociatedItem)
|
||||
-> Result<(), MethodError<'tcx>> {
|
||||
// Check if this is one of the Fn,FnMut,FnOnce traits.
|
||||
let tcx = self.tcx;
|
||||
@ -765,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn assemble_projection_candidates(&mut self,
|
||||
trait_def_id: DefId,
|
||||
item: ty::ImplOrTraitItem<'tcx>) {
|
||||
item: ty::AssociatedItem) {
|
||||
debug!("assemble_projection_candidates(\
|
||||
trait_def_id={:?}, \
|
||||
item={:?})",
|
||||
@ -820,7 +806,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn assemble_where_clause_candidates(&mut self,
|
||||
trait_def_id: DefId,
|
||||
item: ty::ImplOrTraitItem<'tcx>) {
|
||||
item: ty::AssociatedItem) {
|
||||
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
|
||||
trait_def_id);
|
||||
|
||||
@ -865,7 +851,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
self.assemble_extension_candidates_for_all_traits()?;
|
||||
|
||||
let out_of_scope_traits = match self.pick_core() {
|
||||
Some(Ok(p)) => vec![p.item.container().id()],
|
||||
Some(Ok(p)) => vec![p.item.container.id()],
|
||||
Some(Err(MethodError::Ambiguity(v))) => {
|
||||
v.into_iter()
|
||||
.map(|source| {
|
||||
@ -1065,7 +1051,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
// don't have enough information to fully evaluate).
|
||||
let (impl_def_id, substs, ref_obligations) = match probe.kind {
|
||||
InherentImplCandidate(ref substs, ref ref_obligations) => {
|
||||
(probe.item.container().id(), substs, ref_obligations)
|
||||
(probe.item.container.id(), substs, ref_obligations)
|
||||
}
|
||||
|
||||
ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => {
|
||||
@ -1128,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
/// use, so it's ok to just commit to "using the method from the trait Foo".
|
||||
fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option<Pick<'tcx>> {
|
||||
// Do all probes correspond to the same trait?
|
||||
let container = probes[0].item.container();
|
||||
let container = probes[0].item.container;
|
||||
match container {
|
||||
ty::TraitContainer(_) => {}
|
||||
ty::ImplContainer(_) => return None,
|
||||
}
|
||||
if probes[1..].iter().any(|p| p.item.container() != container) {
|
||||
if probes[1..].iter().any(|p| p.item.container != container) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -1150,19 +1136,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MISCELLANY
|
||||
fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {
|
||||
fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool {
|
||||
// "fast track" -- check for usage of sugar
|
||||
match *item {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
|
||||
match method.explicit_self {
|
||||
ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
|
||||
ty::ExplicitSelfCategory::ByValue |
|
||||
ty::ExplicitSelfCategory::ByReference(..) |
|
||||
ty::ExplicitSelfCategory::ByBox => true,
|
||||
}
|
||||
}
|
||||
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
|
||||
_ => false,
|
||||
match self.mode {
|
||||
Mode::MethodCall => item.method_has_self_argument,
|
||||
Mode::Path => true
|
||||
}
|
||||
// FIXME -- check for types that deref to `Self`,
|
||||
// like `Rc<Self>` and so on.
|
||||
@ -1177,24 +1155,26 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn xform_self_ty(&self,
|
||||
item: &ty::ImplOrTraitItem<'tcx>,
|
||||
item: &ty::AssociatedItem,
|
||||
impl_ty: Ty<'tcx>,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
match item.as_opt_method() {
|
||||
Some(ref method) => self.xform_method_self_ty(method, impl_ty, substs),
|
||||
None => impl_ty,
|
||||
if item.kind == ty::AssociatedKind::Method && self.mode == Mode::MethodCall {
|
||||
self.xform_method_self_ty(item.def_id, impl_ty, substs)
|
||||
} else {
|
||||
impl_ty
|
||||
}
|
||||
}
|
||||
|
||||
fn xform_method_self_ty(&self,
|
||||
method: &Rc<ty::Method<'tcx>>,
|
||||
method: DefId,
|
||||
impl_ty: Ty<'tcx>,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
let self_ty = self.tcx.lookup_item_type(method).ty.fn_sig().input(0);
|
||||
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
|
||||
impl_ty,
|
||||
method.fty.sig.0.inputs.get(0),
|
||||
self_ty,
|
||||
substs);
|
||||
|
||||
assert!(!substs.has_escaping_regions());
|
||||
@ -1204,26 +1184,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
// are given do not include type/lifetime parameters for the
|
||||
// method yet. So create fresh variables here for those too,
|
||||
// if there are any.
|
||||
assert_eq!(substs.types().count(),
|
||||
method.generics.parent_types as usize);
|
||||
assert_eq!(substs.regions().count(),
|
||||
method.generics.parent_regions as usize);
|
||||
|
||||
if self.mode == Mode::Path {
|
||||
return impl_ty;
|
||||
}
|
||||
let generics = self.tcx.lookup_generics(method);
|
||||
assert_eq!(substs.types().count(), generics.parent_types as usize);
|
||||
assert_eq!(substs.regions().count(), generics.parent_regions as usize);
|
||||
|
||||
// Erase any late-bound regions from the method and substitute
|
||||
// in the values from the substitution.
|
||||
let xform_self_ty = method.fty.sig.input(0);
|
||||
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
|
||||
let xform_self_ty = self.erase_late_bound_regions(&self_ty);
|
||||
|
||||
if method.generics.types.is_empty() && method.generics.regions.is_empty() {
|
||||
if generics.types.is_empty() && generics.regions.is_empty() {
|
||||
xform_self_ty.subst(self.tcx, substs)
|
||||
} else {
|
||||
let substs = Substs::for_item(self.tcx,
|
||||
method.def_id,
|
||||
|def, _| {
|
||||
let substs = Substs::for_item(self.tcx, method, |def, _| {
|
||||
let i = def.index as usize;
|
||||
if i < substs.params().len() {
|
||||
substs.region_at(i)
|
||||
@ -1232,8 +1204,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
// `impl_self_ty()` for an explanation.
|
||||
self.tcx.mk_region(ty::ReErased)
|
||||
}
|
||||
},
|
||||
|def, cur_substs| {
|
||||
}, |def, cur_substs| {
|
||||
let i = def.index as usize;
|
||||
if i < substs.params().len() {
|
||||
substs.type_at(i)
|
||||
@ -1283,8 +1254,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
/// Find item with name `item_name` defined in impl/trait `def_id`
|
||||
/// and return it, or `None`, if no such item was defined there.
|
||||
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
|
||||
self.fcx.impl_or_trait_item(def_id, self.item_name)
|
||||
fn associated_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
|
||||
self.fcx.associated_item(def_id, self.item_name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1317,11 +1288,11 @@ impl<'tcx> Candidate<'tcx> {
|
||||
|
||||
fn to_source(&self) -> CandidateSource {
|
||||
match self.kind {
|
||||
InherentImplCandidate(..) => ImplSource(self.item.container().id()),
|
||||
InherentImplCandidate(..) => ImplSource(self.item.container.id()),
|
||||
ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
|
||||
ObjectCandidate |
|
||||
TraitCandidate |
|
||||
WhereClauseCandidate(_) => TraitSource(self.item.container().id()),
|
||||
WhereClauseCandidate(_) => TraitSource(self.item.container.id()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,20 +89,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
CandidateSource::ImplSource(impl_did) => {
|
||||
// Provide the best span we can. Use the item, if local to crate, else
|
||||
// the impl, if local to crate (item may be defaulted), else nothing.
|
||||
let item = self.impl_or_trait_item(impl_did, item_name)
|
||||
let item = self.associated_item(impl_did, item_name)
|
||||
.or_else(|| {
|
||||
self.impl_or_trait_item(self.tcx
|
||||
.impl_trait_ref(impl_did)
|
||||
.unwrap()
|
||||
.def_id,
|
||||
self.associated_item(
|
||||
self.tcx.impl_trait_ref(impl_did).unwrap().def_id,
|
||||
|
||||
item_name)
|
||||
})
|
||||
.unwrap();
|
||||
let note_span = self.tcx
|
||||
.map
|
||||
.span_if_local(item.def_id())
|
||||
.or_else(|| self.tcx.map.span_if_local(impl_did));
|
||||
item_name
|
||||
)
|
||||
}).unwrap();
|
||||
let note_span = self.tcx.map.span_if_local(item.def_id).or_else(|| {
|
||||
self.tcx.map.span_if_local(impl_did)
|
||||
});
|
||||
|
||||
let impl_ty = self.impl_self_ty(span, impl_did).ty;
|
||||
|
||||
@ -127,8 +124,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
CandidateSource::TraitSource(trait_did) => {
|
||||
let item = self.impl_or_trait_item(trait_did, item_name).unwrap();
|
||||
let item_span = self.tcx.map.def_id_span(item.def_id(), span);
|
||||
let item = self.associated_item(trait_did, item_name).unwrap();
|
||||
let item_span = self.tcx.map.def_id_span(item.def_id, span);
|
||||
span_note!(err,
|
||||
item_span,
|
||||
"candidate #{} is defined in the trait `{}`",
|
||||
@ -334,8 +331,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// this isn't perfect (that is, there are cases when
|
||||
// implementing a trait would be legal but is rejected
|
||||
// here).
|
||||
(type_is_local || info.def_id.is_local()) &&
|
||||
self.impl_or_trait_item(info.def_id, item_name).is_some()
|
||||
(type_is_local || info.def_id.is_local())
|
||||
&& self.associated_item(info.def_id, item_name).is_some()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,8 +75,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
match BinOpCategory::from(op) {
|
||||
BinOpCategory::Shortcircuit => {
|
||||
// && and || are a simple case.
|
||||
let lhs_diverges = self.diverges.get();
|
||||
self.demand_suptype(lhs_expr.span, tcx.mk_bool(), lhs_ty);
|
||||
self.check_expr_coercable_to_type(rhs_expr, tcx.mk_bool());
|
||||
|
||||
// Depending on the LHS' value, the RHS can never execute.
|
||||
self.diverges.set(lhs_diverges);
|
||||
|
||||
tcx.mk_bool()
|
||||
}
|
||||
_ => {
|
||||
|
@ -142,13 +142,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn regionck_fn(&self,
|
||||
fn_id: ast::NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
blk: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
debug!("regionck_fn(id={})", fn_id);
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(blk.id), blk.id, Subject(fn_id));
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(body.id), body.id, Subject(fn_id));
|
||||
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_fn_body(fn_id, decl, blk, self.tcx.map.span(fn_id));
|
||||
rcx.visit_fn_body(fn_id, decl, body, self.tcx.map.span(fn_id));
|
||||
}
|
||||
|
||||
rcx.free_region_map.relate_free_regions_from_predicates(
|
||||
@ -268,7 +268,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
fn visit_fn_body(&mut self,
|
||||
id: ast::NodeId, // the id of the fn itself
|
||||
fn_decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
span: Span)
|
||||
{
|
||||
// When we enter a function, we can derive
|
||||
@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
self.relate_free_regions(&fn_sig_tys[..], body.id, span);
|
||||
self.link_fn_args(self.tcx.region_maps.node_extent(body.id),
|
||||
&fn_decl.inputs[..]);
|
||||
self.visit_block(body);
|
||||
self.visit_expr(body);
|
||||
self.visit_region_obligations(body.id);
|
||||
|
||||
let call_site_scope = self.call_site_scope.unwrap();
|
||||
@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
// regions, until regionck, as described in #3238.
|
||||
|
||||
fn visit_fn(&mut self, _fk: intravisit::FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
self.visit_fn_body(id, fd, b, span)
|
||||
}
|
||||
|
||||
@ -825,7 +825,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn check_expr_fn_block(&mut self,
|
||||
expr: &hir::Expr,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
let repeating_scope = self.set_repeating_scope(body.id);
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.set_repeating_scope(repeating_scope);
|
||||
|
@ -57,18 +57,7 @@ use rustc::util::nodemap::NodeMap;
|
||||
// PUBLIC ENTRY POINTS
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn closure_analyze_fn(&self, body: &hir::Block) {
|
||||
let mut seed = SeedBorrowKind::new(self);
|
||||
seed.visit_block(body);
|
||||
|
||||
let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
|
||||
adjust.visit_block(body);
|
||||
|
||||
// it's our job to process these.
|
||||
assert!(self.deferred_call_resolutions.borrow().is_empty());
|
||||
}
|
||||
|
||||
pub fn closure_analyze_const(&self, body: &hir::Expr) {
|
||||
pub fn closure_analyze(&self, body: &hir::Expr) {
|
||||
let mut seed = SeedBorrowKind::new(self);
|
||||
seed.visit_expr(body);
|
||||
|
||||
@ -110,7 +99,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn check_closure(&mut self,
|
||||
expr: &hir::Expr,
|
||||
capture_clause: hir::CaptureClause,
|
||||
_body: &hir::Block)
|
||||
_body: &hir::Expr)
|
||||
{
|
||||
let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
|
||||
if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
|
||||
@ -164,7 +153,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
id: ast::NodeId,
|
||||
span: Span,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
/*!
|
||||
* Analysis starting point.
|
||||
*/
|
||||
@ -497,7 +486,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fn_kind: intravisit::FnKind<'v>,
|
||||
decl: &'v hir::FnDecl,
|
||||
body: &'v hir::Block,
|
||||
body: &'v hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId)
|
||||
{
|
||||
|
@ -8,9 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use astconv::ExplicitSelf;
|
||||
use check::FnCtxt;
|
||||
use constrained_type_params::{identify_constrained_type_params, Parameter};
|
||||
use CrateCtxt;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use middle::region::{CodeExtent};
|
||||
use rustc::infer::TypeOrigin;
|
||||
@ -156,8 +158,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
|
||||
self.check_variances_for_type_defn(item, ast_generics);
|
||||
}
|
||||
hir::ItemTrait(.., ref items) => {
|
||||
self.check_trait(item, items);
|
||||
hir::ItemTrait(..) => {
|
||||
self.check_trait(item);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -172,32 +174,39 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let free_id_outlive = fcx.parameter_environment.free_id_outlive;
|
||||
|
||||
let item = fcx.tcx.impl_or_trait_item(fcx.tcx.map.local_def_id(item_id));
|
||||
let item = fcx.tcx.associated_item(fcx.tcx.map.local_def_id(item_id));
|
||||
|
||||
let (mut implied_bounds, self_ty) = match item.container() {
|
||||
let (mut implied_bounds, self_ty) = match item.container {
|
||||
ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
|
||||
ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
|
||||
fcx.tcx.lookup_item_type(def_id).ty)
|
||||
};
|
||||
|
||||
match item {
|
||||
ty::ConstTraitItem(assoc_const) => {
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, &assoc_const.ty);
|
||||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let ty = fcx.tcx.lookup_item_type(item.def_id).ty;
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
|
||||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
ty::MethodTraitItem(method) => {
|
||||
reject_shadowing_type_parameters(fcx.tcx, span, &method.generics);
|
||||
let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
|
||||
let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
|
||||
this.check_fn_or_method(fcx, span, &method_ty, &predicates,
|
||||
ty::AssociatedKind::Method => {
|
||||
reject_shadowing_type_parameters(fcx.tcx, span, item.def_id);
|
||||
let method_ty = fcx.tcx.lookup_item_type(item.def_id).ty;
|
||||
let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
|
||||
let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
|
||||
let fty = match method_ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => bug!()
|
||||
};
|
||||
this.check_fn_or_method(fcx, span, fty, &predicates,
|
||||
free_id_outlive, &mut implied_bounds);
|
||||
let sig_if_method = sig_if_method.expect("bad signature for method");
|
||||
this.check_method_receiver(fcx, sig_if_method, &method,
|
||||
this.check_method_receiver(fcx, sig_if_method, &item,
|
||||
free_id_outlive, self_ty);
|
||||
}
|
||||
ty::TypeTraitItem(assoc_type) => {
|
||||
if let Some(ref ty) = assoc_type.ty {
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, ty);
|
||||
ty::AssociatedKind::Type => {
|
||||
if item.has_value {
|
||||
let ty = fcx.tcx.lookup_item_type(item.def_id).ty;
|
||||
let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
|
||||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
}
|
||||
@ -248,19 +257,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id));
|
||||
let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
|
||||
let def_id = fcx.tcx.map.local_def_id(item.id);
|
||||
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
|
||||
vec![] // no implied bounds in a struct def'n
|
||||
});
|
||||
}
|
||||
|
||||
fn check_auto_trait(&mut self,
|
||||
trait_def_id: DefId,
|
||||
items: &[hir::TraitItem],
|
||||
span: Span)
|
||||
{
|
||||
fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
|
||||
// We want to ensure:
|
||||
//
|
||||
// 1) that there are no items contained within
|
||||
@ -302,7 +307,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
// extraneous predicates created by things like
|
||||
// an associated type inside the trait.
|
||||
let mut err = None;
|
||||
if !items.is_empty() {
|
||||
if !self.tcx().associated_item_def_ids(trait_def_id).is_empty() {
|
||||
error_380(self.ccx, span);
|
||||
} else if has_ty_params {
|
||||
err = Some(struct_span_err!(self.tcx().sess, span, E0567,
|
||||
@ -326,20 +331,16 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait(&mut self,
|
||||
item: &hir::Item,
|
||||
items: &[hir::TraitItem])
|
||||
{
|
||||
fn check_trait(&mut self, item: &hir::Item) {
|
||||
let trait_def_id = self.tcx().map.local_def_id(item.id);
|
||||
|
||||
if self.tcx().trait_has_default_impl(trait_def_id) {
|
||||
self.check_auto_trait(trait_def_id, items, item.span);
|
||||
self.check_auto_trait(trait_def_id, item.span);
|
||||
}
|
||||
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let predicates = fcx.tcx.lookup_predicates(trait_def_id);
|
||||
let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
|
||||
let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
vec![]
|
||||
});
|
||||
@ -347,11 +348,12 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
|
||||
fn check_item_fn(&mut self,
|
||||
item: &hir::Item,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
{
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let type_scheme = fcx.tcx.lookup_item_type(fcx.tcx.map.local_def_id(item.id));
|
||||
let def_id = fcx.tcx.map.local_def_id(item.id);
|
||||
let type_scheme = fcx.tcx.lookup_item_type(def_id);
|
||||
let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty);
|
||||
let bare_fn_ty = match item_ty.sty {
|
||||
ty::TyFnDef(.., ref bare_fn_ty) => bare_fn_ty,
|
||||
@ -360,8 +362,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id));
|
||||
let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
|
||||
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
|
||||
|
||||
let mut implied_bounds = vec![];
|
||||
let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body.id);
|
||||
@ -422,8 +423,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let predicates = fcx.tcx.lookup_predicates(item_def_id);
|
||||
let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
|
||||
let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
|
||||
this.check_where_clauses(fcx, item.span, &predicates);
|
||||
|
||||
fcx.impl_implied_bounds(fcx.tcx.map.local_def_id(item.id), item.span)
|
||||
@ -476,35 +476,39 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
fn check_method_receiver<'fcx, 'tcx>(&mut self,
|
||||
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
|
||||
method_sig: &hir::MethodSig,
|
||||
method: &ty::Method<'tcx>,
|
||||
method: &ty::AssociatedItem,
|
||||
free_id_outlive: CodeExtent,
|
||||
self_ty: ty::Ty<'tcx>)
|
||||
{
|
||||
// check that the type of the method's receiver matches the
|
||||
// method's first parameter.
|
||||
debug!("check_method_receiver({:?},cat={:?},self_ty={:?})",
|
||||
method.name, method.explicit_self, self_ty);
|
||||
debug!("check_method_receiver({:?}, self_ty={:?})",
|
||||
method, self_ty);
|
||||
|
||||
let rcvr_ty = match method.explicit_self {
|
||||
ty::ExplicitSelfCategory::Static => return,
|
||||
ty::ExplicitSelfCategory::ByValue => self_ty,
|
||||
ty::ExplicitSelfCategory::ByReference(region, mutability) => {
|
||||
fcx.tcx.mk_ref(region, ty::TypeAndMut {
|
||||
ty: self_ty,
|
||||
mutbl: mutability
|
||||
})
|
||||
}
|
||||
ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty)
|
||||
};
|
||||
if !method.method_has_self_argument {
|
||||
return;
|
||||
}
|
||||
|
||||
let span = method_sig.decl.inputs[0].pat.span;
|
||||
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
|
||||
let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
|
||||
let method_ty = fcx.tcx.lookup_item_type(method.def_id).ty;
|
||||
let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
|
||||
let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
|
||||
|
||||
debug!("check_method_receiver: sig={:?}", sig);
|
||||
|
||||
let self_arg_ty = sig.inputs[0];
|
||||
let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) {
|
||||
ExplicitSelf::ByValue => self_ty,
|
||||
ExplicitSelf::ByReference(region, mutbl) => {
|
||||
fcx.tcx.mk_ref(region, ty::TypeAndMut {
|
||||
ty: self_ty,
|
||||
mutbl: mutbl
|
||||
})
|
||||
}
|
||||
ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
|
||||
};
|
||||
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
|
||||
let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
|
||||
&ty::Binder(rcvr_ty));
|
||||
@ -512,7 +516,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
|
||||
|
||||
let origin = TypeOrigin::MethodReceiver(span);
|
||||
fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]);
|
||||
fcx.demand_eqtype_with_origin(origin, rcvr_ty, self_arg_ty);
|
||||
}
|
||||
|
||||
fn check_variances_for_type_defn(&self,
|
||||
@ -578,7 +582,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) {
|
||||
fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, def_id: DefId) {
|
||||
let generics = tcx.lookup_generics(def_id);
|
||||
let parent = tcx.lookup_generics(generics.parent.unwrap());
|
||||
let impl_params: FxHashMap<_, _> = parent.types
|
||||
.iter()
|
||||
|
@ -49,11 +49,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn resolve_type_vars_in_fn(&self,
|
||||
decl: &hir::FnDecl,
|
||||
blk: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
item_id: ast::NodeId) {
|
||||
assert_eq!(self.writeback_errors.get(), false);
|
||||
let mut wbcx = WritebackCx::new(self);
|
||||
wbcx.visit_block(blk);
|
||||
wbcx.visit_expr(body);
|
||||
for arg in &decl.inputs {
|
||||
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
|
||||
wbcx.visit_pat(&arg.pat);
|
||||
|
@ -38,8 +38,6 @@ use rustc::hir::intravisit;
|
||||
use rustc::hir::{Item, ItemImpl};
|
||||
use rustc::hir;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
mod orphan;
|
||||
mod overlap;
|
||||
mod unsafety;
|
||||
@ -113,8 +111,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
// If there are no traits, then this implementation must have a
|
||||
// base type.
|
||||
|
||||
let impl_items = self.create_impl_from_item(item);
|
||||
|
||||
if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) {
|
||||
debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
|
||||
trait_ref,
|
||||
@ -144,8 +140,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
self.add_inherent_impl(base_def_id, impl_did);
|
||||
}
|
||||
}
|
||||
|
||||
tcx.impl_or_trait_item_def_ids.borrow_mut().insert(impl_did, Rc::new(impl_items));
|
||||
}
|
||||
|
||||
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
|
||||
@ -161,20 +155,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
|
||||
}
|
||||
|
||||
// Converts an implementation in the AST to a vector of items.
|
||||
fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
|
||||
match item.node {
|
||||
ItemImpl(.., ref impl_items) => {
|
||||
impl_items.iter()
|
||||
.map(|impl_item| self.crate_context.tcx.map.local_def_id(impl_item.id))
|
||||
.collect()
|
||||
}
|
||||
_ => {
|
||||
span_bug!(item.span, "can't convert a non-impl to an impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destructors
|
||||
//
|
||||
|
||||
@ -187,10 +167,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
tcx.populate_implementations_for_trait_if_necessary(drop_trait);
|
||||
let drop_trait = tcx.lookup_trait_def(drop_trait);
|
||||
|
||||
let impl_items = tcx.impl_or_trait_item_def_ids.borrow();
|
||||
|
||||
drop_trait.for_each_impl(tcx, |impl_did| {
|
||||
let items = impl_items.get(&impl_did).unwrap();
|
||||
let items = tcx.associated_item_def_ids(impl_did);
|
||||
if items.is_empty() {
|
||||
// We'll error out later. For now, just don't ICE.
|
||||
return;
|
||||
|
@ -48,25 +48,23 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
|
||||
Value,
|
||||
}
|
||||
|
||||
fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> (ast::Name, Namespace) {
|
||||
let item = tcx.impl_or_trait_item(def_id);
|
||||
(item.name(),
|
||||
match item {
|
||||
ty::TypeTraitItem(..) => Namespace::Type,
|
||||
ty::ConstTraitItem(..) => Namespace::Value,
|
||||
ty::MethodTraitItem(..) => Namespace::Value,
|
||||
})
|
||||
}
|
||||
let name_and_namespace = |def_id| {
|
||||
let item = self.tcx.associated_item(def_id);
|
||||
(item.name, match item.kind {
|
||||
ty::AssociatedKind::Type => Namespace::Type,
|
||||
ty::AssociatedKind::Const |
|
||||
ty::AssociatedKind::Method => Namespace::Value,
|
||||
})
|
||||
};
|
||||
|
||||
let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow();
|
||||
let impl_items1 = self.tcx.associated_item_def_ids(impl1);
|
||||
let impl_items2 = self.tcx.associated_item_def_ids(impl2);
|
||||
|
||||
for &item1 in &impl_items[&impl1][..] {
|
||||
let (name, namespace) = name_and_namespace(self.tcx, item1);
|
||||
for &item1 in &impl_items1[..] {
|
||||
let (name, namespace) = name_and_namespace(item1);
|
||||
|
||||
for &item2 in &impl_items[&impl2][..] {
|
||||
if (name, namespace) == name_and_namespace(self.tcx, item2) {
|
||||
for &item2 in &impl_items2[..] {
|
||||
if (name, namespace) == name_and_namespace(item2) {
|
||||
let msg = format!("duplicate definitions with name `{}`", name);
|
||||
let node_id = self.tcx.map.as_local_node_id(item1).unwrap();
|
||||
self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
|
||||
|
@ -66,7 +66,7 @@ use middle::const_val::ConstVal;
|
||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer};
|
||||
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rscope::*;
|
||||
@ -79,7 +79,6 @@ use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::{abi, ast, attr};
|
||||
use syntax::parse::token::keywords;
|
||||
@ -351,24 +350,6 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(&self,
|
||||
trait_def_id: DefId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) {
|
||||
trait_associated_type_names(self.tcx(), trait_id)
|
||||
.any(|name| name == assoc_name)
|
||||
} else {
|
||||
self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| {
|
||||
match self.tcx().impl_or_trait_item(def_id) {
|
||||
ty::TypeTraitItem(ref item) => item.name == assoc_name,
|
||||
_ => false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
|
||||
None
|
||||
}
|
||||
@ -557,60 +538,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
container: ImplOrTraitItemContainer,
|
||||
name: ast::Name,
|
||||
id: ast::NodeId,
|
||||
vis: &hir::Visibility,
|
||||
sig: &hir::MethodSig,
|
||||
defaultness: hir::Defaultness,
|
||||
has_body: bool,
|
||||
untransformed_rcvr_ty: Ty<'tcx>,
|
||||
rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
|
||||
let def_id = ccx.tcx.map.local_def_id(id);
|
||||
let ty_generics = generics_of_def_id(ccx, def_id);
|
||||
|
||||
let ty_generic_predicates =
|
||||
ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
|
||||
|
||||
let (fty, explicit_self_category) = {
|
||||
let anon_scope = match container {
|
||||
ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
|
||||
TraitContainer(_) => None
|
||||
};
|
||||
AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
||||
sig, untransformed_rcvr_ty, anon_scope)
|
||||
};
|
||||
|
||||
let ty_method = ty::Method {
|
||||
name: name,
|
||||
generics: ty_generics,
|
||||
predicates: ty_generic_predicates,
|
||||
fty: fty,
|
||||
explicit_self: explicit_self_category,
|
||||
vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
|
||||
defaultness: defaultness,
|
||||
has_body: has_body,
|
||||
def_id: def_id,
|
||||
container: container,
|
||||
};
|
||||
|
||||
let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
||||
ccx.tcx.map.span(id), def_id);
|
||||
let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty);
|
||||
debug!("method {} (id {}) has type {:?}",
|
||||
name, id, fty);
|
||||
ccx.tcx.tcache.borrow_mut().insert(def_id, fty);
|
||||
write_ty_to_tcx(ccx, id, fty);
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
|
||||
|
||||
debug!("writing method type: def_id={:?} mty={:?}",
|
||||
def_id, ty_method);
|
||||
|
||||
ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
|
||||
ty::MethodTraitItem(Rc::new(ty_method)));
|
||||
}
|
||||
|
||||
fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
struct_generics: &'tcx ty::Generics<'tcx>,
|
||||
struct_predicates: &ty::GenericPredicates<'tcx>,
|
||||
@ -631,62 +558,65 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
struct_predicates.clone());
|
||||
}
|
||||
|
||||
fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
container: AssociatedItemContainer,
|
||||
id: ast::NodeId,
|
||||
sig: &hir::MethodSig,
|
||||
untransformed_rcvr_ty: Ty<'tcx>,
|
||||
rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
|
||||
let def_id = ccx.tcx.map.local_def_id(id);
|
||||
let ty_generics = generics_of_def_id(ccx, def_id);
|
||||
|
||||
let ty_generic_predicates =
|
||||
ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
|
||||
|
||||
let anon_scope = match container {
|
||||
ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
|
||||
TraitContainer(_) => None
|
||||
};
|
||||
let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
||||
sig, untransformed_rcvr_ty, anon_scope);
|
||||
|
||||
let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
||||
ccx.tcx.map.span(id), def_id);
|
||||
let fty = ccx.tcx.mk_fn_def(def_id, substs, fty);
|
||||
ccx.tcx.tcache.borrow_mut().insert(def_id, fty);
|
||||
write_ty_to_tcx(ccx, id, fty);
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, ty_generic_predicates);
|
||||
}
|
||||
|
||||
fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
container: ImplOrTraitItemContainer,
|
||||
name: ast::Name,
|
||||
container: AssociatedItemContainer,
|
||||
id: ast::NodeId,
|
||||
vis: &hir::Visibility,
|
||||
defaultness: hir::Defaultness,
|
||||
ty: ty::Ty<'tcx>,
|
||||
has_value: bool)
|
||||
ty: ty::Ty<'tcx>)
|
||||
{
|
||||
let predicates = ty::GenericPredicates {
|
||||
parent: Some(container.id()),
|
||||
predicates: vec![]
|
||||
};
|
||||
ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
|
||||
predicates);
|
||||
let def_id = ccx.tcx.map.local_def_id(id);
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
|
||||
ccx.tcx.tcache.borrow_mut().insert(def_id, ty);
|
||||
|
||||
write_ty_to_tcx(ccx, id, ty);
|
||||
|
||||
let associated_const = Rc::new(ty::AssociatedConst {
|
||||
name: name,
|
||||
vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
|
||||
defaultness: defaultness,
|
||||
def_id: ccx.tcx.map.local_def_id(id),
|
||||
container: container,
|
||||
ty: ty,
|
||||
has_value: has_value
|
||||
});
|
||||
ccx.tcx.impl_or_trait_items.borrow_mut()
|
||||
.insert(ccx.tcx.map.local_def_id(id), ty::ConstTraitItem(associated_const));
|
||||
}
|
||||
|
||||
fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
container: ImplOrTraitItemContainer,
|
||||
name: ast::Name,
|
||||
container: AssociatedItemContainer,
|
||||
id: ast::NodeId,
|
||||
vis: &hir::Visibility,
|
||||
defaultness: hir::Defaultness,
|
||||
ty: Option<Ty<'tcx>>)
|
||||
{
|
||||
let predicates = ty::GenericPredicates {
|
||||
parent: Some(container.id()),
|
||||
predicates: vec![]
|
||||
};
|
||||
ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
|
||||
predicates);
|
||||
let def_id = ccx.tcx.map.local_def_id(id);
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
|
||||
|
||||
let associated_type = Rc::new(ty::AssociatedType {
|
||||
name: name,
|
||||
vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
|
||||
defaultness: defaultness,
|
||||
ty: ty,
|
||||
def_id: ccx.tcx.map.local_def_id(id),
|
||||
container: container
|
||||
});
|
||||
ccx.tcx.impl_or_trait_items.borrow_mut()
|
||||
.insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type));
|
||||
if let Some(ty) = ty {
|
||||
ccx.tcx.tcache.borrow_mut().insert(def_id, ty);
|
||||
write_ty_to_tcx(ccx, id, ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
@ -820,14 +750,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
generics: ty_generics,
|
||||
ty: ty,
|
||||
});
|
||||
// Trait-associated constants are always public.
|
||||
let public = &hir::Public;
|
||||
let visibility = if opt_trait_ref.is_some() { public } else { &impl_item.vis };
|
||||
convert_associated_const(ccx, ImplContainer(def_id),
|
||||
impl_item.name, impl_item.id,
|
||||
visibility,
|
||||
impl_item.defaultness,
|
||||
ty, true /* has_value */);
|
||||
impl_item.id, ty);
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,21 +768,14 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
|
||||
let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
|
||||
|
||||
convert_associated_type(ccx, ImplContainer(def_id),
|
||||
impl_item.name, impl_item.id, &impl_item.vis,
|
||||
impl_item.defaultness, Some(typ));
|
||||
convert_associated_type(ccx, ImplContainer(def_id), impl_item.id, Some(typ));
|
||||
}
|
||||
}
|
||||
|
||||
for impl_item in impl_items {
|
||||
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
// Trait methods are always public.
|
||||
let public = &hir::Public;
|
||||
let method_vis = if opt_trait_ref.is_some() { public } else { &impl_item.vis };
|
||||
|
||||
convert_method(ccx, ImplContainer(def_id),
|
||||
impl_item.name, impl_item.id, method_vis,
|
||||
sig, impl_item.defaultness, true, selfty,
|
||||
impl_item.id, sig, selfty,
|
||||
&ty_predicates);
|
||||
}
|
||||
}
|
||||
@ -880,7 +797,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
|
||||
// Convert all the associated constants.
|
||||
for trait_item in trait_items {
|
||||
if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
|
||||
if let hir::ConstTraitItem(ref ty, _) = trait_item.node {
|
||||
let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
|
||||
let ty_generics = generics_of_def_id(ccx, const_def_id);
|
||||
let ty = ccx.icx(&trait_predicates)
|
||||
@ -890,14 +807,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
generics: ty_generics,
|
||||
ty: ty,
|
||||
});
|
||||
convert_associated_const(ccx,
|
||||
container,
|
||||
trait_item.name,
|
||||
trait_item.id,
|
||||
&hir::Public,
|
||||
hir::Defaultness::Default,
|
||||
ty,
|
||||
default.is_some())
|
||||
convert_associated_const(ccx, container, trait_item.id, ty)
|
||||
}
|
||||
}
|
||||
|
||||
@ -911,39 +821,21 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
|ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
|
||||
});
|
||||
|
||||
convert_associated_type(ccx,
|
||||
container,
|
||||
trait_item.name,
|
||||
trait_item.id,
|
||||
&hir::Public,
|
||||
hir::Defaultness::Default,
|
||||
typ);
|
||||
convert_associated_type(ccx, container, trait_item.id, typ);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert all the methods
|
||||
for trait_item in trait_items {
|
||||
if let hir::MethodTraitItem(ref sig, ref body) = trait_item.node {
|
||||
if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
|
||||
convert_method(ccx,
|
||||
container,
|
||||
trait_item.name,
|
||||
trait_item.id,
|
||||
&hir::Inherited,
|
||||
sig,
|
||||
hir::Defaultness::Default,
|
||||
body.is_some(),
|
||||
tcx.mk_self_type(),
|
||||
&trait_predicates);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Add an entry mapping
|
||||
let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
|
||||
ccx.tcx.map.local_def_id(trait_item.id)
|
||||
}).collect());
|
||||
tcx.impl_or_trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
|
||||
trait_item_def_ids);
|
||||
},
|
||||
hir::ItemStruct(ref struct_def, _) |
|
||||
hir::ItemUnion(ref struct_def, _) => {
|
||||
@ -1308,28 +1200,6 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
tcx.intern_trait_def(trait_def)
|
||||
}
|
||||
|
||||
pub fn trait_associated_type_names<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_node_id: ast::NodeId)
|
||||
-> impl Iterator<Item=ast::Name> + 'a
|
||||
{
|
||||
let item = match tcx.map.get(trait_node_id) {
|
||||
hir_map::NodeItem(item) => item,
|
||||
_ => bug!("trait_node_id {} is not an item", trait_node_id)
|
||||
};
|
||||
|
||||
let trait_items = match item.node {
|
||||
hir::ItemTrait(.., ref trait_items) => trait_items,
|
||||
_ => bug!("trait_node_id {} is not a trait", trait_node_id)
|
||||
};
|
||||
|
||||
trait_items.iter().filter_map(|trait_item| {
|
||||
match trait_item.node {
|
||||
hir::TypeTraitItem(..) => Some(trait_item.name),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) {
|
||||
let tcx = ccx.tcx;
|
||||
let trait_def = trait_def_of_item(ccx, it);
|
||||
@ -2209,13 +2079,14 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
&impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
|
||||
|
||||
let lifetimes_in_associated_types: FxHashSet<_> = impl_items.iter()
|
||||
.map(|item| ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(item.id)))
|
||||
.filter_map(|item| match item {
|
||||
ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
|
||||
ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
|
||||
.map(|item| ccx.tcx.map.local_def_id(item.id))
|
||||
.filter(|&def_id| {
|
||||
let item = ccx.tcx.associated_item(def_id);
|
||||
item.kind == ty::AssociatedKind::Type && item.has_value
|
||||
})
|
||||
.flat_map(|ty| ctp::parameters_for(&ty, true))
|
||||
.collect();
|
||||
.flat_map(|def_id| {
|
||||
ctp::parameters_for(&ccx.tcx.lookup_item_type(def_id).ty, true)
|
||||
}).collect();
|
||||
|
||||
for (ty_lifetime, lifetime) in impl_scheme.generics.regions.iter()
|
||||
.zip(&ast_generics.lifetimes)
|
||||
|
@ -163,7 +163,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
|
||||
pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
did: DefId) -> clean::Trait {
|
||||
let def = tcx.lookup_trait_def(did);
|
||||
let trait_items = tcx.trait_items(did).clean(cx);
|
||||
let trait_items = tcx.associated_items(did).map(|item| item.clean(cx)).collect();
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
let generics = filter_non_trait_generics(did, generics);
|
||||
@ -307,7 +307,6 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
|
||||
|
||||
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
|
||||
if !def_id.is_local() {
|
||||
tcx.populate_implementations_for_primitive_if_necessary(def_id);
|
||||
build_impl(cx, tcx, def_id, &mut impls);
|
||||
}
|
||||
}
|
||||
@ -367,21 +366,18 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
||||
}
|
||||
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let trait_items = tcx.sess.cstore.impl_or_trait_items(did)
|
||||
.iter()
|
||||
.filter_map(|&did| {
|
||||
match tcx.impl_or_trait_item(did) {
|
||||
ty::ConstTraitItem(ref assoc_const) => {
|
||||
let did = assoc_const.def_id;
|
||||
let type_scheme = tcx.lookup_item_type(did);
|
||||
let default = if assoc_const.has_value {
|
||||
let trait_items = tcx.associated_items(did).filter_map(|item| {
|
||||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let type_scheme = tcx.lookup_item_type(item.def_id);
|
||||
let default = if item.has_value {
|
||||
Some(pprust::expr_to_string(
|
||||
lookup_const_by_id(tcx, did, None).unwrap().0))
|
||||
lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(assoc_const.name.clean(cx)),
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::AssociatedConstItem(
|
||||
type_scheme.ty.clean(cx),
|
||||
default,
|
||||
@ -389,21 +385,21 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
||||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
||||
def_id: did
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
ty::MethodTraitItem(method) => {
|
||||
if method.vis != ty::Visibility::Public && associated_trait.is_none() {
|
||||
ty::AssociatedKind::Method => {
|
||||
if item.vis != ty::Visibility::Public && associated_trait.is_none() {
|
||||
return None
|
||||
}
|
||||
let mut item = method.clean(cx);
|
||||
item.inner = match item.inner.clone() {
|
||||
let mut cleaned = item.clean(cx);
|
||||
cleaned.inner = match cleaned.inner.clone() {
|
||||
clean::TyMethodItem(clean::TyMethod {
|
||||
unsafety, decl, generics, abi
|
||||
}) => {
|
||||
let constness = if tcx.sess.cstore.is_const_fn(did) {
|
||||
let constness = if tcx.sess.cstore.is_const_fn(item.def_id) {
|
||||
hir::Constness::Const
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
@ -419,12 +415,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
||||
}
|
||||
_ => panic!("not a tymethod"),
|
||||
};
|
||||
Some(item)
|
||||
Some(cleaned)
|
||||
}
|
||||
ty::TypeTraitItem(ref assoc_ty) => {
|
||||
let did = assoc_ty.def_id;
|
||||
ty::AssociatedKind::Type => {
|
||||
let typedef = clean::Typedef {
|
||||
type_: assoc_ty.ty.unwrap().clean(cx),
|
||||
type_: tcx.lookup_item_type(item.def_id).ty.clean(cx),
|
||||
generics: clean::Generics {
|
||||
lifetimes: vec![],
|
||||
type_params: vec![],
|
||||
@ -432,14 +427,14 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
||||
}
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(assoc_ty.name.clean(cx)),
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::TypedefItem(typedef, true),
|
||||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
||||
def_id: did
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1338,47 +1338,116 @@ impl Clean<Item> for hir::ImplItem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let generics = (self.generics, &self.predicates).clean(cx);
|
||||
let mut decl = (self.def_id, &self.fty.sig).clean(cx);
|
||||
match self.explicit_self {
|
||||
ty::ExplicitSelfCategory::ByValue => {
|
||||
decl.inputs.values[0].type_ = Infer;
|
||||
let inner = match self.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let ty = cx.tcx().lookup_item_type(self.def_id).ty;
|
||||
AssociatedConstItem(ty.clean(cx), None)
|
||||
}
|
||||
ty::ExplicitSelfCategory::ByReference(..) => {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef{ref mut type_, ..} => **type_ = Infer,
|
||||
_ => unreachable!(),
|
||||
ty::AssociatedKind::Method => {
|
||||
let generics = (cx.tcx().lookup_generics(self.def_id),
|
||||
&cx.tcx().lookup_predicates(self.def_id)).clean(cx);
|
||||
let fty = match cx.tcx().lookup_item_type(self.def_id).ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let mut decl = (self.def_id, &fty.sig).clean(cx);
|
||||
|
||||
if self.method_has_self_argument {
|
||||
let self_ty = match self.container {
|
||||
ty::ImplContainer(def_id) => {
|
||||
cx.tcx().lookup_item_type(def_id).ty
|
||||
}
|
||||
ty::TraitContainer(_) => cx.tcx().mk_self_type()
|
||||
};
|
||||
let self_arg_ty = *fty.sig.input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
decl.inputs.values[0].type_ = Infer;
|
||||
} else if let ty::TyRef(_, mt) = self_arg_ty.sty {
|
||||
if mt.ty == self_ty {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef{ref mut type_, ..} => **type_ = Infer,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer(_) => false,
|
||||
ty::TraitContainer(_) => self.has_value
|
||||
};
|
||||
if provided {
|
||||
MethodItem(Method {
|
||||
unsafety: fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: fty.abi,
|
||||
|
||||
// trait methods canot (currently, at least) be const
|
||||
constness: hir::Constness::NotConst,
|
||||
})
|
||||
} else {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: fty.abi,
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer(..) => false,
|
||||
ty::TraitContainer(did) => {
|
||||
cx.tcx().provided_trait_methods(did).iter().any(|m| {
|
||||
m.def_id == self.def_id
|
||||
})
|
||||
}
|
||||
};
|
||||
let inner = if provided {
|
||||
MethodItem(Method {
|
||||
unsafety: self.fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: self.fty.abi,
|
||||
ty::AssociatedKind::Type => {
|
||||
let my_name = self.name.clean(cx);
|
||||
|
||||
// trait methods canot (currently, at least) be const
|
||||
constness: hir::Constness::NotConst,
|
||||
})
|
||||
} else {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: self.fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: self.fty.abi,
|
||||
})
|
||||
let mut bounds = if let ty::TraitContainer(did) = self.container {
|
||||
// When loading a cross-crate associated type, the bounds for this type
|
||||
// are actually located on the trait/impl itself, so we need to load
|
||||
// all of the generics from there and then look for bounds that are
|
||||
// applied to this associated type in question.
|
||||
let def = cx.tcx().lookup_trait_def(did);
|
||||
let predicates = cx.tcx().lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
generics.where_predicates.iter().filter_map(|pred| {
|
||||
let (name, self_type, trait_, bounds) = match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref name, ref self_type, ref trait_ },
|
||||
ref bounds
|
||||
} => (name, self_type, trait_, bounds),
|
||||
_ => return None,
|
||||
};
|
||||
if *name != my_name { return None }
|
||||
match **trait_ {
|
||||
ResolvedPath { did, .. } if did == self.container.id() => {}
|
||||
_ => return None,
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == "Self" => {}
|
||||
_ => return None,
|
||||
}
|
||||
Some(bounds)
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => { bounds.remove(i); }
|
||||
None => bounds.push(TyParamBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
let ty = if self.has_value {
|
||||
Some(cx.tcx().lookup_item_type(self.def_id).ty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
AssociatedTypeItem(bounds, ty.clean(cx))
|
||||
}
|
||||
};
|
||||
|
||||
Item {
|
||||
@ -1394,16 +1463,6 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
match *self {
|
||||
ty::ConstTraitItem(ref cti) => cti.clean(cx),
|
||||
ty::MethodTraitItem(ref mti) => mti.clean(cx),
|
||||
ty::TypeTraitItem(ref tti) => tti.clean(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait reference, which may have higher ranked lifetimes.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
pub struct PolyTrait {
|
||||
@ -2884,79 +2943,6 @@ impl Clean<Deprecation> for attr::Deprecation {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
source: DUMMY_SP.clean(cx),
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: Vec::new(),
|
||||
inner: AssociatedConstItem(self.ty.clean(cx), None),
|
||||
visibility: None,
|
||||
def_id: self.def_id,
|
||||
stability: None,
|
||||
deprecation: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let my_name = self.name.clean(cx);
|
||||
|
||||
let mut bounds = if let ty::TraitContainer(did) = self.container {
|
||||
// When loading a cross-crate associated type, the bounds for this type
|
||||
// are actually located on the trait/impl itself, so we need to load
|
||||
// all of the generics from there and then look for bounds that are
|
||||
// applied to this associated type in question.
|
||||
let def = cx.tcx().lookup_trait_def(did);
|
||||
let predicates = cx.tcx().lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
generics.where_predicates.iter().filter_map(|pred| {
|
||||
let (name, self_type, trait_, bounds) = match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref name, ref self_type, ref trait_ },
|
||||
ref bounds
|
||||
} => (name, self_type, trait_, bounds),
|
||||
_ => return None,
|
||||
};
|
||||
if *name != my_name { return None }
|
||||
match **trait_ {
|
||||
ResolvedPath { did, .. } if did == self.container.id() => {}
|
||||
_ => return None,
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == "Self" => {}
|
||||
_ => return None,
|
||||
}
|
||||
Some(bounds)
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => { bounds.remove(i); }
|
||||
None => bounds.push(TyParamBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
Item {
|
||||
source: DUMMY_SP.clean(cx),
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
|
||||
inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
|
||||
visibility: self.vis.clean(cx),
|
||||
def_id: self.def_id,
|
||||
stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
|
||||
deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lang_struct(cx: &DocContext, did: Option<DefId>,
|
||||
t: ty::Ty, name: &str,
|
||||
fallback: fn(Box<Type>) -> Type) -> Type {
|
||||
|
@ -1017,10 +1017,10 @@ pub enum ExprKind {
|
||||
Loop(P<Block>, Option<SpannedIdent>),
|
||||
/// A `match` block.
|
||||
Match(P<Expr>, Vec<Arm>),
|
||||
/// A closure (for example, `move |a, b, c| {a + b + c}`)
|
||||
/// A closure (for example, `move |a, b, c| a + b + c`)
|
||||
///
|
||||
/// The final span is the span of the argument block `|...|`
|
||||
Closure(CaptureBy, P<FnDecl>, P<Block>, Span),
|
||||
Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
|
||||
/// A block (`{ ... }`)
|
||||
Block(P<Block>),
|
||||
|
||||
|
@ -198,17 +198,13 @@ pub trait AstBuilder {
|
||||
fn lambda_fn_decl(&self,
|
||||
span: Span,
|
||||
fn_decl: P<ast::FnDecl>,
|
||||
blk: P<ast::Block>,
|
||||
body: P<ast::Expr>,
|
||||
fn_decl_span: Span)
|
||||
-> P<ast::Expr>;
|
||||
|
||||
fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr>;
|
||||
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr>;
|
||||
fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr>;
|
||||
|
||||
fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Expr>) -> P<ast::Expr>;
|
||||
fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>;
|
||||
fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
|
||||
fn lambda(&self, span: Span, ids: Vec<ast::Ident>, body: P<ast::Expr>) -> P<ast::Expr>;
|
||||
fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr>;
|
||||
fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
|
||||
|
||||
fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident>,
|
||||
blk: Vec<ast::Stmt>) -> P<ast::Expr>;
|
||||
@ -940,19 +936,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
fn lambda_fn_decl(&self,
|
||||
span: Span,
|
||||
fn_decl: P<ast::FnDecl>,
|
||||
blk: P<ast::Block>,
|
||||
body: P<ast::Expr>,
|
||||
fn_decl_span: Span) // span of the `|...|` part
|
||||
-> P<ast::Expr> {
|
||||
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
|
||||
fn_decl,
|
||||
blk,
|
||||
body,
|
||||
fn_decl_span))
|
||||
}
|
||||
|
||||
fn lambda(&self,
|
||||
span: Span,
|
||||
ids: Vec<ast::Ident>,
|
||||
blk: P<ast::Block>)
|
||||
body: P<ast::Expr>)
|
||||
-> P<ast::Expr> {
|
||||
let fn_decl = self.fn_decl(
|
||||
ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
|
||||
@ -962,26 +958,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
// part of the lambda, but it probably (maybe?) corresponds to
|
||||
// the entire lambda body. Probably we should extend the API
|
||||
// here, but that's not entirely clear.
|
||||
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk, span))
|
||||
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, body, span))
|
||||
}
|
||||
|
||||
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
|
||||
self.lambda(span, Vec::new(), blk)
|
||||
fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
|
||||
self.lambda(span, Vec::new(), body)
|
||||
}
|
||||
|
||||
fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr> {
|
||||
self.lambda(span, vec![ident], blk)
|
||||
}
|
||||
|
||||
fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident>,
|
||||
expr: P<ast::Expr>) -> P<ast::Expr> {
|
||||
self.lambda(span, ids, self.block_expr(expr))
|
||||
}
|
||||
fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
|
||||
self.lambda0(span, self.block_expr(expr))
|
||||
}
|
||||
fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
|
||||
self.lambda1(span, self.block_expr(expr), ident)
|
||||
fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
|
||||
self.lambda(span, vec![ident], body)
|
||||
}
|
||||
|
||||
fn lambda_stmts(&self,
|
||||
@ -989,14 +974,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
ids: Vec<ast::Ident>,
|
||||
stmts: Vec<ast::Stmt>)
|
||||
-> P<ast::Expr> {
|
||||
self.lambda(span, ids, self.block(span, stmts))
|
||||
self.lambda(span, ids, self.expr_block(self.block(span, stmts)))
|
||||
}
|
||||
fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr> {
|
||||
self.lambda0(span, self.block(span, stmts))
|
||||
self.lambda0(span, self.expr_block(self.block(span, stmts)))
|
||||
}
|
||||
fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>,
|
||||
ident: ast::Ident) -> P<ast::Expr> {
|
||||
self.lambda1(span, self.block(span, stmts), ident)
|
||||
self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
|
||||
}
|
||||
|
||||
fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {
|
||||
|
@ -354,7 +354,7 @@ declare_features! (
|
||||
// Allows `#[deprecated]` attribute
|
||||
(accepted, deprecated, "1.9.0", Some(29935)),
|
||||
// `expr?`
|
||||
(accepted, question_mark, "1.14.0", Some(31436)),
|
||||
(accepted, question_mark, "1.13.0", Some(31436)),
|
||||
// Allows `..` in tuple (struct) patterns
|
||||
(accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
|
||||
);
|
||||
@ -1228,12 +1228,11 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
fn visit_fn(&mut self,
|
||||
fn_kind: FnKind,
|
||||
fn_decl: &ast::FnDecl,
|
||||
block: &ast::Block,
|
||||
span: Span,
|
||||
_node_id: NodeId) {
|
||||
// check for const fn declarations
|
||||
match fn_kind {
|
||||
FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _) => {
|
||||
FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
|
||||
gate_feature_post!(&self, const_fn, span, "const fn is unstable");
|
||||
}
|
||||
_ => {
|
||||
@ -1245,13 +1244,13 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
}
|
||||
|
||||
match fn_kind {
|
||||
FnKind::ItemFn(_, _, _, _, abi, _) |
|
||||
FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => {
|
||||
FnKind::ItemFn(_, _, _, _, abi, _, _) |
|
||||
FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
|
||||
self.check_abi(abi, span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_fn(self, fn_kind, fn_decl, block, span);
|
||||
visit::walk_fn(self, fn_kind, fn_decl, span);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
|
||||
|
@ -1201,7 +1201,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||
ExprKind::Closure(capture_clause, decl, body, span) => {
|
||||
ExprKind::Closure(capture_clause,
|
||||
folder.fold_fn_decl(decl),
|
||||
folder.fold_block(body),
|
||||
folder.fold_expr(body),
|
||||
folder.new_span(span))
|
||||
}
|
||||
ExprKind::Block(blk) => ExprKind::Block(folder.fold_block(blk)),
|
||||
|
@ -3162,25 +3162,12 @@ impl<'a> Parser<'a> {
|
||||
let decl = self.parse_fn_block_decl()?;
|
||||
let decl_hi = self.prev_span.hi;
|
||||
let body = match decl.output {
|
||||
FunctionRetTy::Default(_) => {
|
||||
// If no explicit return type is given, parse any
|
||||
// expr and wrap it up in a dummy block:
|
||||
let body_expr = self.parse_expr()?;
|
||||
P(ast::Block {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: body_expr.span,
|
||||
stmts: vec![Stmt {
|
||||
span: body_expr.span,
|
||||
node: StmtKind::Expr(body_expr),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
}],
|
||||
rules: BlockCheckMode::Default,
|
||||
})
|
||||
}
|
||||
FunctionRetTy::Default(_) => self.parse_expr()?,
|
||||
_ => {
|
||||
// If an explicit return type is given, require a
|
||||
// block to appear (RFC 968).
|
||||
self.parse_block()?
|
||||
let body_lo = self.span.lo;
|
||||
self.parse_block_expr(body_lo, BlockCheckMode::Default, ThinVec::new())?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2128,26 +2128,8 @@ impl<'a> State<'a> {
|
||||
|
||||
try!(self.print_fn_block_args(&decl));
|
||||
try!(space(&mut self.s));
|
||||
|
||||
let default_return = match decl.output {
|
||||
ast::FunctionRetTy::Default(..) => true,
|
||||
_ => false
|
||||
};
|
||||
|
||||
match body.stmts.last().map(|stmt| &stmt.node) {
|
||||
Some(&ast::StmtKind::Expr(ref i_expr)) if default_return &&
|
||||
body.stmts.len() == 1 => {
|
||||
// we extract the block, so as not to create another set of boxes
|
||||
if let ast::ExprKind::Block(ref blk) = i_expr.node {
|
||||
try!(self.print_block_unclosed_with_attrs(&blk, &i_expr.attrs));
|
||||
} else {
|
||||
// this is a bare expression
|
||||
try!(self.print_expr(&i_expr));
|
||||
try!(self.end()); // need to close a box
|
||||
}
|
||||
}
|
||||
_ => try!(self.print_block_unclosed(&body)),
|
||||
}
|
||||
try!(self.print_expr(body));
|
||||
try!(self.end()); // need to close a box
|
||||
|
||||
// a box will be closed by print_expr, but we didn't want an overall
|
||||
// wrapper so we closed the corresponding opening. so create an
|
||||
|
@ -75,9 +75,9 @@ impl Visitor for NodeCounter {
|
||||
self.count += 1;
|
||||
walk_generics(self, g)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId) {
|
||||
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
|
||||
self.count += 1;
|
||||
walk_fn(self, fk, fd, b, s)
|
||||
walk_fn(self, fk, fd, s)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &TraitItem) {
|
||||
self.count += 1;
|
||||
|
@ -31,13 +31,13 @@ use codemap::Spanned;
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum FnKind<'a> {
|
||||
/// fn foo() or extern "Abi" fn foo()
|
||||
ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility),
|
||||
ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block),
|
||||
|
||||
/// fn foo(&self)
|
||||
Method(Ident, &'a MethodSig, Option<&'a Visibility>),
|
||||
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
|
||||
|
||||
/// |x, y| {}
|
||||
Closure,
|
||||
/// |x, y| body
|
||||
Closure(&'a Expr),
|
||||
}
|
||||
|
||||
/// Each method of the Visitor trait is a hook to be potentially
|
||||
@ -68,8 +68,8 @@ pub trait Visitor: Sized {
|
||||
fn visit_expr_post(&mut self, _ex: &Expr) { }
|
||||
fn visit_ty(&mut self, t: &Ty) { walk_ty(self, t) }
|
||||
fn visit_generics(&mut self, g: &Generics) { walk_generics(self, g) }
|
||||
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId) {
|
||||
walk_fn(self, fk, fd, b, s)
|
||||
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
|
||||
walk_fn(self, fk, fd, s)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &TraitItem) { walk_trait_item(self, ti) }
|
||||
fn visit_impl_item(&mut self, ii: &ImplItem) { walk_impl_item(self, ii) }
|
||||
@ -246,9 +246,8 @@ pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
|
||||
}
|
||||
ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
|
||||
visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety,
|
||||
constness, abi, &item.vis),
|
||||
constness, abi, &item.vis, body),
|
||||
declaration,
|
||||
body,
|
||||
item.span,
|
||||
item.id)
|
||||
}
|
||||
@ -519,24 +518,25 @@ pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, function_declaration: &FnDecl)
|
||||
visitor.visit_fn_ret_ty(&function_declaration.output)
|
||||
}
|
||||
|
||||
pub fn walk_fn_kind<V: Visitor>(visitor: &mut V, function_kind: FnKind) {
|
||||
match function_kind {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _) => {
|
||||
visitor.visit_generics(generics);
|
||||
}
|
||||
FnKind::Method(_, ref sig, _) => {
|
||||
visitor.visit_generics(&sig.generics);
|
||||
}
|
||||
FnKind::Closure => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_fn<V>(visitor: &mut V, kind: FnKind, declaration: &FnDecl, body: &Block, _span: Span)
|
||||
pub fn walk_fn<V>(visitor: &mut V, kind: FnKind, declaration: &FnDecl, _span: Span)
|
||||
where V: Visitor,
|
||||
{
|
||||
walk_fn_kind(visitor, kind);
|
||||
walk_fn_decl(visitor, declaration);
|
||||
visitor.visit_block(body)
|
||||
match kind {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _, body) => {
|
||||
visitor.visit_generics(generics);
|
||||
walk_fn_decl(visitor, declaration);
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
FnKind::Method(_, ref sig, _, body) => {
|
||||
visitor.visit_generics(&sig.generics);
|
||||
walk_fn_decl(visitor, declaration);
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
FnKind::Closure(body) => {
|
||||
walk_fn_decl(visitor, declaration);
|
||||
visitor.visit_expr(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
|
||||
@ -552,8 +552,8 @@ pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
|
||||
walk_fn_decl(visitor, &sig.decl);
|
||||
}
|
||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None), &sig.decl,
|
||||
body, trait_item.span, trait_item.id);
|
||||
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
|
||||
&sig.decl, trait_item.span, trait_item.id);
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
@ -575,8 +575,8 @@ pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)), &sig.decl,
|
||||
body, impl_item.span, impl_item.id);
|
||||
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
|
||||
&sig.decl, impl_item.span, impl_item.id);
|
||||
}
|
||||
ImplItemKind::Type(ref ty) => {
|
||||
visitor.visit_ty(ty);
|
||||
@ -711,9 +711,8 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) {
|
||||
walk_list!(visitor, visit_arm, arms);
|
||||
}
|
||||
ExprKind::Closure(_, ref function_declaration, ref body, _decl_span) => {
|
||||
visitor.visit_fn(FnKind::Closure,
|
||||
visitor.visit_fn(FnKind::Closure(body),
|
||||
function_declaration,
|
||||
body,
|
||||
expression.span,
|
||||
expression.id)
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
|
||||
cx.ident_of("read_struct"),
|
||||
vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
|
||||
cx.expr_usize(trait_span, nfields),
|
||||
cx.lambda_expr_1(trait_span, result, blkarg)])
|
||||
cx.lambda1(trait_span, result, blkarg)])
|
||||
}
|
||||
StaticEnum(_, ref fields) => {
|
||||
let variant = cx.ident_of("i");
|
||||
@ -165,7 +165,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
|
||||
let result =
|
||||
cx.expr_ok(trait_span,
|
||||
cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms));
|
||||
let lambda = cx.lambda_expr(trait_span, vec![blkarg, variant], result);
|
||||
let lambda = cx.lambda(trait_span, vec![blkarg, variant], result);
|
||||
let variant_vec = cx.expr_vec(trait_span, variants);
|
||||
let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
|
||||
let result = cx.expr_method_call(trait_span,
|
||||
@ -176,7 +176,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
|
||||
decoder,
|
||||
cx.ident_of("read_enum"),
|
||||
vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
|
||||
cx.lambda_expr_1(trait_span, result, blkarg)])
|
||||
cx.lambda1(trait_span, result, blkarg)])
|
||||
}
|
||||
_ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
|
||||
};
|
||||
|
@ -197,7 +197,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
|
||||
};
|
||||
let self_ref = cx.expr_addr_of(span, self_.clone());
|
||||
let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
||||
let lambda = cx.lambda_expr_1(span, enc, blkarg);
|
||||
let lambda = cx.lambda1(span, enc, blkarg);
|
||||
let call = cx.expr_method_call(span,
|
||||
blkencoder.clone(),
|
||||
emit_struct_field,
|
||||
@ -246,7 +246,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
|
||||
let self_ref = cx.expr_addr_of(span, self_.clone());
|
||||
let enc =
|
||||
cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
||||
let lambda = cx.lambda_expr_1(span, enc, blkarg);
|
||||
let lambda = cx.lambda1(span, enc, blkarg);
|
||||
let call = cx.expr_method_call(span,
|
||||
blkencoder.clone(),
|
||||
emit_variant_arg,
|
||||
@ -273,7 +273,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
|
||||
cx.expr_usize(trait_span, idx),
|
||||
cx.expr_usize(trait_span, fields.len()),
|
||||
blk]);
|
||||
let blk = cx.lambda_expr_1(trait_span, call, blkarg);
|
||||
let blk = cx.lambda1(trait_span, call, blkarg);
|
||||
let ret = cx.expr_method_call(trait_span,
|
||||
encoder,
|
||||
cx.ident_of("emit_enum"),
|
||||
|
@ -11,10 +11,10 @@
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize {}
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }
|
||||
//~^ NOTE previous `start` function here
|
||||
|
||||
#[start]
|
||||
fn f(argc: isize, argv: *const *const u8) -> isize {}
|
||||
fn f(argc: isize, argv: *const *const u8) -> isize { 0 }
|
||||
//~^ ERROR E0138
|
||||
//~| NOTE multiple `start` functions
|
||||
|
@ -8,12 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn f() -> String { //~ ERROR E0269
|
||||
fn f() -> String { //~ ERROR mismatched types
|
||||
0u8;
|
||||
"bla".to_string(); //~ HELP consider removing this semicolon
|
||||
}
|
||||
|
||||
fn g() -> String { //~ ERROR E0269
|
||||
fn g() -> String { //~ ERROR mismatched types
|
||||
"this won't work".to_string();
|
||||
"removeme".to_string(); //~ HELP consider removing this semicolon
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user