use syntax::codemap::{self, Span};
use syntax::feature_gate::emit_feature_err;
use syntax::owned_slice::OwnedSlice;
-use syntax::parse::token;
+use syntax::parse::token::{self, InternedString};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::visit::{self, Visitor};
traits::VariableType(p.id));
debug!("Pattern binding {} is assigned to {} with type {:?}",
- token::get_ident(path1.node),
+ path1.node,
self.fcx.infcx().ty_to_string(
self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
var_ty);
}
ast::ItemFn(..) => {} // entirely within check_item_body
ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
- debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
+ debug!("ItemImpl {} with id {}", it.ident, it.id);
match ccx.tcx.impl_trait_ref(local_def(it.id)) {
Some(impl_trait_ref) => {
check_impl_items_against_trait(ccx,
check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
}
ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
- debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
+ debug!("ItemImpl {} with id {}", it.ident, it.id);
let impl_pty = ccx.tcx.lookup_item_type(ast_util::local_def(it.id));
Position::ArgumentNamed(s) if s == "Self" => (),
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match types.iter().find(|t| {
- t.ident.as_str() == s
+ t.ident.name == s
}) {
Some(_) => (),
None => {
span_err!(ccx.tcx.sess, attr.span, E0230,
"there is no type parameter \
{} on trait {}",
- s, item.ident.as_str());
+ s, item.ident);
}
},
// `{:1}` and `{}` are not to be used
// This is checked by resolve
tcx.sess.span_bug(impl_item.span,
&format!("impl-item `{}` is not a member of `{:?}`",
- token::get_name(ty_impl_item.name()),
+ ty_impl_item.name(),
impl_trait_ref));
});
match impl_item.node {
span_err!(tcx.sess, impl_item.span, E0323,
"item `{}` is an associated const, \
which doesn't match its trait `{:?}`",
- token::get_name(impl_const.name),
+ impl_const.name,
impl_trait_ref)
}
}
span_err!(tcx.sess, impl_item.span, E0324,
"item `{}` is an associated method, \
which doesn't match its trait `{:?}`",
- token::get_name(impl_method.name),
+ impl_method.name,
impl_trait_ref)
}
}
span_err!(tcx.sess, impl_item.span, E0325,
"item `{}` is an associated type, \
which doesn't match its trait `{:?}`",
- token::get_name(impl_type.name),
+ impl_type.name,
impl_trait_ref)
}
}
span_err!(tcx.sess, impl_span, E0046,
"not all trait items implemented, missing: `{}`",
missing_items.iter()
- .map(<ast::Name>::as_str)
+ .map(|name| name.to_string())
.collect::<Vec<_>>().join("`, `"))
}
span_err!(tcx.sess, invalidator.span, E0399,
"the following trait items need to be reimplemented \
as `{}` was overridden: `{}`",
- invalidator.ident.as_str(),
+ invalidator.ident,
invalidated_items.iter()
- .map(<ast::Name>::as_str)
+ .map(|name| name.to_string())
.collect::<Vec<_>>().join("`, `"))
}
}
trait_def.associated_type_names.contains(&assoc_name)
}
- fn ty_infer(&self, ty_param_def: Option<ty::TypeParameterDef<'tcx>>, span: Span) -> Ty<'tcx> {
- let default = ty_param_def.and_then(|t|
- t.default.map(|ty| type_variable::Default {
- ty: ty,
+ fn ty_infer(&self,
+ ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
+ substs: Option<&mut subst::Substs<'tcx>>,
+ space: Option<subst::ParamSpace>,
+ span: Span) -> Ty<'tcx> {
+ // Grab the default doing subsitution
+ let default = ty_param_def.and_then(|def| {
+ def.default.map(|ty| type_variable::Default {
+ ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
origin_span: span,
- definition_span: span
- }));
- self.infcx().next_ty_var_with_default(default)
+ def_id: def.default_def_id
+ })
+ });
+
+ let ty_var = self.infcx().next_ty_var_with_default(default);
+
+ // Finally we add the type variable to the substs
+ match substs {
+ None => ty_var,
+ Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
+ }
}
fn projected_ty_from_poly_trait_ref(&self,
}
}
+ /// Apply "fallbacks" to some types
+ /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
+ fn default_type_parameters(&self) {
+ use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
+ for ty in &self.infcx().unsolved_variables() {
+ let resolved = self.infcx().resolve_type_vars_if_possible(ty);
+ if self.infcx().type_var_diverges(resolved) {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
+ } else {
+ match self.infcx().type_is_unconstrained_numeric(resolved) {
+ UnconstrainedInt => {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
+ },
+ UnconstrainedFloat => {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
+ }
+ Neither => { }
+ }
+ }
+ }
+ }
+
fn select_all_obligations_and_apply_defaults(&self) {
+ if self.tcx().sess.features.borrow().default_type_parameter_fallback {
+ self.new_select_all_obligations_and_apply_defaults();
+ } else {
+ self.old_select_all_obligations_and_apply_defaults();
+ }
+ }
+
+ // Implements old type inference fallback algorithm
+ fn old_select_all_obligations_and_apply_defaults(&self) {
+ self.select_obligations_where_possible();
+ self.default_type_parameters();
+ self.select_obligations_where_possible();
+ }
+
+ fn new_select_all_obligations_and_apply_defaults(&self) {
use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
- // For the time being this errs on the side of being memory wasteful but provides better
+ // For the time being this errs on the side of being memory wasteful but provides better
// error reporting.
// let type_variables = self.infcx().type_variables.clone();
// We wrap this in a transaction for error reporting, if we detect a conflict
// we will rollback the inference context to its prior state so we can probe
// for conflicts and correctly report them.
+
+
let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
for ty in &unbound_tyvars {
if self.infcx().type_var_diverges(ty) {
// a unification failure and then report an error for each.
for (conflict, default) in conflicts {
let conflicting_default =
- self.find_conflicting_default(
- &unbound_tyvars,
- &default_map,
- conflict).unwrap_or(type_variable::Default {
+ self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
+ .unwrap_or(type_variable::Default {
ty: self.infcx().next_ty_var(),
origin_span: codemap::DUMMY_SP,
- definition_span: codemap::DUMMY_SP
+ def_id: local_def(0) // what do I put here?
});
+ // This is to ensure that we elimnate any non-determinism from the error
+ // reporting by fixing an order, it doesn't matter what order we choose
+ // just that it is consistent.
+ let (first_default, second_default) =
+ if default.def_id < conflicting_default.def_id {
+ (default, conflicting_default)
+ } else {
+ (conflicting_default, default)
+ };
+
+
self.infcx().report_conflicting_default_types(
- conflicting_default.origin_span,
- conflicting_default,
- default)
+ first_default.origin_span,
+ first_default,
+ second_default)
}
}
}
// We also run this inside snapshot that never commits so we can do error
// reporting for more then one conflict.
- //let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
- for ty in &unbound_tyvars {
- if self.infcx().type_var_diverges(ty) {
- demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
- } else {
- match self.infcx().type_is_unconstrained_numeric(ty) {
- UnconstrainedInt => {
- demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
- },
- UnconstrainedFloat => {
- demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
- },
- Neither => {
- if let Some(default) = default_map.get(ty) {
- let default = default.clone();
- match infer::mk_eqty(self.infcx(), false,
- infer::Misc(default.origin_span),
- ty, default.ty) {
- Ok(()) => {}
- Err(_) => {
- result = Some(default);
- }
+ for ty in &unbound_tyvars {
+ if self.infcx().type_var_diverges(ty) {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
+ } else {
+ match self.infcx().type_is_unconstrained_numeric(ty) {
+ UnconstrainedInt => {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
+ },
+ UnconstrainedFloat => {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
+ },
+ Neither => {
+ if let Some(default) = default_map.get(ty) {
+ let default = default.clone();
+ match infer::mk_eqty(self.infcx(), false,
+ infer::Misc(default.origin_span),
+ ty, default.ty) {
+ Ok(()) => {}
+ Err(_) => {
+ result = Some(default);
}
}
}
}
}
}
- // let result: Result<(), ()> = Err(()); result
- //});
+ }
return result;
}
assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
self.select_all_obligations_and_apply_defaults();
+
let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
match fulfillment_cx.select_all_or_error(self.infcx()) {
Ok(()) => { }
// The special-cased logic below has three functions:
// 1. Provide as good of an expected type as possible.
let expected = expected_arg_tys.get(i).map(|&ty| {
- Expectation::rvalue_hint(ty)
+ Expectation::rvalue_hint(fcx.tcx(), ty)
});
check_expr_with_unifier(fcx, &**arg,
debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
- let tps = fcx.inh.infcx.type_vars_for_defs(span, tps);
- let substs = subst::Substs::new_type(tps, rps);
+ let mut substs = subst::Substs::new(
+ VecPerParamSpace::empty(),
+ VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
+ fcx.inh.infcx.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
TypeAndSubsts { substs: substs, ty: substd_ty }
field.span,
|actual| {
format!("attempted to take value of method `{}` on type \
- `{}`", token::get_ident(field.node), actual)
+ `{}`", field.node, actual)
},
expr_t, None);
format!("attempted access of field `{}` on \
type `{}`, but no field with that \
name was found",
- token::get_ident(field.node),
+ field.node,
actual)
},
expr_t, None);
fn suggest_field_names<'tcx>(id : DefId,
field : &ast::SpannedIdent,
tcx : &ty::ctxt<'tcx>,
- skip : Vec<&str>) {
- let ident = token::get_ident(field.node);
- let name = &ident;
+ skip : Vec<InternedString>) {
+ let name = field.node.name.as_str();
// only find fits with at least one matching letter
let mut best_dist = name.len();
let fields = tcx.lookup_struct_fields(id);
for elem in &fields {
let n = elem.name.as_str();
// ignore already set fields
- if skip.iter().any(|&x| x == n) {
+ if skip.iter().any(|x| *x == n) {
continue;
}
// ignore private fields from non-local crates
if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
continue;
}
- let dist = lev_distance(n, name);
+ let dist = lev_distance(&n, &name);
if dist < best_dist {
best = Some(n);
best_dist = dist;
class_id);
format!("struct variant `{}::{}` has no field named `{}`",
actual, variant_type.name.as_str(),
- token::get_ident(field.ident.node))
+ field.ident.node)
}
None => {
format!("structure `{}` has no field named `{}`",
actual,
- token::get_ident(field.ident.node))
+ field.ident.node)
}
},
struct_ty,
Some((_, true)) => {
span_err!(fcx.tcx().sess, field.ident.span, E0062,
"field `{}` specified more than once",
- token::get_ident(field.ident.node));
+ field.ident.node);
error_happened = true;
}
Some((field_id, false)) => {
let (_, seen) = *class_field_map.get(&name).unwrap();
if !seen {
missing_fields.push(
- format!("`{}`", &token::get_name(name)))
+ format!("`{}`", name))
}
}
match unop {
ast::UnUniq => match ty.sty {
ty::TyBox(ty) => {
- Expectation::rvalue_hint(ty)
+ Expectation::rvalue_hint(tcx, ty)
}
_ => {
NoExpectation
// the last field of a struct can be unsized.
ExpectHasType(mt.ty)
} else {
- Expectation::rvalue_hint(mt.ty)
+ Expectation::rvalue_hint(tcx, mt.ty)
}
}
_ => NoExpectation
let tcx = fcx.tcx();
if !tcx.expr_is_lval(&**lhs) {
span_err!(tcx.sess, expr.span, E0070,
- "illegal left-hand side expression");
+ "invalid left-hand side expression");
}
let lhs_ty = fcx.expr_ty(&**lhs);
/// which still is useful, because it informs integer literals and the like.
/// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
/// for examples of where this comes up,.
- fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
- match ty.sty {
+ fn rvalue_hint(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+ match tcx.struct_tail(ty).sty {
ty::TySlice(_) | ty::TyTrait(..) => {
ExpectRvalueLikeUnsized(ty)
}
// caught by case 1.
match rty.is_representable(tcx, sp) {
ty::SelfRecursive => {
- span_err!(tcx.sess, sp, E0072,
- "illegal recursive {} type; \
- wrap the inner value in a box to make it representable",
- designation);
+ span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
+ tcx.sess.fileline_help(sp, "wrap the inner value in a box to make it representable");
return false
}
ty::Representable | ty::ContainsRecursive => (),
// variables. If the user provided some types, we may still need
// to add defaults. If the user provided *too many* types, that's
// a problem.
- for &space in &ParamSpace::all() {
+ for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
adjust_type_parameters(fcx, span, space, type_defs,
require_type_space, &mut substs);
assert_eq!(substs.types.len(space), type_defs.len(space));
// Nothing specified at all: supply inference variables for
// everything.
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
- substs.types.replace(space, fcx.infcx().type_vars_for_defs(span, &desired[..]));
+ substs.types.replace(space, Vec::new());
+ fcx.infcx().type_vars_for_defs(span, space, substs, &desired[..]);
return;
}
if !*b {
span_err!(ccx.tcx.sess, span, E0091,
"type parameter `{}` is unused",
- token::get_ident(tps[i].ident));
+ tps[i].ident);
}
}
}
}
let tcx = ccx.tcx;
- let name = token::get_ident(it.ident);
+ let name = it.ident.name.as_str();
let (n_tps, inputs, output) = if name.starts_with("atomic_") {
let split : Vec<&str> = name.split('_').collect();
assert!(split.len() >= 2, "Atomic intrinsic not correct format");