use rustc::infer::type_variable::{TypeVariableOrigin};
use rustc::middle::region::CodeExtent;
use rustc::ty::subst::{Kind, Subst, Substs};
-use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
+use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, Ty, TyCtxt, Visibility};
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use syntax::ptr::P;
use syntax::symbol::{Symbol, InternedString, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
-use syntax_pos::{self, BytePos, Span, DUMMY_SP};
+use syntax_pos::{self, BytePos, Span};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
body_id: ast::NodeId,
+ /// The parameter environment used for proving trait obligations
+ /// in this function. This can change when we descend into
+ /// closures (as they bring new things into scope), hence it is
+ /// not part of `Inherited` (as of the time of this writing,
+ /// closures do not yet change the environment, but they will
+ /// eventually).
+ param_env: ty::ParamEnv<'tcx>,
+
// Number of errors that had been reported when we started
// checking this function. On exit, if we find that *more* errors
// have been reported, we will skip regionck and other work that
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
- let param_env = tcx.param_env(def_id);
InheritedBuilder {
- infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
+ infcx: tcx.infer_ctxt(tables),
def_id,
}
}
fn normalize_associated_types_in<T>(&self,
span: Span,
body_id: ast::NodeId,
+ param_env: ty::ParamEnv<'tcx>,
value: &T) -> T
where T : TypeFoldable<'tcx>
{
- let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, value);
+ let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, param_env, value);
self.register_infer_ok_obligations(ok)
}
fn normalize_associated_types_in_as_infer_ok<T>(&self,
span: Span,
body_id: ast::NodeId,
+ param_env: ty::ParamEnv<'tcx>,
value: &T)
-> InferOk<'tcx, T>
where T : TypeFoldable<'tcx>
let mut selcx = traits::SelectionContext::new(self);
let cause = ObligationCause::misc(span, body_id);
let traits::Normalized { value, obligations } =
- traits::normalize(&mut selcx, cause, value);
+ traits::normalize(&mut selcx, param_env, cause, value);
debug!("normalize_associated_types_in: result={:?} predicates={:?}",
value,
obligations);
let body = tcx.hir.body(body_id);
Inherited::build(tcx, def_id).enter(|inh| {
+ let param_env = tcx.param_env(def_id);
let fcx = if let Some(decl) = fn_decl {
let fn_sig = tcx.type_of(def_id).fn_sig();
let fn_sig =
inh.liberate_late_bound_regions(def_id, &fn_sig);
let fn_sig =
- inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
+ inh.normalize_associated_types_in(body.value.span,
+ body_id.node_id,
+ param_env,
+ &fn_sig);
- check_fn(&inh, fn_sig, decl, id, body)
+ check_fn(&inh, param_env, fn_sig, decl, id, body)
} else {
- let fcx = FnCtxt::new(&inh, body.value.id);
+ let fcx = FnCtxt::new(&inh, param_env, body.value.id);
let expected_type = tcx.type_of(def_id);
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
/// * ...
/// * inherited: other fields inherited from the enclosing fn (if any)
fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
fn_sig: ty::FnSig<'tcx>,
decl: &'gcx hir::FnDecl,
fn_id: ast::NodeId,
{
let mut fn_sig = fn_sig.clone();
- debug!("check_fn(sig={:?}, fn_id={})", fn_sig, fn_id);
+ debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
// Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context.
- let mut fcx = FnCtxt::new(inherited, body.value.id);
+ let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
let ret_ty = fn_sig.output();
}
}
- let signature = |item: &ty::AssociatedItem| {
- match item.kind {
- ty::AssociatedKind::Method => {
- format!("{}", tcx.type_of(item.def_id).fn_sig().0)
- }
- ty::AssociatedKind::Type => format!("type {};", item.name.to_string()),
- ty::AssociatedKind::Const => {
- format!("const {}: {:?};", item.name.to_string(), tcx.type_of(item.def_id))
- }
- }
- };
-
if !missing_items.is_empty() {
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
"not all trait items implemented, missing: `{}`",
if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) {
err.span_label(span, format!("`{}` from trait", trait_item.name));
} else {
- err.note(&format!("`{}` from trait: `{}`",
- trait_item.name,
- signature(&trait_item)));
+ err.note_trait_signature(trait_item.name.to_string(),
+ trait_item.signature(&tcx));
}
}
err.emit();
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
body_id: ast::NodeId)
-> FnCtxt<'a, 'gcx, 'tcx> {
FnCtxt {
body_id: body_id,
+ param_env,
err_count_on_creation: inh.tcx.sess.err_count(),
ret_coercion: None,
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
// Require that the predicate holds for the concrete type.
let cause = traits::ObligationCause::new(span, self.body_id,
traits::ReturnType);
- self.register_predicate(traits::Obligation::new(cause, predicate));
+ self.register_predicate(traits::Obligation::new(cause,
+ self.param_env,
+ predicate));
}
ty_var
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
where T : TypeFoldable<'tcx>
{
- let ok = self.normalize_associated_types_in_as_infer_ok(span, value);
- self.register_infer_ok_obligations(ok)
+ self.inh.normalize_associated_types_in(span, self.body_id, self.param_env, value)
}
fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T)
-> InferOk<'tcx, T>
where T : TypeFoldable<'tcx>
{
- self.inh.normalize_associated_types_in_as_infer_ok(span, self.body_id, value)
- }
-
- pub fn write_nil(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, self.tcx.mk_nil());
- }
-
- pub fn write_error(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, self.tcx.types.err);
+ self.inh.normalize_associated_types_in_as_infer_ok(span,
+ self.body_id,
+ self.param_env,
+ value)
}
pub fn require_type_meets(&self,
cause: traits::ObligationCause<'tcx>)
{
self.fulfillment_cx.borrow_mut()
- .register_bound(self, ty, def_id, cause);
+ .register_bound(self, self.param_env, ty, def_id, cause);
}
pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
{
// WF obligations never themselves fail, so no real need to give a detailed cause:
let cause = traits::ObligationCause::new(span, self.body_id, code);
- self.register_predicate(traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
+ self.register_predicate(traits::Obligation::new(cause,
+ self.param_env,
+ ty::Predicate::WellFormed(ty)));
}
pub fn register_old_wf_obligation(&self,
debug!("add_obligations_for_parameters(predicates={:?})",
predicates);
- for obligation in traits::predicates_for_generics(cause, predicates) {
+ for obligation in traits::predicates_for_generics(cause, self.param_env, predicates) {
self.register_predicate(obligation);
}
}
// is polymorphic) and the expected return type.
// No argument expectations are produced if unification fails.
let origin = self.misc(call_span);
- let ures = self.sub_types(false, &origin, formal_ret, ret_ty);
+ let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
// FIXME(#15760) can't use try! here, FromError doesn't default
// to identity so the resulting type is not constrained.
pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
// Don't do all the complex logic below for DeclItem.
match stmt.node {
- hir::StmtDecl(ref decl, id) => {
+ hir::StmtDecl(ref decl, _) => {
match decl.node {
hir::DeclLocal(_) => {}
hir::DeclItem(_) => {
- self.write_nil(id);
return;
}
}
self.diverges.set(Diverges::Maybe);
self.has_errors.set(false);
- let (node_id, _span) = match stmt.node {
- hir::StmtDecl(ref decl, id) => {
- let span = match decl.node {
+ match stmt.node {
+ hir::StmtDecl(ref decl, _) => {
+ match decl.node {
hir::DeclLocal(ref l) => {
self.check_decl_local(&l);
- l.span
- }
- hir::DeclItem(_) => {/* ignore for now */
- DUMMY_SP
}
- };
- (id, span)
+ hir::DeclItem(_) => {/* ignore for now */}
+ }
}
- hir::StmtExpr(ref expr, id) => {
+ hir::StmtExpr(ref expr, _) => {
// Check with expected type of ()
self.check_expr_has_type(&expr, self.tcx.mk_nil());
- (id, expr.span)
}
- hir::StmtSemi(ref expr, id) => {
+ hir::StmtSemi(ref expr, _) => {
self.check_expr(&expr);
- (id, expr.span)
}
- };
-
- if self.has_errors.get() {
- self.write_error(node_id);
- } else {
- self.write_nil(node_id);
}
// Combine the diverging and has_error flags.
hir::StmtSemi(ref e, _) => e,
_ => return,
};
- let last_expr_ty = self.expr_ty(last_expr);
- if self.can_sub_types(last_expr_ty, expected_ty).is_err() {
+ let last_expr_ty = self.node_ty(last_expr.id);
+ if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
return;
}
let original_span = original_sp(last_stmt.span, blk.span);
let ty = self.tcx.type_of(impl_def_id);
let impl_ty = self.instantiate_type_scheme(span, &substs, &ty);
- match self.sub_types(false, &self.misc(span), self_ty, impl_ty) {
+ match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
span_bug!(span,