]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #24072 - ebfull:explain_closure_type_err, r=pnkfelix
authorManish Goregaokar <manishsmail@gmail.com>
Sun, 12 Apr 2015 13:16:14 +0000 (18:46 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Sun, 12 Apr 2015 13:16:14 +0000 (18:46 +0530)
Also fixed bug calling .note() instead of .help()

See #24036

1  2 
src/librustc/middle/ty.rs
src/librustc/session/mod.rs
src/librustc_typeck/check/mod.rs

index 952996c90f52e79d82c5ee31ac1c608eee61da0f,76581529a46f0f12156e1610c2ec9e3c5a3c06fa..0a747ba881fd62f00297e9a071f131164fd9f7c4
@@@ -80,7 -80,7 +80,7 @@@ use std::vec::IntoIter
  use collections::enum_set::{EnumSet, CLike};
  use std::collections::{HashMap, HashSet};
  use syntax::abi;
 -use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE};
 +use syntax::ast::{CrateNum, DefId, ItemTrait, LOCAL_CRATE};
  use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
  use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
  use syntax::ast_util::{self, is_local, lit_is_str, local_def};
@@@ -1092,13 -1092,6 +1092,13 @@@ impl<'tcx> FnOutput<'tcx> 
              ty::FnDiverging => unreachable!()
          }
      }
 +
 +    pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> {
 +        match self {
 +            ty::FnConverging(t) => t,
 +            ty::FnDiverging => def
 +        }
 +    }
  }
  
  pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
@@@ -4368,8 -4361,8 +4368,8 @@@ pub fn named_element_ty<'tcx>(cx: &ctxt
              variant_info.arg_names.as_ref()
                  .expect("must have struct enum variant if accessing a named fields")
                  .iter().zip(variant_info.args.iter())
 -                .find(|&(ident, _)| ident.name == n)
 -                .map(|(_ident, arg_t)| arg_t.subst(cx, substs))
 +                .find(|&(&name, _)| name == n)
 +                .map(|(_name, arg_t)| arg_t.subst(cx, substs))
          }
          _ => None
      }
@@@ -5103,7 -5096,7 +5103,7 @@@ pub fn type_err_to_str<'tcx>(cx: &ctxt<
      }
  }
  
- pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
+ pub fn note_and_explain_type_err<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>, sp: Span) {
      match *err {
          terr_regions_does_not_outlive(subregion, superregion) => {
              note_and_explain_region(cx, "", subregion, "...");
                                      "expected concrete lifetime is ",
                                      conc_region, "");
          }
+         terr_sorts(values) => {
+             let expected_str = ty_sort_string(cx, values.expected);
+             let found_str = ty_sort_string(cx, values.found);
+             if expected_str == found_str && expected_str == "closure" {
+                 cx.sess.span_note(sp, &format!("no two closures, even if identical, have the same \
+                                                 type"));
+                 cx.sess.span_help(sp, &format!("consider boxing your closure and/or \
+                                         using it as a trait object"));
+             }
+         }
          _ => {}
      }
  }
@@@ -5348,7 -5351,7 +5358,7 @@@ pub fn ty_to_def_id(ty: Ty) -> Option<a
  #[derive(Clone)]
  pub struct VariantInfo<'tcx> {
      pub args: Vec<Ty<'tcx>>,
 -    pub arg_names: Option<Vec<ast::Ident>>,
 +    pub arg_names: Option<Vec<ast::Name>>,
      pub ctor_ty: Option<Ty<'tcx>>,
      pub name: ast::Name,
      pub id: ast::DefId,
