use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{
- self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility,
- ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation
+ self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility,
+ ToPolyTraitRef, ToPredicate, RegionKind, UserType
};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use std::slice;
use require_c_abi_if_variadic;
-use session::{CompileIncomplete, config, Session};
+use session::{CompileIncomplete, Session};
+use session::config::EntryFnType;
use TypeAndSubsts;
use lint;
use util::captures::Captures;
};
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(
- &UserTypeAnnotation::Ty(revealed_ty)
+ &UserType::Ty(revealed_ty)
);
debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
ty.hir_id, o_ty, revealed_ty, c_ty);
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
- if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
- if id == fn_id {
- if let config::EntryFnType::Main = entry_type {
- let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
- let trait_ref = ty::TraitRef::new(term_id, substs);
- let return_ty_span = decl.output.span();
- let cause = traits::ObligationCause::new(
- return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
-
- inherited.register_predicate(
- traits::Obligation::new(
- cause, param_env, trait_ref.to_predicate()));
- }
+ if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
+ let main_id = fcx.tcx.hir().as_local_node_id(def_id).unwrap();
+ if main_id == fn_id {
+ let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
+ let trait_ref = ty::TraitRef::new(term_id, substs);
+ let return_ty_span = decl.output.span();
+ let cause = traits::ObligationCause::new(
+ return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
+
+ inherited.register_predicate(
+ traits::Obligation::new(
+ cause, param_env, trait_ref.to_predicate()));
}
}
}
user_self_ty: None, // not relevant here
};
- self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf(
+ self.infcx.canonicalize_user_type_annotation(&UserType::TypeOf(
method.def_id,
user_substs,
))
if !substs.is_noop() {
let canonicalized = self.infcx.canonicalize_user_type_annotation(
- &UserTypeAnnotation::TypeOf(def_id, UserSubsts {
+ &UserType::TypeOf(def_id, UserSubsts {
substs,
user_self_ty,
})
pub fn write_user_type_annotation(
&self,
hir_id: hir::HirId,
- canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>,
+ canonical_user_type_annotation: CanonicalUserType<'tcx>,
) {
debug!(
"write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}",
// types that involve projections, since those can resolve to
// `'static` bounds (modulo #54940, which hopefully will be
// fixed by the time you see this comment, dear reader,
- // although I have my doubts). Other sorts of things are
- // already sufficiently enforced with erased regions. =)
- if ty.has_free_regions() || ty.has_projections() {
- let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty));
+ // although I have my doubts). Also pass in types with inference
+ // types, because they may be repeated. Other sorts of things
+ // are already sufficiently enforced with erased regions. =)
+ if ty.has_free_regions() || ty.has_projections() || ty.has_infer_types() {
+ let c_ty = self.infcx.canonicalize_response(&UserType::Ty(ty));
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
}
opt_ty.unwrap_or_else(
|| tcx.mk_float_var(self.next_float_var_id()))
}
- ast::LitKind::Bool(_) => tcx.types.bool
+ ast::LitKind::Bool(_) => tcx.types.bool,
+ ast::LitKind::Err(_) => tcx.types.err,
}
}
struct_span_err!(self.tcx.sess, expr.span, E0572,
"return statement outside of function body").emit();
} else if let Some(ref e) = *expr_opt {
- *self.ret_coercion_span.borrow_mut() = Some(e.span);
+ if self.ret_coercion_span.borrow().is_none() {
+ *self.ret_coercion_span.borrow_mut() = Some(e.span);
+ }
self.check_return_expr(e);
} else {
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
- *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+ if self.ret_coercion_span.borrow().is_none() {
+ *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+ }
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
coercion.coerce_forced_unit(
} else {
Def::Err
};
- let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span,
- ty, def, segment);
+ let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span,
+ ty, def, segment, true);
// Write back the new resolution.
let hir_id = self.tcx.hir().node_to_hir_id(node_id);
pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
// Don't do all the complex logic below for `DeclItem`.
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- if let hir::DeclKind::Item(_) = decl.node {
- return
- }
- }
- hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
+ hir::StmtKind::Item(..) => return,
+ hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
}
- self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement");
+ self.warn_if_unreachable(stmt.id, stmt.span, "statement");
// Hide the outer diverging and `has_errors` flags.
let old_diverges = self.diverges.get();
self.has_errors.set(false);
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- match decl.node {
- hir::DeclKind::Local(ref l) => {
- self.check_decl_local(&l);
- }
- // Ignore for now.
- hir::DeclKind::Item(_) => ()
- }
+ hir::StmtKind::Local(ref l) => {
+ self.check_decl_local(&l);
}
- hir::StmtKind::Expr(ref expr, _) => {
+ // Ignore for now.
+ hir::StmtKind::Item(_) => {}
+ hir::StmtKind::Expr(ref expr) => {
// Check with expected type of `()`.
self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
}
- hir::StmtKind::Semi(ref expr, _) => {
+ hir::StmtKind::Semi(ref expr) => {
self.check_expr(&expr);
}
}
found: Ty<'tcx>,
cause_span: Span,
blk_id: ast::NodeId,
- ) {
+ ) -> bool {
self.suggest_missing_semicolon(err, expression, expected, cause_span);
+ let mut pointing_at_return_type = false;
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
- self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
+ pointing_at_return_type = self.suggest_missing_return_type(
+ err, &fn_decl, expected, found, can_suggest);
}
self.suggest_ref_or_into(err, expression, expected, found);
+ pointing_at_return_type
}
pub fn suggest_ref_or_into(
/// This routine checks if the return type is left as default, the method is not part of an
/// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
/// type.
- fn suggest_missing_return_type(&self,
- err: &mut DiagnosticBuilder<'tcx>,
- fn_decl: &hir::FnDecl,
- expected: Ty<'tcx>,
- found: Ty<'tcx>,
- can_suggest: bool) {
+ fn suggest_missing_return_type(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ fn_decl: &hir::FnDecl,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ can_suggest: bool,
+ ) -> bool {
// Only suggest changing the return type for methods that
// haven't set a return type at all (and aren't `fn main()` or an impl).
match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
"try adding a return type",
format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
Applicability::MachineApplicable);
+ true
}
(&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
err.span_label(span, "possibly return type missing here?");
+ true
}
(&hir::FunctionRetTy::DefaultReturn(span), _, false, true) => {
// `fn main()` must return `()`, do not suggest changing return type
err.span_label(span, "expected `()` because of default return type");
+ true
}
// expectation was caused by something else, not the default return
- (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => {}
+ (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => false,
(&hir::FunctionRetTy::Return(ref ty), _, _, _) => {
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
if ty.sty == expected.sty {
err.span_label(sp, format!("expected `{}` because of return type",
expected));
+ return true;
}
+ false
}
}
}
None => return None,
};
let last_expr = match last_stmt.node {
- hir::StmtKind::Semi(ref e, _) => e,
+ hir::StmtKind::Semi(ref e) => e,
_ => return None,
};
let last_expr_ty = self.node_ty(last_expr.hir_id);