Auto merge of - eddyb:rollup, r=eddyb

Rollup of 5 pull requests

- Successful merges: , , , , 
- Failed merges:
This commit is contained in:
bors 2016-11-09 18:22:47 -08:00 committed by GitHub
commit b46ce08df5
148 changed files with 1830 additions and 2527 deletions

@ -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, &param_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