@@@ -5395,7 -5398,7 +5405,7 @@@ impl<'tcx> VariantInfo<'tcx> 
                      .map(|field| node_id_to_type(cx, field.node.id)).collect();
                  let arg_names = fields.iter().map(|field| {
                      match field.node.kind {
 -                        NamedField(ident, _) => ident,
 +                        NamedField(ident, _) => ident.name,
                          UnnamedField(..) => cx.sess.bug(
                              "enum_variants: all fields in struct must have a name")
                      }
index 88faf1cb68ae4db505359543eff52f5c592f25d1,698b681bd55ae2c57b98882ddfde9c8cf92a1ddd..500af5fc772f5ca2d6e18046f8f83ed94f80a560
@@@ -52,7 -52,6 +52,7 @@@ pub struct Session 
      pub working_dir: PathBuf,
      pub lint_store: RefCell<lint::LintStore>,
      pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
 +    pub plugin_llvm_passes: RefCell<Vec<String>>,
      pub crate_types: RefCell<Vec<config::CrateType>>,
      pub crate_metadata: RefCell<Vec<String>>,
      pub features: RefCell<feature_gate::Features>,
@@@ -69,13 -68,13 +69,13 @@@ impl Session 
          if self.opts.treat_err_as_bug {
              self.span_bug(sp, msg);
          }
 -        self.diagnostic().span_fatal(sp, msg)
 +        panic!(self.diagnostic().span_fatal(sp, msg))
      }
      pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
          if self.opts.treat_err_as_bug {
              self.span_bug(sp, msg);
          }
 -        self.diagnostic().span_fatal_with_code(sp, msg, code)
 +        panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
      }
      pub fn fatal(&self, msg: &str) -> ! {
          if self.opts.treat_err_as_bug {
      pub fn span_end_note(&self, sp: Span, msg: &str) {
          self.diagnostic().span_end_note(sp, msg)
      }
 +
 +    /// Prints out a message with a suggested edit of the code.
 +    ///
 +    /// See `diagnostic::RenderSpan::Suggestion` for more information.
 +    pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) {
 +        self.diagnostic().span_suggestion(sp, msg, suggestion)
 +    }
      pub fn span_help(&self, sp: Span, msg: &str) {
          self.diagnostic().span_help(sp, msg)
      }
          self.diagnostic().handler().note(msg)
      }
      pub fn help(&self, msg: &str) {
-         self.diagnostic().handler().note(msg)
+         self.diagnostic().handler().help(msg)
      }
      pub fn opt_span_bug(&self, opt_sp: Option<Span>, msg: &str) -> ! {
          match opt_sp {
@@@ -399,7 -391,6 +399,7 @@@ pub fn build_session_(sopts: config::Op
          working_dir: env::current_dir().unwrap(),
          lint_store: RefCell::new(lint::LintStore::new()),
          lints: RefCell::new(NodeMap()),
 +        plugin_llvm_passes: RefCell::new(Vec::new()),
          crate_types: RefCell::new(Vec::new()),
          crate_metadata: RefCell::new(Vec::new()),
          features: RefCell::new(feature_gate::Features::new()),
index 31039e3abca6eb6729f9c5d2b16fa2b1cdca9bae,ce4eab9988dd4df86b99612394c878ac9b5fc482..862c454a3883360eabacd2cb7af2641c50a58843
@@@ -139,7 -139,6 +139,7 @@@ pub mod demand
  pub mod method;
  mod upvar;
  pub mod wf;
 +mod cast;
  mod closure;
  mod callee;
  mod compare_method;
@@@ -186,7 -185,7 +186,7 @@@ pub struct Inherited<'a, 'tcx: 'a> 
      // back and process them.
      deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
  
 -    deferred_cast_checks: RefCell<Vec<CastCheck<'tcx>>>,
 +    deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
  }
  
  trait DeferredCallResolution<'tcx> {
  
  type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
  
 -/// Reifies a cast check to be checked once we have full type information for
 -/// a function context.
 -struct CastCheck<'tcx> {
 -    expr: ast::Expr,
 -    expr_ty: Ty<'tcx>,
 -    cast_ty: Ty<'tcx>,
 -    span: Span,
 -}
 -
  /// When type-checking an expression, we propagate downward
  /// whatever type hint we are able in the form of an `Expectation`.
  #[derive(Copy, Clone)]
@@@ -1063,6 -1071,141 +1063,6 @@@ fn report_cast_to_unsized_type<'a, 'tcx
  }
  
  
 -fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
 -    fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 -                                          span: Span,
 -                                          t_1: Ty<'tcx>,
 -                                          t_e: Ty<'tcx>) {
 -        fcx.type_error_message(span, |actual| {
 -            format!("illegal cast; cast through an \
 -                    integer first: `{}` as `{}`",
 -                    actual,
 -                    fcx.infcx().ty_to_string(t_1))
 -        }, t_e, None);
 -    }
 -
 -    let span = cast.span;
 -    let e = &cast.expr;
 -    let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
 -    let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
 -
 -    // Check for trivial casts.
 -    if !ty::type_has_ty_infer(t_1) {
 -        if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
 -            if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
 -                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
 -                                        e.id,
 -                                        span,
 -                                        format!("trivial numeric cast: `{}` as `{}`. Cast can be \
 -                                                 replaced by coercion, this might require type \
 -                                                 ascription or a temporary variable",
 -                                                fcx.infcx().ty_to_string(t_e),
 -                                                fcx.infcx().ty_to_string(t_1)));
 -            } else {
 -                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
 -                                        e.id,
 -                                        span,
 -                                        format!("trivial cast: `{}` as `{}`. Cast can be \
 -                                                 replaced by coercion, this might require type \
 -                                                 ascription or a temporary variable",
 -                                                fcx.infcx().ty_to_string(t_e),
 -                                                fcx.infcx().ty_to_string(t_1)));
 -            }
 -            return;
 -        }
 -    }
 -
 -    let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
 -    let t_e_is_scalar = ty::type_is_scalar(t_e);
 -    let t_e_is_integral = ty::type_is_integral(t_e);
 -    let t_e_is_float = ty::type_is_floating_point(t_e);
 -    let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
 -
 -    let t_1_is_scalar = ty::type_is_scalar(t_1);
 -    let t_1_is_char = ty::type_is_char(t_1);
 -    let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
 -    let t_1_is_float = ty::type_is_floating_point(t_1);
 -
 -    // casts to scalars other than `char` and `bare fn` are trivial
 -    let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
 -
 -    if t_e_is_bare_fn_item && t_1_is_bare_fn {
 -        demand::coerce(fcx, e.span, t_1, &e);
 -    } else if t_1_is_char {
 -        let t_e = fcx.infcx().shallow_resolve(t_e);
 -        if t_e.sty != ty::ty_uint(ast::TyU8) {
 -            fcx.type_error_message(span, |actual| {
 -                format!("only `u8` can be cast as `char`, not `{}`", actual)
 -            }, t_e, None);
 -        }
 -    } else if t_1.sty == ty::ty_bool {
 -        span_err!(fcx.tcx().sess, span, E0054,
 -                  "cannot cast as `bool`, compare with zero instead");
 -    } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
 -        t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
 -        // Casts to float must go through an integer or boolean
 -        cast_through_integer_err(fcx, span, t_1, t_e)
 -    } else if t_e_is_c_enum && t_1_is_trivial {
 -        if ty::type_is_unsafe_ptr(t_1) {
 -            // ... and likewise with C enum -> *T
 -            cast_through_integer_err(fcx, span, t_1, t_e)
 -        }
 -        // casts from C-like enums are allowed
 -    } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
 -        fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
 -                                      t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
 -            match t1.sty {
 -                ty::ty_vec(_, Some(_)) => {}
 -                _ => return false
 -            }
 -            if ty::type_needs_infer(t2) {
 -                // This prevents this special case from going off when casting
 -                // to a type that isn't fully specified; e.g. `as *_`. (Issue
 -                // #14893.)
 -                return false
 -            }
 -
 -            let el = ty::sequence_element_type(fcx.tcx(), t1);
 -            infer::mk_eqty(fcx.infcx(),
 -                           false,
 -                           infer::Misc(sp),
 -                           el,
 -                           t2).is_ok()
 -        }
 -
 -        // Due to the limitations of LLVM global constants,
 -        // region pointers end up pointing at copies of
 -        // vector elements instead of the original values.
 -        // To allow unsafe pointers to work correctly, we
 -        // need to special-case obtaining an unsafe pointer
 -        // from a region pointer to a vector.
 -
 -        /* this cast is only allowed from &[T, ..n] to *T or
 -        &T to *T. */
 -        match (&t_e.sty, &t_1.sty) {
 -            (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
 -             &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
 -            if types_compatible(fcx, e.span, mt1, mt2) => {
 -                /* this case is allowed */
 -            }
 -            _ => {
 -                demand::coerce(fcx, e.span, t_1, &e);
 -            }
 -        }
 -    } else if !(t_e_is_scalar && t_1_is_trivial) {
 -        /*
 -        If more type combinations should be supported than are
 -        supported here, then file an enhancement issue and
 -        record the issue number in this comment.
 -        */
 -        fcx.type_error_message(span, |actual| {
 -            format!("non-scalar cast: `{}` as `{}`",
 -                    actual,
 -                    fcx.infcx().ty_to_string(t_1))
 -        }, t_e, None);
 -    }
 -}
 -
  impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
      fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
  
