This is dependent on https://github.com/rust-lang/rust-installer/pull/38. Once it is merged we most likely need to update the commit.
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl<T: ?Sized> !marker::Send for Weak<T> {}
impl<T: ?Sized> !marker::Sync for Weak<T> {}
+impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
#[unstable(feature = "rc_weak",
reason = "Weak pointers may not belong in this module.")]
impl<T: ?Sized> Weak<T> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Traits for dynamic typing of any `'static` type (through runtime reflection)
-//!
//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
NodeLifetime(&'ast Lifetime),
}
-/// Represents an entry and its parent Node ID
+/// Represents an entry and its parent NodeID.
/// The odd layout is to bring down the total size.
#[derive(Copy, Debug)]
enum MapEntry<'ast> {
}
}
- fn parent(self) -> Option<NodeId> {
+ fn parent_node(self) -> Option<NodeId> {
Some(match self {
EntryItem(id, _) => id,
EntryForeignItem(id, _) => id,
self.find_entry(id).and_then(|x| x.to_node())
}
- /// Retrieve the parent NodeId for `id`, or `id` itself if no
- /// parent is registered in this map.
+ /// Similar to get_parent, returns the parent node id or id if there is no
+ /// parent.
+ /// This function returns the immediate parent in the AST, whereas get_parent
+ /// returns the enclosing item. Note that this might not be the actual parent
+ /// node in the AST - some kinds of nodes are not in the map and these will
+ /// never appear as the parent_node. So you can always walk the parent_nodes
+ /// from a node to the root of the ast (unless you get the same id back here
+ /// that can happen if the id is not in the map itself or is just weird).
+ pub fn get_parent_node(&self, id: NodeId) -> NodeId {
+ self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
+ }
+
+ /// If there is some error when walking the parents (e.g., a node does not
+ /// have a parent in the map or a node can't be found), then we return the
+ /// last good node id we found. Note that reaching the crate root (id == 0),
+ /// is not an error, since items in the crate module have the crate root as
+ /// parent.
+ fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
+ where F: Fn(&Node<'ast>) -> bool
+ {
+ let mut id = start_id;
+ loop {
+ let parent_node = self.get_parent_node(id);
+ if parent_node == 0 {
+ return Ok(0);
+ }
+ if parent_node == id {
+ return Err(id);
+ }
+
+ let node = self.find_entry(parent_node);
+ if node.is_none() {
+ return Err(id);
+ }
+ let node = node.unwrap().to_node();
+ match node {
+ Some(ref node) => {
+ if found(node) {
+ return Ok(parent_node);
+ }
+ }
+ None => {
+ return Err(parent_node);
+ }
+ }
+ id = parent_node;
+ }
+ }
+
+ /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
+ /// parent item is in this map. The "parent item" is the closest parent node
+ /// in the AST which is recorded by the map and is an item, either an item
+ /// in a module, trait, or impl.
pub fn get_parent(&self, id: NodeId) -> NodeId {
- self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
+ match self.walk_parent_nodes(id, |node| match *node {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) => true,
+ _ => false,
+ }) {
+ Ok(id) => id,
+ Err(id) => id,
+ }
+ }
+
+ /// Returns the nearest enclosing scope. A scope is an item or block.
+ /// FIXME it is not clear to me that all items qualify as scopes - statics
+ /// and associated types probably shouldn't, for example. Behaviour in this
+ /// regard should be expected to be highly unstable.
+ pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
+ match self.walk_parent_nodes(id, |node| match *node {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) |
+ NodeBlock(_) => true,
+ _ => false,
+ }) {
+ Ok(id) => Some(id),
+ Err(_) => None,
+ }
}
pub fn get_parent_did(&self, id: NodeId) -> DefId {
return None;
}
self.idx += 1;
- let (p, name) = match self.map.find_entry(idx) {
- Some(EntryItem(p, n)) => (p, n.name()),
- Some(EntryForeignItem(p, n))=> (p, n.name()),
- Some(EntryTraitItem(p, n)) => (p, n.name()),
- Some(EntryImplItem(p, n)) => (p, n.name()),
- Some(EntryVariant(p, n)) => (p, n.name()),
+ let name = match self.map.find_entry(idx) {
+ Some(EntryItem(_, n)) => n.name(),
+ Some(EntryForeignItem(_, n))=> n.name(),
+ Some(EntryTraitItem(_, n)) => n.name(),
+ Some(EntryImplItem(_, n)) => n.name(),
+ Some(EntryVariant(_, n)) => n.name(),
_ => continue,
};
- if self.matches_names(p, name) {
+ if self.matches_names(self.map.get_parent(idx), name) {
return Some(idx)
}
}
/// A Visitor that walks over an AST and collects Node's into an AST Map.
struct NodeCollector<'ast> {
map: Vec<MapEntry<'ast>>,
- /// The node in which we are currently mapping (an item or a method).
- parent: NodeId
+ parent_node: NodeId,
}
impl<'ast> NodeCollector<'ast> {
}
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
- let entry = MapEntry::from_node(self.parent, node);
+ let entry = MapEntry::from_node(self.parent_node, node);
self.insert_entry(id, entry);
}
impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
fn visit_item(&mut self, i: &'ast Item) {
self.insert(i.id, NodeItem(i));
- let parent = self.parent;
- self.parent = i.id;
+
+ let parent_node = self.parent_node;
+ self.parent_node = i.id;
+
match i.node {
ItemImpl(_, _, _, _, _, ref impl_items) => {
for ii in impl_items {
_ => {}
}
visit::walk_item(self, i);
- self.parent = parent;
+ self.parent_node = parent_node;
}
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
- let parent = self.parent;
- self.parent = ti.id;
+ let parent_node = self.parent_node;
+ self.parent_node = ti.id;
visit::walk_trait_item(self, ti);
- self.parent = parent;
+ self.parent_node = parent_node;
}
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
- let parent = self.parent;
- self.parent = ii.id;
+ let parent_node = self.parent_node;
+ self.parent_node = ii.id;
+
visit::walk_impl_item(self, ii);
- self.parent = parent;
+
+ self.parent_node = parent_node;
}
fn visit_pat(&mut self, pat: &'ast Pat) {
PatIdent(..) => NodeLocal(pat),
_ => NodePat(pat)
});
+
+ let parent_node = self.parent_node;
+ self.parent_node = pat.id;
visit::walk_pat(self, pat);
+ self.parent_node = parent_node;
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.insert(expr.id, NodeExpr(expr));
+ let parent_node = self.parent_node;
+ self.parent_node = expr.id;
visit::walk_expr(self, expr);
+ self.parent_node = parent_node;
}
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
- self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
+ let id = ast_util::stmt_id(stmt);
+ self.insert(id, NodeStmt(stmt));
+ let parent_node = self.parent_node;
+ self.parent_node = id;
visit::walk_stmt(self, stmt);
+ self.parent_node = parent_node;
}
fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
- b: &'ast Block, s: Span, _: NodeId) {
+ b: &'ast Block, s: Span, id: NodeId) {
+ let parent_node = self.parent_node;
+ self.parent_node = id;
self.visit_fn_decl(fd);
visit::walk_fn(self, fk, fd, b, s);
+ self.parent_node = parent_node;
}
fn visit_ty(&mut self, ty: &'ast Ty) {
+ let parent_node = self.parent_node;
+ self.parent_node = ty.id;
match ty.node {
TyBareFn(ref fd) => {
self.visit_fn_decl(&*fd.decl);
_ => {}
}
visit::walk_ty(self, ty);
+ self.parent_node = parent_node;
}
fn visit_block(&mut self, block: &'ast Block) {
self.insert(block.id, NodeBlock(block));
+ let parent_node = self.parent_node;
+ self.parent_node = block.id;
visit::walk_block(self, block);
+ self.parent_node = parent_node;
}
fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
let mut collector = NodeCollector {
map: vec![],
- parent: CRATE_NODE_ID
+ parent_node: CRATE_NODE_ID,
};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
visit::walk_crate(&mut collector, &forest.krate);
ii: ii
});
+ let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let mut collector = NodeCollector {
map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
- parent: fld.new_id(DUMMY_NODE_ID)
+ parent_node: ii_parent_id,
};
- let ii_parent_id = collector.parent;
collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
visit::walk_inlined_item(&mut collector, &ii_parent.ii);
E0267: r##"
This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Break and continue can be used as normal inside
-closures as long as they are also contained within a loop. To halt the execution
-of a closure you should instead use a return statement.
+closure but outside of any loop. Erroneous code example:
+
+```
+let w = || { break; }; // error: `break` inside of a closure
+```
+
+`break` and `continue` keywords can be used as normal inside closures as long as
+they are also contained within a loop. To halt the execution of a closure you
+should instead use a return statement. Example:
+
+```
+let w = || {
+ for _ in 0..10 {
+ break;
+ }
+};
+
+w();
+```
"##,
E0268: r##"
This error indicates the use of a loop keyword (`break` or `continue`) outside
of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken.
+be taken. Erroneous code example:
+
+```
+fn some_func() {
+ break; // error: `break` outside of loop
+}
+```
+
+Please verify that you are using `break` and `continue` only in loops. Example:
+
+```
+fn some_func() {
+ for _ in 0..10 {
+ break; // ok!
+ }
+}
+```
"##,
E0271: r##"
```
"##,
+E0277: r##"
+You tried to use a type which doesn't implement some trait in a place which
+expected that trait. Erroneous code example:
+
+```
+// here we declare the Foo trait with a bar method
+trait Foo {
+ fn bar(&self);
+}
+
+// we now declare a function which takes an object with Foo trait implemented
+// as parameter
+fn some_func<T: Foo>(foo: T) {
+ foo.bar();
+}
+
+fn main() {
+ // we now call the method with the i32 type, which doesn't implement
+ // the Foo trait
+ some_func(5i32); // error: the trait `Foo` is not implemented for the
+ // type `i32`
+}
+```
+
+In order to fix this error, verify that the type you're using does implement
+the trait. Example:
+
+```
+trait Foo {
+ fn bar(&self);
+}
+
+fn some_func<T: Foo>(foo: T) {
+ foo.bar(); // we can now use this method since i32 implements the
+ // Foo trait
+}
+
+// we implement the trait on the i32 type
+impl Foo for i32 {
+ fn bar(&self) {}
+}
+
+fn main() {
+ some_func(5i32); // ok!
+}
+```
+"##,
+
E0282: r##"
This error indicates that type inference did not result in one unique possible
type, and extra information is required. In most cases this can be provided
E0274, // rustc_on_unimplemented must have a value
E0275, // overflow evaluating requirement
E0276, // requirement appears on impl method but not on corresponding trait method
- E0277, // trait is not implemented for type
E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
E0280, // requirement is not satisfied
#![feature(vec_push_all)]
#![feature(wrapping)]
#![feature(cell_extras)]
+#![feature(page_size)]
#![cfg_attr(test, feature(test))]
#![allow(trivial_casts)]
use metadata::tyencode;
use middle::cast;
use middle::check_const::ConstQualif;
-use middle::mem_categorization::Typer;
use middle::privacy::{AllPublic, LastMod};
use middle::subst;
use middle::subst::VecPerParamSpace;
c::tag_table_tcache => {
let type_scheme = val_dsr.read_type_scheme(dcx);
let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
- dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme);
+ dcx.tcx.register_item_type(lid, type_scheme);
}
c::tag_table_param_defs => {
let bounds = val_dsr.read_type_param_def(dcx);
}
fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
- F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'tcx,
- ty::ParameterEnvironment<'a, 'tcx>>) -> R,
+ F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
{
let param_env = match item_id {
Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
None => self.tcx.empty_parameter_environment()
};
- f(&mut euv::ExprUseVisitor::new(self, ¶m_env))
+
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), false);
+
+ f(&mut euv::ExprUseVisitor::new(self, &infcx))
}
fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
fn check_static_type(&self, e: &ast::Expr) {
let ty = self.tcx.node_id_to_type(e.id);
- let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
- let mut fulfill_cx = traits::FulfillmentContext::new(false);
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
- match fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+ match fulfill_cx.select_all_or_error(&infcx) {
Ok(()) => { },
Err(ref errors) => {
traits::report_fulfillment_errors(&infcx, errors);
use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
use middle::expr_use_visitor::WriteAndRead;
use middle::expr_use_visitor as euv;
-use middle::mem_categorization::{cmt, Typer};
+use middle::infer;
+use middle::mem_categorization::{cmt};
use middle::pat_util::*;
use middle::ty::*;
use middle::ty;
match p.node {
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
let pat_ty = tcx.node_id_to_type(p.id);
- if cx.param_env.type_moves_by_default(pat_ty, pat.span) {
+ //FIXME: (@jroesch) this code should be floated up as well
+ let infcx = infer::new_infer_ctxt(cx.tcx,
+ &cx.tcx.tables,
+ Some(cx.param_env.clone()),
+ false);
+ if infcx.type_moves_by_default(pat_ty, pat.span) {
check_move(p, sub.as_ref().map(|p| &**p));
}
}
let mut checker = MutationChecker {
cx: cx,
};
- let mut visitor = ExprUseVisitor::new(&mut checker,
- &checker.cx.param_env);
+
+ let infcx = infer::new_infer_ctxt(cx.tcx,
+ &cx.tcx.tables,
+ Some(checker.cx.param_env.clone()),
+ false);
+
+ let mut visitor = ExprUseVisitor::new(&mut checker, &infcx);
visitor.walk_expr(guard);
}
// is the public starting point.
use middle::expr_use_visitor as euv;
+use middle::infer;
use middle::mem_categorization as mc;
use middle::ty::ParameterEnvironment;
use middle::ty;
s: Span,
fn_id: ast::NodeId) {
{
+ // FIXME (@jroesch) change this to be an inference context
let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+ let infcx = infer::new_infer_ctxt(self.tcx,
+ &self.tcx.tables,
+ Some(param_env.clone()),
+ false);
let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env };
- let mut euv = euv::ExprUseVisitor::new(&mut delegate, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
euv.walk_fn(fd, b);
}
visit::walk_fn(self, fk, fd, b, s)
substs: trait_substs });
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
- let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+ let mut selcx = traits::SelectionContext::new(&infcx);
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
trait_ref.to_poly_trait_predicate());
let selection = match selcx.select(&obligation) {
use self::OverloadedCallType::*;
use middle::{def, region, pat_util};
+use middle::infer;
use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::ty::{self};
use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
// supplies types from the tree. After type checking is complete, you
// can just use the tcx as the typer.
-pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> {
- typer: &'t TYPER,
- mc: mc::MemCategorizationContext<'t,TYPER>,
+pub struct ExprUseVisitor<'d,'t,'a: 't, 'tcx:'a> {
+ typer: &'t infer::InferCtxt<'a, 'tcx>,
+ mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
delegate: &'d mut (Delegate<'tcx>+'d),
}
ByRef,
}
-impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
pub fn new(delegate: &'d mut Delegate<'tcx>,
- typer: &'t TYPER)
- -> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+ typer: &'t infer::InferCtxt<'a, 'tcx>)
+ -> ExprUseVisitor<'d,'t,'a, 'tcx> {
ExprUseVisitor {
typer: typer,
mc: mc::MemCategorizationContext::new(typer),
}
fn tcx(&self) -> &'t ty::ctxt<'tcx> {
- self.typer.tcx()
+ self.typer.tcx
}
fn delegate_consume(&mut self,
match local.init {
None => {
let delegate = &mut self.delegate;
- pat_util::pat_bindings(&self.typer.tcx().def_map, &*local.pat,
+ pat_util::pat_bindings(&self.typer.tcx.def_map, &*local.pat,
|_, id, span, _| {
delegate.decl_without_init(id, span);
})
let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
if pat_util::pat_is_binding(def_map, pat) {
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
cmt_pat,
// the leaves of the pattern tree structure.
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
let def_map = def_map.borrow();
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
match pat.node {
ast::PatEnum(_, _) | ast::PatQPath(..) |
}
}
-fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
+fn copy_or_move<'a, 'tcx>(typer: &infer::InferCtxt<'a, 'tcx>,
cmt: &mc::cmt<'tcx>,
move_reason: MoveReason)
-> ConsumeMode
struct Implicator<'a, 'tcx: 'a> {
infcx: &'a InferCtxt<'a,'tcx>,
- closure_typer: &'a (ty::ClosureTyper<'tcx>+'a),
body_id: ast::NodeId,
stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
span: Span,
/// appear in a context with lifetime `outer_region`
pub fn implications<'a,'tcx>(
infcx: &'a InferCtxt<'a,'tcx>,
- closure_typer: &ty::ClosureTyper<'tcx>,
body_id: ast::NodeId,
ty: Ty<'tcx>,
outer_region: ty::Region,
let mut stack = Vec::new();
stack.push((outer_region, None));
- let mut wf = Implicator { closure_typer: closure_typer,
- infcx: infcx,
+ let mut wf = Implicator { infcx: infcx,
body_id: body_id,
span: span,
stack: stack,
{
let value =
traits::fully_normalize(self.infcx,
- self.closure_typer,
traits::ObligationCause::misc(self.span, self.body_id),
value);
match value {
use middle::subst;
use middle::subst::Substs;
use middle::subst::Subst;
-use middle::traits;
+use middle::traits::{self, FulfillmentContext, Normalized,
+ SelectionContext, ObligationCause};
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
use middle::ty::{self, Ty, HasTypeFlags};
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
use std::fmt;
use syntax::ast;
use syntax::codemap;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
use util::nodemap::{FnvHashMap, NodeMap};
use self::combine::CombineFields;
pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>,
+ pub fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+
// This is a temporary field used for toggling on normalization in the inference context,
// as we move towards the approach described here:
// https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
}
}
+/// errors_will_be_reported is required to proxy to the fulfillment context
+/// FIXME -- a better option would be to hold back on modifying
+/// the global cache until we know that all dependent obligations
+/// are also satisfied. In that case, we could actually remove
+/// this boolean flag, and we'd also avoid the problem of squelching
+/// duplicate errors that occur across fns.
pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
tables: &'a RefCell<ty::Tables<'tcx>>,
- param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
+ param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
+ errors_will_be_reported: bool)
-> InferCtxt<'a, 'tcx> {
InferCtxt {
tcx: tcx,
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(tcx),
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
+ fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
normalize: false,
err_count_on_creation: tcx.sess.err_count()
}
}
+pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
+ tables: &'a RefCell<ty::Tables<'tcx>>)
+ -> InferCtxt<'a, 'tcx> {
+ let mut infcx = new_infer_ctxt(tcx, tables, None, false);
+ infcx.normalize = true;
+ infcx
+}
+
/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
/// returns ty::err.
pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
region_vars_snapshot: RegionSnapshot,
}
-impl<'a, 'tcx> mc::Typer<'tcx> for InferCtxt<'a, 'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
- let ty = self.node_ty(id);
- self.resolve_type_vars_or_error(&ty)
- }
+pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
+ where T : TypeFoldable<'tcx> + HasTypeFlags
+{
+ debug!("normalize_associated_type(t={:?})", value);
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
- let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
- self.resolve_type_vars_or_error(&ty)
- }
+ let value = erase_regions(tcx, value);
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- let ty = self.resolve_type_vars_if_possible(&ty);
- !traits::type_known_to_meet_builtin_bound(self, self, ty, ty::BoundCopy, span)
+ if !value.has_projection_types() {
+ return value;
}
- fn node_method_ty(&self, method_call: ty::MethodCall)
- -> Option<Ty<'tcx>> {
- self.tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.ty)
- .map(|ty| self.resolve_type_vars_if_possible(&ty))
- }
+ let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let cause = traits::ObligationCause::dummy();
+ let traits::Normalized { value: result, obligations } =
+ traits::normalize(&mut selcx, cause, &value);
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.origin.clone())
- }
+ debug!("normalize_associated_type: result={:?} obligations={:?}",
+ result,
+ obligations);
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
- -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
- Ref::map(self.tables.borrow(), project_adjustments)
+ for obligation in obligations {
+ fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
- }
+ let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
- self.parameter_environment.temporary_scope(rvalue_id)
- }
+ result
+}
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
+ infcx: &InferCtxt<'a,'tcx>,
+ fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+ result: &T)
+ -> T
+ where T : TypeFoldable<'tcx>
+{
+ match drain_fulfillment_cx(infcx, fulfill_cx, result) {
+ Ok(v) => v,
+ Err(errors) => {
+ infcx.tcx.sess.span_bug(
+ span,
+ &format!("Encountered errors `{:?}` fulfilling during trans",
+ errors));
+ }
}
}
-impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- &self.parameter_environment
+/// Finishes processes any obligations that remain in the fulfillment
+/// context, and then "freshens" and returns `result`. This is
+/// primarily used during normalization and other cases where
+/// processing the obligations in `fulfill_cx` may cause type
+/// inference variables that appear in `result` to be unified, and
+/// hence we need to process those obligations to get the complete
+/// picture of the type.
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+ fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+ result: &T)
+ -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
+ where T : TypeFoldable<'tcx>
+{
+ debug!("drain_fulfillment_cx(result={:?})",
+ result);
+
+ // In principle, we only need to do this so long as `result`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ match fulfill_cx.select_all_or_error(infcx) {
+ Ok(()) => { }
+ Err(errors) => {
+ return Err(errors);
+ }
}
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- self.tables.borrow().closure_kinds.get(&def_id).cloned()
- }
+ // Use freshen to simultaneously replace all type variables with
+ // their bindings and replace all regions with 'static. This is
+ // sort of overkill because we do not expect there to be any
+ // unbound type variables, hence no `TyFresh` types should ever be
+ // inserted.
+ Ok(result.fold_with(&mut infcx.freshener()))
+}
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
+/// Returns an equivalent value with all free regions removed (note
+/// that late-bound regions remain, because they are important for
+/// subtyping, but they are anonymized and normalized as well). This
+/// is a stronger, caching version of `ty_fold::erase_regions`.
+pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
+ where T : TypeFoldable<'tcx>
+{
+ let value1 = value.fold_with(&mut RegionEraser(cx));
+ debug!("erase_regions({:?}) = {:?}",
+ value, value1);
+ return value1;
- let closure_ty = self.tables
- .borrow()
- .closure_tys
- .get(&def_id)
- .unwrap()
- .subst(self.tcx, substs);
+ struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
- if self.normalize {
- // NOTE: this flag is currently *always* set to false, we are slowly folding
- // normalization into this trait and will come back to remove this in the near
- // future.
-
- // code from NormalizingClosureTyper:
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- // normalize_associated_type(self.param_env.tcx, &closure_ty)
- panic!("see issue 26597: fufillment context refactor must occur")
- } else {
- closure_ty
+ impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
+ fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
+ None => {}
+ Some(u) => return u
+ }
+
+ let t_norm = ty_fold::super_fold_ty(self, ty);
+ self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
+ return t_norm;
}
- }
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- let result = ty::ctxt::closure_upvars(self, def_id, substs);
+ fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+ where T : TypeFoldable<'tcx>
+ {
+ let u = self.tcx().anonymize_late_bound_regions(t);
+ ty_fold::super_fold_binder(self, &u)
+ }
- if self.normalize {
- // NOTE: this flag is currently *always* set to false, we are slowly folding
- // normalization into this trait and will come back to remove this in the near
- // future.
-
- // code from NormalizingClosureTyper:
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- // monomorphize::normalize_associated_type(self.param_env.tcx, &result)
- panic!("see issue 26597: fufillment context refactor must occur")
- } else {
- result
+ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+ // because late-bound regions affect subtyping, we can't
+ // erase the bound/free distinction, but we can replace
+ // all free regions with 'static.
+ //
+ // Note that we *CAN* replace early-bound regions -- the
+ // type system never "sees" those, they get substituted
+ // away. In trans, they will always be erased to 'static
+ // whenever a substitution occurs.
+ match r {
+ ty::ReLateBound(..) => r,
+ _ => ty::ReStatic
+ }
+ }
+
+ fn fold_substs(&mut self,
+ substs: &subst::Substs<'tcx>)
+ -> subst::Substs<'tcx> {
+ subst::Substs { regions: subst::ErasedRegions,
+ types: substs.types.fold_with(self) }
}
}
}
.map(|method| resolve_ty(method.ty)))
}
- pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+ pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
match self.tables.borrow().node_types.get(&id) {
Some(&t) => t,
// FIXME
self.equate(true, trace).relate(a, b)
}).map(|_| ())
}
+
+ pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
+ let ty = self.node_type(id);
+ self.resolve_type_vars_or_error(&ty)
+ }
+
+ pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+ let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
+ self.resolve_type_vars_or_error(&ty)
+ }
+
+ pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+ let ty = self.resolve_type_vars_if_possible(&ty);
+ !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
+ // FIXME(@jroesch): should be able to use:
+ // ty.moves_by_default(&self.parameter_environment, span)
+ }
+
+ pub fn node_method_ty(&self, method_call: ty::MethodCall)
+ -> Option<Ty<'tcx>> {
+ self.tables
+ .borrow()
+ .method_map
+ .get(&method_call)
+ .map(|method| method.ty)
+ .map(|ty| self.resolve_type_vars_if_possible(&ty))
+ }
+
+ pub fn node_method_origin(&self, method_call: ty::MethodCall)
+ -> Option<ty::MethodOrigin<'tcx>>
+ {
+ self.tables
+ .borrow()
+ .method_map
+ .get(&method_call)
+ .map(|method| method.origin.clone())
+ }
+
+ pub fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
+ fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
+ -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
+ &tables.adjustments
+ }
+
+ Ref::map(self.tables.borrow(), project_adjustments)
+ }
+
+ pub fn is_method_call(&self, id: ast::NodeId) -> bool {
+ self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
+ }
+
+ pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
+ self.tcx.region_maps.temporary_scope(rvalue_id)
+ }
+
+ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
+ self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+ }
+
+ pub fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
+ &self.parameter_environment
+ }
+
+ pub fn closure_kind(&self,
+ def_id: ast::DefId)
+ -> Option<ty::ClosureKind>
+ {
+ self.tables.borrow().closure_kinds.get(&def_id).cloned()
+ }
+
+ pub fn closure_type(&self,
+ def_id: ast::DefId,
+ substs: &subst::Substs<'tcx>)
+ -> ty::ClosureTy<'tcx>
+ {
+
+ let closure_ty = self.tables
+ .borrow()
+ .closure_tys
+ .get(&def_id)
+ .unwrap()
+ .subst(self.tcx, substs);
+
+ if self.normalize {
+ normalize_associated_type(&self.tcx, &closure_ty)
+ } else {
+ closure_ty
+ }
+ }
+
+ pub fn closure_upvars(&self,
+ def_id: ast::DefId,
+ substs: &Substs<'tcx>)
+ -> Option<Vec<ty::ClosureUpvar<'tcx>>>
+ {
+ let result = ty::ctxt::closure_upvars(self, def_id, substs);
+
+ if self.normalize {
+ normalize_associated_type(&self.tcx, &result)
+ } else {
+ result
+ }
+ }
}
impl<'tcx> TypeTrace<'tcx> {
use self::VarKind::*;
use middle::def::*;
-use middle::mem_categorization::Typer;
use middle::pat_util;
use middle::region;
use middle::ty;
-use middle::ty::ClosureTyper;
use lint;
use util::nodemap::NodeMap;
use self::Aliasability::*;
use ast_map;
+use middle::infer;
use middle::check_const;
use middle::def;
use middle::region;
use middle::ty::{self, Ty};
-use util::nodemap::NodeMap;
use syntax::ast::{MutImmutable, MutMutable};
use syntax::ast;
use syntax::codemap::Span;
-use std::cell::Ref;
use std::fmt;
use std::rc::Rc;
fn span(&self) -> Span { self.span }
}
-pub struct MemCategorizationContext<'t,TYPER:'t> {
- typer: &'t TYPER
-}
-
-impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
-impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> {
- fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self }
+#[derive(Copy, Clone)]
+pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
+ pub typer: &'t infer::InferCtxt<'a, 'tcx>,
}
pub type McResult<T> = Result<T, ()>;
-/// The `Typer` trait provides the interface for the mem-categorization
-/// module to the results of the type check. It can be used to query
-/// the type assigned to an expression node, to inquire after adjustments,
-/// and so on.
-///
-/// This interface is needed because mem-categorization is used from
-/// two places: `regionck` and `borrowck`. `regionck` executes before
-/// type inference is complete, and hence derives types and so on from
-/// intermediate tables. This also implies that type errors can occur,
-/// and hence `node_ty()` and friends return a `Result` type -- any
-/// error will propagate back up through the mem-categorization
-/// routines.
-///
-/// In the borrow checker, in contrast, type checking is complete and we
-/// know that no errors have occurred, so we simply consult the tcx and we
-/// can be sure that only `Ok` results will occur.
-pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool;
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>;
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>>;
- fn is_method_call(&self, id: ast::NodeId) -> bool;
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture>;
-}
-
impl MutabilityCategory {
pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
let ret = match m {
}
}
-impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
- pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
+impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
+ pub fn new(typer: &'t infer::InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> {
MemCategorizationContext { typer: typer }
}
- fn tcx(&self) -> &'t ty::ctxt<'tcx> {
- self.typer.tcx()
+ fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+ self.typer.tcx
}
fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
}
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()>
- where F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+ where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
{
self.cat_pattern_(cmt, pat, &mut op)
}
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
-> McResult<()>
- where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+ where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
{
// Here, `cmt` is the categorization for the value being
// matched and pat is the pattern it is being matched against.
impl1_def_id,
impl2_def_id);
- let param_env = &infcx.tcx.empty_parameter_environment();
- let selcx = &mut SelectionContext::intercrate(infcx, param_env);
+ let selcx = &mut SelectionContext::intercrate(infcx);
infcx.probe(|_| {
overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
})
// particular node-id).
region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
- errors_will_be_reported: bool,
+ pub errors_will_be_reported: bool,
}
#[derive(Clone)]
/// `projection_ty` again.
pub fn normalize_projection_type<'a>(&mut self,
infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>)
-> Ty<'tcx>
// FIXME(#20304) -- cache
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
for obligation in normalized.obligations {
}
pub fn select_all_or_error<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- try!(self.select_where_possible(infcx, typer));
+ try!(self.select_where_possible(infcx));
// Anything left is ambiguous.
let errors: Vec<FulfillmentError> =
/// gaining type information. It'd be equally valid to use `select_where_possible` but it
/// results in `O(n^2)` performance (#18208).
pub fn select_new_obligations<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
self.select(&mut selcx, true)
}
pub fn select_where_possible<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
self.select(&mut selcx, false)
}
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>,
ty: Ty<'tcx>,
bound: ty::BuiltinBound,
span: Span)
// Note: we only assume something is `Copy` if we can
// *definitively* show that it implements `Copy`. Otherwise,
// assume it is move; linear is always ok.
- match fulfill_cx.select_all_or_error(infcx, typer) {
+ match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => {
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
ty,
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
- let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause,
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), false);
+ let predicates = match fully_normalize(&infcx, cause,
&infcx.parameter_environment.caller_bounds) {
Ok(predicates) => predicates,
Err(errors) => {
}
pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
- closure_typer: &ty::ClosureTyper<'tcx>,
cause: ObligationCause<'tcx>,
value: &T)
-> Result<T, Vec<FulfillmentError<'tcx>>>
{
debug!("normalize_param_env(value={:?})", value);
- let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
+ let mut selcx = &mut SelectionContext::new(infcx);
+ // FIXME (@jroesch) ISSUE 26721
+ // I'm not sure if this is a bug or not, needs further investigation.
+ // It appears that by reusing the fulfillment_cx here we incur more
+ // obligations and later trip an asssertion on regionck.rs line 337.
+ //
+ // The two possibilities I see is:
+ // - normalization is not actually fully happening and we
+ // have a bug else where
+ // - we are adding a duplicate bound into the list causing
+ // its size to change.
+ //
+ // I think we should probably land this refactor and then come
+ // back to this is a follow-up patch.
let mut fulfill_cx = FulfillmentContext::new(false);
+
let Normalized { value: normalized_value, obligations } =
project::normalize(selcx, cause, value);
debug!("normalize_param_env: normalized_value={:?} obligations={:?}",
for obligation in obligations {
fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
}
- try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
+
+ try!(fulfill_cx.select_all_or_error(infcx));
let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
debug!("normalize_param_env: resolved_value={:?}", resolved_value);
Ok(resolved_value)
pub struct SelectionContext<'cx, 'tcx:'cx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx (ty::ClosureTyper<'tcx>+'cx),
-
/// Freshener used specifically for skolemizing entries on the
/// obligation stack. This ensures that all entries on the stack
/// at one time will have the same set of skolemized entries,
}
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx ty::ClosureTyper<'tcx>)
+ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>)
-> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
- closure_typer: closure_typer,
freshener: infcx.freshener(),
intercrate: false,
}
}
- pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx ty::ClosureTyper<'tcx>)
+ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>)
-> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
- closure_typer: closure_typer,
freshener: infcx.freshener(),
intercrate: true,
}
}
pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'cx, 'tcx> {
- self.closure_typer.param_env()
+ self.infcx.param_env()
}
- pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) {
- self.closure_typer
+ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+ self.infcx
}
///////////////////////////////////////////////////////////////////////////
kind,
obligation);
- match self.closure_typer.closure_kind(closure_def_id) {
+ match self.infcx.closure_kind(closure_def_id) {
Some(closure_kind) => {
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
if closure_kind.extends(kind) {
return ok_if(Vec::new());
}
- match self.closure_typer.closure_upvars(def_id, substs) {
+ match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()),
None => {
debug!("assemble_builtin_bound_candidates: no upvar types available yet");
ty::TyClosure(def_id, substs) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
- match self.closure_typer.closure_upvars(def_id, substs) {
+ match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => {
Some(upvars.iter().map(|c| c.ty).collect())
}
substs: &Substs<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
- let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
+ let closure_type = self.infcx.closure_type(closure_def_id, substs);
let ty::Binder((trait_ref, _)) =
util::closure_trait_ref_and_return_type(self.tcx(),
obligation.predicate.def_id(),
use middle::fast_reject;
use middle::free_region::FreeRegionMap;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::region;
use middle::resolve_lifetime;
use middle::infer;
-> Result<(),CopyImplementationError> {
let tcx = self.tcx;
+ // FIXME: (@jroesch) float this code up
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false);
+
let did = match self_type.sty {
ty::TyStruct(struct_did, substs) => {
let fields = tcx.struct_fields(struct_did, substs);
for field in &fields {
- if self.type_moves_by_default(field.mt.ty, span) {
+ if infcx.type_moves_by_default(field.mt.ty, span) {
return Err(FieldDoesNotImplementCopy(field.name))
}
}
for variant_arg_type in &variant.args {
let substd_arg_type =
variant_arg_type.subst(tcx, substs);
- if self.type_moves_by_default(substd_arg_type, span) {
+ if infcx.type_moves_by_default(substd_arg_type, span) {
return Err(VariantDoesNotImplementCopy(variant.name))
}
}
}
}
-pub trait ClosureTyper<'tcx> {
- fn tcx(&self) -> &ctxt<'tcx> {
- self.param_env().tcx
- }
-
- fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>;
-
- /// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck,
- /// returns `None` if the kind of this closure has not yet been
- /// inferred.
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>;
-
- /// Returns the argument/return types of this closure.
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>;
-
- /// Returns the set of all upvars and their transformed
- /// types. During typeck, maybe return `None` if the upvar types
- /// have not yet been inferred.
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ClosureUpvar<'tcx>>>;
-}
-
impl<'tcx> CommonTypes<'tcx> {
fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
- interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
+ interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
-> CommonTypes<'tcx>
{
- let mut mk = |sty| ctxt::intern_ty(arena, interner, sty);
+ let mk = |sty| ctxt::intern_ty(arena, interner, sty);
CommonTypes {
bool: mk(TyBool),
char: mk(TyChar),
f: F) -> (Session, R)
where F: FnOnce(&ctxt<'tcx>) -> R
{
- let mut interner = FnvHashMap();
- let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+ let interner = RefCell::new(FnvHashMap());
+ let common_types = CommonTypes::new(&arenas.type_, &interner);
tls::enter(ctxt {
arenas: arenas,
- interner: RefCell::new(interner),
+ interner: interner,
substs_interner: RefCell::new(FnvHashMap()),
bare_fn_interner: RefCell::new(FnvHashMap()),
region_interner: RefCell::new(FnvHashMap()),
}
fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
- interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+ interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
st: TypeVariants<'tcx>)
-> Ty<'tcx> {
- match interner.get(&st) {
- Some(ty) => return *ty,
- _ => ()
- }
+ let ty: Ty /* don't be &mut TyS */ = {
+ let mut interner = interner.borrow_mut();
+ match interner.get(&st) {
+ Some(ty) => return *ty,
+ _ => ()
+ }
+
+ let flags = FlagComputation::for_sty(&st);
- let flags = FlagComputation::for_sty(&st);
+ let ty = match () {
+ () => type_arena.alloc(TyS { sty: st,
+ flags: Cell::new(flags.flags),
+ region_depth: flags.depth, }),
+ };
- let ty = match () {
- () => type_arena.alloc(TyS { sty: st,
- flags: Cell::new(flags.flags),
- region_depth: flags.depth, }),
+ interner.insert(InternedTy { ty: ty }, ty);
+ ty
};
debug!("Interned type: {:?} Pointer: {:?}",
ty, ty as *const TyS);
-
- interner.insert(InternedTy { ty: ty }, ty);
-
ty
}
// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for Ty above).
pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
- let mut interner = self.interner.borrow_mut();
- ctxt::intern_ty(&self.arenas.type_, &mut *interner, st)
+ ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
}
pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
TyClosure(did, substs) => {
// FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
let param_env = cx.empty_parameter_environment();
- let upvars = param_env.closure_upvars(did, substs).unwrap();
+ let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
+ let upvars = infcx.closure_upvars(did, substs).unwrap();
TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
}
span: Span)
-> bool
{
- let tcx = param_env.tcx();
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()));
+ let tcx = param_env.tcx;
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false);
- let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env,
+ let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
self, bound, span);
debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
is_impld
}
- fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+ // FIXME (@jroesch): I made this public to use it, not sure if should be private
+ pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
span: Span) -> bool {
if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
.clone()
}
+ // Register a given item type
+ pub fn register_item_type(&self, did: ast::DefId, ty: TypeScheme<'tcx>) {
+ self.tcache.borrow_mut().insert(did, ty);
+ }
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
if id.krate == ast::LOCAL_CRATE {
self.node_id_to_type(id.node)
} else {
- let mut tcache = self.tcache.borrow_mut();
- tcache.entry(id).or_insert_with(|| csearch::get_field_type(self, struct_id, id)).ty
+ memoized(&self.tcache, id,
+ |id| csearch::get_field_type(self, struct_id, id)).ty
}
}
}
// Returns a list of `ClosureUpvar`s for each upvar.
- pub fn closure_upvars(typer: &Typer<'tcx>,
+ pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
closure_id: ast::DefId,
substs: &Substs<'tcx>)
-> Option<Vec<ClosureUpvar<'tcx>>>
// This may change if abstract return types of some sort are
// implemented.
assert!(closure_id.krate == ast::LOCAL_CRATE);
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
match tcx.freevars.borrow().get(&closure_id.node) {
None => Some(vec![]),
Some(ref freevars) => {
}
}
-impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
- Ok(self.tcx.node_id_to_type(id))
- }
-
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
- Ok(self.tcx.expr_ty_adjusted(expr))
- }
-
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
- self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.ty)
- }
-
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.origin.clone())
- }
-
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
-
- Ref::map(self.tcx.tables.borrow(), projection)
- }
-
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tcx.is_method_call(id)
- }
-
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
- self.tcx.region_maps.temporary_scope(rvalue_id)
- }
-
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- self.tcx.upvar_capture(upvar_id)
- }
-
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- ty.moves_by_default(self, span)
- }
-}
-
-impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- self
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- Some(self.tcx.closure_kind(def_id))
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- self.tcx.closure_type(def_id, substs)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ClosureUpvar<'tcx>>> {
- ctxt::closure_upvars(self, def_id, substs)
- }
-}
-
-
/// The category of explicit self.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum ExplicitSelfCategory {
const NANOS_PER_SEC: f64 = 1_000_000_000.0;
let secs = dur.secs() as f64;
let secs = secs + dur.extra_nanos() as f64 / NANOS_PER_SEC;
- println!("{}time: {:.3} \t{}", repeat(" ").take(old).collect::<String>(),
- secs, what);
+
+ let mem_string = match get_resident() {
+ Some(n) => {
+ let mb = n as f64 / 1_000_000.0;
+ format!("; rss: {}MB", mb.round() as usize)
+ }
+ None => "".to_owned(),
+ };
+ println!("{}time: {:.3}{}\t{}", repeat(" ").take(old).collect::<String>(),
+ secs, mem_string, what);
DEPTH.with(|slot| slot.set(old));
rv
}
+// Memory reporting
+fn get_resident() -> Option<usize> {
+ if cfg!(unix) {
+ get_proc_self_statm_field(1)
+ } else {
+ None
+ }
+}
+
+// Like std::macros::try!, but for Option<>.
+macro_rules! option_try(
+ ($e:expr) => (match $e { Some(e) => e, None => return None })
+);
+
+fn get_proc_self_statm_field(field: usize) -> Option<usize> {
+ use std::fs::File;
+ use std::io::Read;
+
+ assert!(cfg!(unix));
+
+ let mut f = option_try!(File::open("/proc/self/statm").ok());
+ let mut contents = String::new();
+ option_try!(f.read_to_string(&mut contents).ok());
+ let s = option_try!(contents.split_whitespace().nth(field));
+ let npages = option_try!(s.parse::<usize>().ok());
+ Some(npages * ::std::env::page_size())
+}
+
pub fn indent<R, F>(op: F) -> R where
R: Debug,
F: FnOnce() -> R,
TyError => write!(f, "[type error]"),
TyParam(ref param_ty) => write!(f, "{}", param_ty),
TyEnum(did, substs) | TyStruct(did, substs) => {
- parameterized(f, substs, did, &[],
- |tcx| tcx.lookup_item_type(did).generics)
+ ty::tls::with(|tcx| {
+ if did.krate == ast::LOCAL_CRATE &&
+ !tcx.tcache.borrow().contains_key(&did) {
+ write!(f, "{}<..>", tcx.item_path_str(did))
+ } else {
+ parameterized(f, substs, did, &[],
+ |tcx| tcx.lookup_item_type(did).generics)
+ }
+ })
}
TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data),
use borrowck::*;
use borrowck::InteriorKind::{InteriorElement, InteriorField};
use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::region;
use rustc::middle::ty;
debug!("check_loans(body id={})", body.id);
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
+ let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
let mut clcx = CheckLoanCtxt {
bccx: bccx,
dfcx_loans: dfcx_loans,
move_data: move_data,
all_loans: all_loans,
- param_env: ¶m_env,
+ param_env: &infcx.parameter_environment
};
{
- let mut euv = euv::ExprUseVisitor::new(&mut clcx, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut clcx, &infcx);
euv.walk_fn(decl, body);
}
}
use borrowck::*;
use borrowck::move_data::MoveData;
use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::region;
use rustc::middle::ty;
};
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
-
+ let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
{
- let mut euv = euv::ExprUseVisitor::new(&mut glcx, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx);
euv.walk_fn(decl, body);
}
impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
fn visit_expr(&mut self, ex: &Expr) {
if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
- let param_env = self.bccx.tcx.empty_parameter_environment();
- let mc = mc::MemCategorizationContext::new(¶m_env);
+ let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None, false);
+ let mc = mc::MemCategorizationContext::new(&infcx);
let base_cmt = mc.cat_expr(&**base).unwrap();
let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
// Check that we don't allow borrows of unsafe static items.
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::mem_categorization as mc;
-use rustc::middle::mem_categorization::Typer;
use rustc::middle::region;
use rustc::middle::ty::{self, Ty};
-> (&'static str, &'static str) {
match ty.sty {
_ => {
- if param_env.type_moves_by_default(ty, span) {
+ if ty.moves_by_default(param_env, span) {
("non-copyable",
"perhaps you meant to use `clone()`?")
} else {
lang_items,
stability::Index::new(krate),
|tcx| {
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
body(Env { infcx: &infcx });
let free_regions = FreeRegionMap::new();
infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
use metadata::{csearch, decoder};
use middle::def::*;
-use middle::mem_categorization::Typer;
use middle::subst::Substs;
use middle::ty::{self, Ty};
use middle::{def, pat_util, stability};
_ => return,
};
let parameter_environment = cx.tcx.empty_parameter_environment();
- if !parameter_environment.type_moves_by_default(ty, item.span) {
+ // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
+ // method
+ if !ty.moves_by_default(¶meter_environment, item.span) {
return;
}
if parameter_environment.can_type_implement_copy(ty, item.span).is_ok() {
#![feature(unicode)]
#![feature(unicode)]
#![feature(vec_push_all)]
-#![feature(cell_extras)]
#![allow(trivial_casts)]
qualname: qualname,
declaration: None,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
})
}
ast::ItemStatic(ref typ, mt, ref expr) => {
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
value: value,
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
value: self.span_utils.snippet(expr.span),
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
filename: filename,
})
},
value: val,
span: sub_span.unwrap(),
qualname: enum_name,
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
})
},
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
let mut type_data = None;
let sub_span;
- let parent = self.tcx.map.get_parent(item.id);
+ let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0);
match typ.node {
// Common case impl for a struct or something basic.
return Some(Data::VariableRefData(VariableRefData {
name: get_ident(ident.node).to_string(),
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
ref_id: f.id,
}));
}
let sub_span = self.span_utils.span_for_last_ident(path.span);
Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
ref_id: def_id,
}))
}
use middle::const_eval;
use middle::def::{self, DefMap};
use middle::expr_use_visitor as euv;
+use middle::infer;
use middle::lang_items::StrEqFnLangItem;
use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::pat_util::*;
use trans::adt;
use trans::base::*;
reassigned: false
};
{
- let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx);
+ let infcx = infer::new_infer_ctxt(bcx.tcx(), &bcx.tcx().tables, None, false);
+ let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx);
visitor.walk_expr(body);
}
rc.reassigned
let trmode;
match bm {
ast::BindByValue(_)
- if !param_env.type_moves_by_default(variable_ty, span) || reassigned =>
+ if !variable_ty.moves_by_default(¶m_env, span) || reassigned =>
{
llmatch = alloca_no_lifetime(bcx,
llvariable_ty.ptr_to(),
use llvm::{ValueRef, True, IntEQ, IntNE};
use back::abi::FAT_PTR_ADDR;
use middle::subst;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::infer;
+use middle::ty::{self, Ty};
use middle::ty::Disr;
use syntax::ast;
use syntax::attr;
Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
}
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
}
// Perhaps one of the upvars of this struct is non-zero
// Let's recurse and find out!
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(tcx);
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
for (j, &ty) in upvar_types.iter().enumerate() {
use libc::{c_uint, c_ulonglong};
use llvm::{self, ValueRef, AttrHelper};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
use session::config::NoDebugInfo;
use syntax::abi;
use syntax::ast;
let (fn_sig, abi, env_ty) = match fn_type.sty {
ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
ty::TyClosure(closure_did, substs) => {
- let typer = common::NormalizingClosureTyper::new(ccx.tcx());
- function_type = typer.closure_type(closure_did, substs);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
(&function_type.sig, abi::RustCall, Some(self_type))
}
use metadata::{csearch, encoder, loader};
use middle::astencode;
use middle::cfg;
+use middle::infer;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
use middle::subst::Substs;
-use middle::ty::{self, Ty, ClosureTyper, HasTypeFlags};
+use middle::ty::{self, Ty, HasTypeFlags};
use rustc::ast_map;
use session::config::{self, NoDebugInfo};
use session::Session;
}
ty::TyClosure(def_id, substs) => {
let repr = adt::represent_type(cx.ccx(), t);
- let typer = common::NormalizingClosureTyper::new(cx.tcx());
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
for (i, upvar) in upvars.iter().enumerate() {
let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
cx = f(cx, llupvar, upvar.ty);
use arena::TypedArena;
use back::link::{self, mangle_internal_name_by_path_and_seq};
use llvm::{ValueRef, get_params};
-use middle::mem_categorization::Typer;
+use middle::infer;
use trans::adt;
use trans::attributes;
use trans::base::*;
use trans::expr;
use trans::monomorphize::{self, MonoId};
use trans::type_of::*;
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
use middle::subst::Substs;
use session::config::FullDebugInfo;
// takes the same set of type arguments as the enclosing fn, and
// this function (`trans_closure`) is invoked at the point
// of the closure expression.
- let typer = NormalizingClosureTyper::new(tcx);
- let function_type = typer.closure_type(closure_id, param_substs);
+
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ let function_type = infcx.closure_type(closure_id, param_substs);
let freevars: Vec<ty::Freevar> =
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
ccx.tn().val_to_string(llreffn));
let tcx = ccx.tcx();
- let typer = NormalizingClosureTyper::new(tcx);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
// Find a version of the closure type. Substitute static for the
// region since it doesn't really matter.
let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
// Make a version with the type of by-ref closure.
- let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
+ let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
abi: abi,
use middle::def;
use middle::infer;
use middle::lang_items::LangItem;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
-use middle::region;
use middle::subst::{self, Substs};
use trans::base;
use trans::build;
use arena::TypedArena;
use libc::{c_uint, c_char};
use std::ffi::CString;
-use std::cell::{Cell, RefCell, Ref};
+use std::cell::{Cell, RefCell};
use std::result::Result as StdResult;
use std::vec::Vec;
use syntax::ast;
// normalized version of the type, and therefore will definitely
// know whether the type implements Copy (and thus needs no
// cleanup/drop/zeroing) ...
- let implements_copy = !param_env.type_moves_by_default(ty, DUMMY_SP);
+ let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP);
if implements_copy { return false; }
}
}
-impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
- Ok(node_id_type(self, id))
- }
-
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
- Ok(expr_ty_adjusted(self, expr))
- }
-
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
- self.tcx()
- .tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| monomorphize_type(self, method.ty))
- }
-
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tcx()
- .tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.origin.clone())
- }
-
- fn adjustments<'a>(&'a self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- // FIXME (@jroesch): this is becuase we currently have a HR inference problem
- // in the snapshot that causes this code not to work.
- fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) ->
- &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
-
- Ref::map(self.tcx().tables.borrow(), project_adjustments)
- }
-
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tcx().tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
- }
-
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
- self.tcx().region_maps.temporary_scope(rvalue_id)
- }
-
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- Some(self.tcx().tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
- }
-
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- self.fcx.param_env.type_moves_by_default(ty, span)
- }
-}
-
-impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
- fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> {
- &self.fcx.param_env
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_kind(def_id)
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_type(def_id, substs)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_upvars(def_id, substs)
- }
-}
-
pub struct Result<'blk, 'tcx: 'blk> {
pub bcx: Block<'blk, 'tcx>,
pub val: ValueRef
trait_ref, trait_ref.def_id());
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+
let obligation =
traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
trait_ref.to_poly_trait_predicate());
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters.
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
let vtable = selection.map(|predicate| {
fulfill_cx.register_predicate_obligation(&infcx, predicate);
});
predicates);
let tcx = ccx.tcx();
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
- let mut fulfill_cx = traits::FulfillmentContext::new(false);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: predicates, obligations } =
traits::normalize(&mut selcx, cause.clone(), &predicates);
drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
}
-// NOTE: here is another use of parameter environment without an InferCtxt,
-// this is obviously related to the typer interface requiring a parameter env.
-// We should pay attention to this when refactoring
-// - @jroesch
-pub struct NormalizingClosureTyper<'a,'tcx:'a> {
- param_env: ty::ParameterEnvironment<'a, 'tcx>
-}
-
-impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> {
- pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> {
- // Parameter environment is used to give details about type parameters,
- // but since we are in trans, everything is fully monomorphized.
- NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() }
- }
-}
-
-impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- &self.param_env
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- self.param_env.closure_kind(def_id)
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let closure_ty = self.param_env.tcx.closure_type(def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let result = self.param_env.closure_upvars(def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &result)
- }
-}
-
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
infcx: &infer::InferCtxt<'a,'tcx>,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
// In principle, we only need to do this so long as `result`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
- let typer = NormalizingClosureTyper::new(infcx.tcx);
- match fulfill_cx.select_all_or_error(infcx, &typer) {
+ match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => { }
Err(errors) => {
return Err(errors);
use trans::expr;
use trans::tvec;
use trans::type_of;
-use middle::mem_categorization::Typer;
use middle::ty::Ty;
use std::fmt;
* affine values (since they must never be duplicated).
*/
- assert!(!bcx.tcx().empty_parameter_environment()
- .type_moves_by_default(self.ty, DUMMY_SP));
+ assert!(!self.ty
+ .moves_by_default(&bcx.tcx().empty_parameter_environment(), DUMMY_SP));
self.shallow_copy_raw(bcx, dst)
}
use trans::common::{C_bytes, CrateContext};
use trans::declare;
use trans::type_::Type;
-use middle::ty::ClosureTyper;
use session::config::NoDebugInfo;
use std::ffi::CString;
use metadata::csearch;
use middle::pat_util;
use middle::subst::{self, Substs};
+use middle::infer;
use rustc::ast_map;
use trans::{type_of, adt, machine, monomorphize};
-use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
+use trans::common::{self, CrateContext, FunctionContext, Block};
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
use trans::type_::Type;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use session::config::{self, FullDebugInfo};
use util::nodemap::FnvHashMap;
use util::common::path2cstr;
}
},
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let closure_ty = typer.closure_type(def_id, substs);
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let closure_ty = infcx.closure_type(def_id, substs);
self.get_unique_type_id_of_closure_type(cx,
closure_ty,
&mut unique_type_id);
subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
}
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let sig = typer.closure_type(def_id, substs).sig;
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let sig = infcx.closure_type(def_id, substs).sig;
subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
}
ty::TyStruct(def_id, substs) => {
use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
use trans;
use trans::monomorphize;
-use middle::ty::{Ty, ClosureTyper};
+use middle::ty::Ty;
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
use llvm::debuginfo::DIScope;
use rustc::ast_map;
use trans::common::CrateContext;
-use middle::ty::ClosureTyper;
use std::ffi::CString;
use std::ptr;
use trans::common::CrateContext;
use middle::subst::{self, Substs};
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use syntax::ast;
use syntax::parse::token;
output.push('>');
}
}
-
//! * Use define_* family of methods when you might be defining the ValueRef.
//! * When in doubt, define.
use llvm::{self, ValueRef};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
use syntax::abi;
use trans::attributes;
use trans::base;
-use trans::common;
use trans::context::CrateContext;
use trans::monomorphize;
use trans::type_::Type;
(&f.sig, f.abi, None)
}
ty::TyClosure(closure_did, substs) => {
- let typer = common::NormalizingClosureTyper::new(ccx.tcx());
- function_type = typer.closure_type(closure_did, substs);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
debug!("declare_rust_fn function_type={:?} self_type={:?}",
use middle::check_const;
use middle::def;
use middle::lang_items::CoerceUnsizedTraitLangItem;
-use middle::mem_categorization::Typer;
use middle::subst::{Substs, VecPerParamSpace};
use middle::traits;
use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
use middle::subst::VecPerParamSpace;
use middle::subst;
use middle::traits;
-use middle::ty::ClosureTyper;
use rustc::ast_map;
use trans::base::*;
use trans::build::*;
}
// FIXME(#20304) -- cache
- // NOTE: @jroesch
- // Here is of an example where we do not use a param_env but use a typer instead.
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let mut selcx = traits::SelectionContext::new(&infcx);
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: result, obligations } =
traits::normalize(&mut selcx, cause, &value);
result,
obligations);
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+
for obligation in obligations {
fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
use middle::infer::InferCtxt;
use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
SelectionContext, ObligationCause};
-use middle::ty::{self, HasTypeFlags};
+use middle::ty::HasTypeFlags;
use middle::ty_fold::TypeFoldable;
use syntax::ast;
use syntax::codemap::Span;
+//FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
- typer: &(ty::ClosureTyper<'tcx>+'a),
fulfillment_cx: &mut FulfillmentContext<'tcx>,
span: Span,
body_id: ast::NodeId,
where T : TypeFoldable<'tcx> + HasTypeFlags
{
debug!("normalize_associated_types_in(value={:?})", value);
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
let cause = ObligationCause::new(span, body_id, MiscObligation);
let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
debug!("normalize_associated_types_in: result={:?} predicates={:?}",
use CrateCtxt;
use middle::infer;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
expected_vid: ty::TyVid)
-> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
{
- let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+ let fulfillment_cx = fcx.inh.infcx.fulfillment_cx.borrow();
// Here `expected_ty` is known to be a type inference variable.
let expected_sig =
};
let source = source.adjust_for_autoref(self.tcx(), reborrow);
- let mut selcx = traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = traits::SelectionContext::new(self.fcx.infcx());
// Use a FIFO queue for this custom fulfillment procedure.
let mut queue = VecDeque::new();
debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
impl_trait_ref);
- let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+ let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
let trait_to_impl_substs = &impl_trait_ref.substs;
debug!("compare_impl_method: trait_bounds={:?}",
infcx.parameter_environment.caller_bounds);
- let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+ let mut selcx = traits::SelectionContext::new(&infcx);
for predicate in impl_pred.fns {
let traits::Normalized { value: predicate, .. } =
impl_sig.subst(tcx, impl_to_skol_substs);
let impl_sig =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_m_span,
impl_m_body_id,
trait_sig.subst(tcx, &trait_to_skol_substs);
let trait_sig =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_m_span,
impl_m_body_id,
// Check that all obligations are satisfied by the implementation's
// version.
- match fulfillment_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+ match fulfillment_cx.select_all_or_error(&infcx) {
Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
Ok(_) => {}
}
debug!("compare_const_impl(impl_trait_ref={:?})",
impl_trait_ref);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
// The below is for the most part highly similar to the procedure
// for methods above. It is simpler in many respects, especially
// There is no "body" here, so just pass dummy id.
let impl_ty =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_c_span,
0,
&impl_ty);
+
debug!("compare_const_impl: impl_ty={:?}",
impl_ty);
let trait_ty =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_c_span,
0,
&trait_ty);
+
debug!("compare_const_impl: trait_ty={:?}",
trait_ty);
ty: named_type } =
tcx.lookup_item_type(self_type_did);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
infcx.commit_if_ok(|snapshot| {
let (named_type_to_skolem, skol_map) =
use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
use check::UnresolvedTypeAction;
-use middle::mem_categorization::Typer;
use middle::subst::{self};
use middle::traits;
use middle::ty::{self, Ty};
poly_trait_ref.to_predicate());
// Now we want to know if this can be matched
- let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+ let mut selcx = traits::SelectionContext::new(fcx.infcx());
if !selcx.evaluate_obligation(&obligation) {
debug!("--> Cannot match obligation");
return None; // Cannot be matched, no such method resolution is possible.
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
- let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, cause, &xform_self_ty);
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
// as it will pollute the fcx's fulfillment context after this probe
// is over.
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
- let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, cause, &xform_self_ty);
match probe.kind {
InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
- let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx.infcx());
+ let selcx = &mut traits::SelectionContext::new(self.infcx());
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
// Check whether the impl imposes obligations we have to worry about.
let obligation = Obligation::misc(span,
fcx.body_id,
poly_trait_ref.to_predicate());
- let mut selcx = SelectionContext::new(infcx, fcx.infcx());
+ let mut selcx = SelectionContext::new(infcx);
if selcx.evaluate_obligation(&obligation) {
span_stored_function();
// one is never copied into the tcx: it is only used by regionck.
fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
- // Tracks trait obligations incurred during this function body.
- fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
-
// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
-> Inherited<'a, 'tcx> {
Inherited {
- infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
+ infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
locals: RefCell::new(NodeMap()),
tables: tables,
fn_sig_map: RefCell::new(NodeMap()),
- fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
}
}
fn normalize_associated_types_in<T>(&self,
- typer: &ty::ClosureTyper<'tcx>,
span: Span,
body_id: ast::NodeId,
value: &T)
-> T
where T : TypeFoldable<'tcx> + HasTypeFlags
{
- let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+ let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
assoc::normalize_associated_types_in(&self.infcx,
- typer,
- &mut *fulfillment_cx, span,
+ &mut fulfillment_cx,
+ span,
body_id,
value)
}
ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id),
&fn_sig);
let fn_sig =
- inh.normalize_associated_types_in(&inh.infcx.parameter_environment,
- body.span,
+ inh.normalize_associated_types_in(body.span,
body.id,
&fn_sig);
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
where T : TypeFoldable<'tcx> + HasTypeFlags
{
- self.inh.normalize_associated_types_in(self.infcx(), span, self.body_id, value)
+ self.inh.normalize_associated_types_in(span, self.body_id, value)
}
fn normalize_associated_type(&self,
let cause = traits::ObligationCause::new(span,
self.body_id,
traits::ObligationCauseCode::MiscObligation);
- self.inh.fulfillment_cx
+ self.inh
+ .infcx
+ .fulfillment_cx
.borrow_mut()
.normalize_projection_type(self.infcx(),
- self.infcx(),
ty::ProjectionTy {
trait_ref: trait_ref,
item_name: item_name,
-> bool
{
traits::type_known_to_meet_builtin_bound(self.infcx(),
- self.param_env(),
ty,
ty::BoundSized,
span)
builtin_bound: ty::BuiltinBound,
cause: traits::ObligationCause<'tcx>)
{
- self.inh.fulfillment_cx.borrow_mut()
+ self.inh.infcx.fulfillment_cx.borrow_mut()
.register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
}
{
debug!("register_predicate({:?})",
obligation);
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
.register_predicate_obligation(self.infcx(), obligation);
}
region: ty::Region,
cause: traits::ObligationCause<'tcx>)
{
- let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
+ let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
fulfillment_cx.register_region_obligation(ty, region, cause);
}
assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
self.select_all_obligations_and_apply_defaults();
- let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
- match fulfillment_cx.select_all_or_error(self.infcx(), self.infcx()) {
+ let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
+ match fulfillment_cx.select_all_or_error(self.infcx()) {
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
}
/// Select as many obligations as we can at present.
fn select_obligations_where_possible(&self) {
match
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
- .select_where_possible(self.infcx(), self.infcx())
+ .select_where_possible(self.infcx())
{
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
/// work.
fn select_new_obligations(&self) {
match
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
- .select_new_obligations(self.infcx(), self.infcx())
+ .select_new_obligations(self.infcx())
{
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
let inh = static_inherited_fields(ccx, &tables);
let rty = ccx.tcx.node_id_to_type(id);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
- let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
+ let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
check_const_with_ty(&fcx, sp, e, declty);
}
use check::dropck;
use check::FnCtxt;
use middle::free_region::FreeRegionMap;
-use middle::infer::InferCtxt;
use middle::implicator;
use middle::mem_categorization as mc;
use middle::region::CodeExtent;
use middle::subst::Substs;
use middle::traits;
-use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall, HasTypeFlags};
+use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags};
use middle::infer::{self, GenericKind};
use middle::pat_util;
// Make a copy of the region obligations vec because we'll need
// to be able to borrow the fulfillment-cx below when projecting.
let region_obligations =
- self.fcx.inh.fulfillment_cx.borrow()
- .region_obligations(node_id)
- .to_vec();
+ self.fcx
+ .inh
+ .infcx
+ .fulfillment_cx
+ .borrow()
+ .region_obligations(node_id)
+ .to_vec();
for r_o in ®ion_obligations {
debug!("visit_region_obligations: r_o={:?}",
// Processing the region obligations should not cause the list to grow further:
assert_eq!(region_obligations.len(),
- self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len());
+ self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
}
/// This method populates the region map's `free_region_map`. It walks over the transformed
debug!("relate_free_regions(t={:?})", ty);
let body_scope = CodeExtent::from_node_id(body_id);
let body_scope = ty::ReScope(body_scope);
- let implications = implicator::implications(self.fcx.infcx(), self.fcx.infcx(), body_id,
+ let implications = implicator::implications(self.fcx.infcx(), body_id,
ty, body_scope, span);
// Record any relations between free regions that we observe into the free-region-map.
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
/// needed.
-fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
- mc: mc::MemCategorizationContext<InferCtxt<'a, 'tcx>>,
+fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
+ mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
discr_cmt: mc::cmt<'tcx>,
root_pat: &ast::Pat) {
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
ty,
region);
- let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx.infcx(), rcx.body_id,
+ let implications = implicator::implications(rcx.fcx.infcx(), rcx.body_id,
ty, region, origin.span());
for implication in implications {
debug!("implication: {:?}", implication);
let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
let predicates = {
- let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+ let selcx = &mut traits::SelectionContext::new(fcx.infcx());
traits::normalize(selcx, cause.clone(), &predicates)
};
for predicate in predicates.value.predicates {
};
debug!("new_polytype={:?}", new_polytype);
- tcx.tcache.borrow_mut().insert(new_did, new_polytype);
+ tcx.register_item_type(new_did, new_polytype);
tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
tcx.impl_or_trait_items
.borrow_mut()
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
source, target);
- let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+ let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true);
let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
}
};
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
// Register an obligation for `A: Trait<B>`.
let cause = traits::ObligationCause::misc(span, impl_did.node);
fulfill_cx.register_predicate_obligation(&infcx, predicate);
// Check that all transitive obligations are satisfied.
- if let Err(errors) = fulfill_cx.select_all_or_error(&infcx,
- &infcx.parameter_environment) {
+ if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
traits::report_fulfillment_errors(&infcx, &errors);
}
pub fn check_coherence(crate_context: &CrateCtxt) {
CoherenceChecker {
crate_context: crate_context,
- inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None),
+ inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true),
inherent_impls: RefCell::new(FnvHashMap()),
}.check(crate_context.tcx.map.krate());
unsafety::check(crate_context.tcx);
impl1_def_id,
impl2_def_id);
- let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
}
ty: result_ty
};
- tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
+ tcx.register_item_type(variant_def_id, variant_scheme.clone());
tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
write_ty_to_tcx(tcx, variant.node.id, result_ty);
}
ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
debug!("method {} (id {}) has type {:?}",
ident, id, fty);
- ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
+ ccx.tcx.register_item_type(def_id, TypeScheme {
generics: ty_method.generics.clone(),
ty: fty
});
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
/* add the field to the tcache */
- ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
- ty::TypeScheme {
- generics: struct_generics.clone(),
- ty: tt
- });
+ ccx.tcx.register_item_type(local_def(v.node.id),
+ ty::TypeScheme {
+ generics: struct_generics.clone(),
+ ty: tt
+ });
ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
struct_predicates.clone());
let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
write_ty_to_tcx(tcx, it.id, selfty);
- tcx.tcache.borrow_mut().insert(local_def(it.id),
- TypeScheme { generics: ty_generics.clone(),
- ty: selfty });
+ tcx.register_item_type(local_def(it.id),
+ TypeScheme { generics: ty_generics.clone(),
+ ty: selfty });
tcx.predicates.borrow_mut().insert(local_def(it.id),
ty_predicates.clone());
if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
let ty = ccx.icx(&ty_predicates)
.to_ty(&ExplicitRscope, &*ty);
- tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
- TypeScheme {
- generics: ty_generics.clone(),
- ty: ty,
- });
+ tcx.register_item_type(local_def(impl_item.id),
+ TypeScheme {
+ generics: ty_generics.clone(),
+ ty: ty,
+ });
convert_associated_const(ccx, ImplContainer(local_def(it.id)),
impl_item.ident, impl_item.id,
impl_item.vis.inherit_from(parent_visibility),
ast::ConstTraitItem(ref ty, ref default) => {
let ty = ccx.icx(&trait_predicates)
.to_ty(&ExplicitRscope, ty);
- tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
- TypeScheme {
- generics: trait_def.generics.clone(),
- ty: ty,
- });
+ tcx.register_item_type(local_def(trait_item.id),
+ TypeScheme {
+ generics: trait_def.generics.clone(),
+ ty: ty,
+ });
convert_associated_const(ccx, TraitContainer(local_def(it.id)),
trait_item.ident, trait_item.id,
ast::Public, ty, default.as_ref().map(|d| &**d));
// Enum-like.
write_ty_to_tcx(tcx, ctor_id, selfty);
- tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
+ tcx.register_item_type(local_def(ctor_id), scheme);
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
} else if struct_def.fields[0].node.kind.is_unnamed() {
// Tuple-like.
let inputs: Vec<_> =
struct_def.fields
.iter()
- .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
- .unwrap()
- .ty)
+ .map(|field| tcx.lookup_item_type(
+ local_def(field.node.id)).ty)
.collect();
let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
&inputs[..],
selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
- tcx.tcache.borrow_mut().insert(local_def(ctor_id),
- TypeScheme {
- generics: scheme.generics,
- ty: ctor_fn_ty
- });
+ tcx.register_item_type(local_def(ctor_id),
+ TypeScheme {
+ generics: scheme.generics,
+ ty: ctor_fn_ty
+ });
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
}
}
base_type,
base_type_free);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
drop(::require_same_types(tcx,
Some(&infcx),
false,
```
"##,
+E0124: r##"
+You declared two fields of a struct with the same name. Erroneous code
+example:
+
+```
+struct Foo {
+ field1: i32,
+ field1: i32 // error: field is already declared
+}
+```
+
+Please verify that the field names have been correctly spelled. Example:
+
+```
+struct Foo {
+ field1: i32,
+ field2: i32 // ok!
+}
+```
+"##,
+
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
E0120,
E0122,
E0123,
- E0124,
E0127,
E0128,
E0129,
{
let result = match maybe_infcx {
None => {
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
}
Some(infcx) => {
/// If the corresponding `Sender` has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return `Err` to
/// indicate that no more messages can ever be received on this channel.
+ /// However, since channels are buffered, messages sent before the disconnect
+ /// will still be properly received.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::sync::mpsc;
+ /// use std::thread;
+ ///
+ /// let (send, recv) = mpsc::channel();
+ /// let handle = thread::spawn(move || {
+ /// send.send(1u8).unwrap();
+ /// });
+ ///
+ /// handle.join().unwrap();
+ ///
+ /// assert_eq!(Ok(1), recv.recv());
+ /// ```
+ ///
+ /// Buffering behavior:
+ ///
+ /// ```
+ /// use std::sync::mpsc;
+ /// use std::thread;
+ /// use std::sync::mpsc::RecvError;
+ ///
+ /// let (send, recv) = mpsc::channel();
+ /// let handle = thread::spawn(move || {
+ /// send.send(1u8).unwrap();
+ /// send.send(2).unwrap();
+ /// send.send(3).unwrap();
+ /// drop(send);
+ /// });
+ ///
+ /// // wait for the thread to join so we ensure the sender is dropped
+ /// handle.join().unwrap();
+ ///
+ /// assert_eq!(Ok(1), recv.recv());
+ /// assert_eq!(Ok(2), recv.recv());
+ /// assert_eq!(Ok(3), recv.recv());
+ /// assert_eq!(Err(RecvError), recv.recv());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn recv(&self) -> Result<T, RecvError> {
loop {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(unused_imports)]
+
+mod foo {
+ use baz::bar;
+ //~^ ERROR import `bar` conflicts with existing submodule
+ mod bar {}
+}
+mod baz { pub mod bar {} }
+
+fn main() {}
// Test a very simple custom DST coercion.
-#![feature(core)]
+#![feature(core, rc_weak)]
use std::cell::RefCell;
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
trait Baz {
fn get(&self) -> i32;
let b: Rc<Baz> = a.clone();
assert_eq!(b.get(), 42);
+ let c: Weak<i32> = a.downgrade();
+ let d: Weak<Baz> = c.clone();
+
let _c = b.clone();
let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
let b: Rc<RefCell<Baz>> = a.clone();
assert_eq!(b.borrow().get(), 42);
+ let c: Weak<RefCell<Baz>> = a.downgrade();
}