@@@ -1559,13 -1702,6 +1559,13 @@@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> 
                                                   span)
      }
  
 +    pub fn type_is_fat_ptr(&self, ty: Ty<'tcx>, span: Span) -> bool {
 +        if let Some(mt) = ty::deref(ty, true) {
 +            return !self.type_is_known_to_be_sized(mt.ty, span);
 +        }
 +        false
 +    }
 +
      pub fn register_builtin_bound(&self,
                                    ty: Ty<'tcx>,
                                    builtin_bound: ty::BuiltinBound,
      fn check_casts(&self) {
          let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
          for check in deferred_cast_checks.iter() {
 -            check_cast(self, check);
 +            cast::check_cast(self, check);
          }
  
          deferred_cast_checks.clear();
@@@ -3205,17 -3341,11 +3205,17 @@@ fn check_expr_with_unifier<'a, 'tcx, F>
  
            let def = path_res.base_def;
            if path_res.depth == 0 {
 -              let (scheme, predicates) =
 -                  type_scheme_and_predicates_for_def(fcx, expr.span, def);
 -              instantiate_path(fcx, &path.segments,
 -                               scheme, &predicates,
 -                               opt_self_ty, def, expr.span, id);
 +              let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
 +                                                                            expr.span,
 +                                                                            def);
 +              instantiate_path(fcx,
 +                               &path.segments,
 +                               scheme,
 +                               &predicates,
 +                               opt_self_ty,
 +                               def,
 +                               expr.span,
 +                               id);
            } else {
                let ty_segments = path.segments.init();
                let base_ty_end = path.segments.len() - path_res.depth;
  
              // Defer other checks until we're done type checking.
              let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
 -            deferred_cast_checks.push(CastCheck {
 -                expr: (**e).clone(),
 -                expr_ty: t_e,
 -                cast_ty: t_1,
 -                span: expr.span,
 -            });
 +            let cast_check = cast::CastCheck::new((**e).clone(), t_e, t_1, expr.span);
 +            deferred_cast_checks.push(cast_check);
          }
        }
        ast::ExprVec(ref args) => {
                                              .ty_to_string(
                                                  actual_structure_type),
                                           type_error_description);
-                     ty::note_and_explain_type_err(tcx, &type_error);
+                     ty::note_and_explain_type_err(tcx, &type_error, path.span);
                  }
              }
          }
@@@ -5073,12 -5207,6 +5073,12 @@@ pub fn check_intrinsic_type(ccx: &Crate
  
              "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
  
 +            "discriminant_value" => (1, vec![
 +                    ty::mk_imm_rptr(tcx,
 +                                    tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
 +                                                                  ty::BrAnon(0))),
 +                                    param(ccx, 0))], tcx.types.u64),
 +
              ref other => {
                  span_err!(tcx.sess, it.span, E0093,
                      "unrecognized intrinsic function: `{}`", *other);