//! case but `&a` in the second. Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
-use middle::const_val::ConstVal;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::eval_length;
use hir::{self, SelfKind};
-use hir::def::{self, Def};
+use hir::def::{Def, PathResolution};
use hir::def_id::DefId;
use hir::print as pprust;
use middle::resolve_lifetime as rl;
use rustc::lint;
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
+use rustc::ty::subst::VecPerParamSpace;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds;
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
ElisionFailureInfo, ElidedLifetime};
+use rscope::{AnonTypeScope, MaybeWithAnonTypes};
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FnvHashSet};
-use rustc_const_math::ConstInt;
use std::cell::RefCell;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
None => match rscope.anon_regions(default_span, 1) {
Ok(rs) => rs[0],
Err(params) => {
- let mut err = struct_span_err!(self.tcx().sess, default_span, E0106,
- "missing lifetime specifier");
+ let ampersand_span = Span { hi: default_span.lo, ..default_span};
+
+ let mut err = struct_span_err!(self.tcx().sess, ampersand_span, E0106,
+ "missing lifetime specifier");
+ err.span_label(ampersand_span, &format!("expected lifetime parameter"));
+
if let Some(params) = params {
report_elision_failure(&mut err, params);
}
self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
}
hir::ParenthesizedParameters(..) => {
- span_err!(tcx.sess, span, E0214,
- "parenthesized parameters may only be used with a trait");
+ struct_span_err!(tcx.sess, span, E0214,
+ "parenthesized parameters may only be used with a trait")
+ .span_label(span, &format!("only traits may use parentheses"))
+ .emit();
+
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
(Substs::empty(),
ty_param_defs.iter().map(|_| tcx.types.err).collect(),
fn convert_ty_with_lifetime_elision(&self,
elided_lifetime: ElidedLifetime,
- ty: &hir::Ty)
+ ty: &hir::Ty,
+ anon_scope: Option<AnonTypeScope>)
-> Ty<'tcx>
{
match elided_lifetime {
Ok(implied_output_region) => {
let rb = ElidableRscope::new(implied_output_region);
- self.ast_ty_to_ty(&rb, ty)
+ self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
}
Err(param_lifetimes) => {
// All regions must be explicitly specified in the output
// if the lifetime elision rules do not apply. This saves
// the user from potentially-confusing errors.
let rb = UnelidableRscope::new(param_lifetimes);
- self.ast_ty_to_ty(&rb, ty)
+ self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
}
}
}
let region_substs =
self.create_region_substs(rscope, span, decl_generics, Vec::new());
- let binding_rscope = BindingRscope::new();
+ let anon_scope = rscope.anon_type_scope();
+ let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
let inputs =
data.inputs.iter()
.map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
let (output, output_span) = match data.output {
Some(ref output_ty) => {
- (self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
+ (self.convert_ty_with_lifetime_elision(implied_output_region,
+ &output_ty,
+ anon_scope),
output_ty.span)
}
None => {
Ok((trait_ref, projection_bounds))
}
_ => {
- span_err!(self.tcx().sess, ty.span, E0172,
- "expected a reference to a trait");
+ struct_span_err!(self.tcx().sess, ty.span, E0172,
+ "expected a reference to a trait")
+ .span_label(ty.span, &format!("expected a trait"))
+ .emit();
Err(ErrorReported)
}
}
"expected a path on the left-hand side \
of `+`, not `{}`",
pprust::ty_to_string(ty));
+ err.span_label(ty.span, &format!("expected a path"));
let hi = bounds.iter().map(|x| match *x {
hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
hir::RegionTyParamBound(ref r) => r.span.hi,
}
for (trait_def_id, name) in associated_types {
- span_err!(tcx.sess, span, E0191,
+ struct_span_err!(tcx.sess, span, E0191,
"the value of the associated type `{}` (from the trait `{}`) must be specified",
name,
- tcx.item_path_str(trait_def_id));
+ tcx.item_path_str(trait_def_id))
+ .span_label(span, &format!(
+ "missing associated type `{}` value", name))
+ .emit();
}
tcx.mk_trait(object.principal, object.bounds)
type_str: &str,
trait_str: &str,
name: &str) {
- span_err!(self.tcx().sess, span, E0223,
- "ambiguous associated type; specify the type using the syntax \
- `<{} as {}>::{}`",
- type_str, trait_str, name);
+ struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type")
+ .span_label(span, &format!("ambiguous associated type"))
+ .note(&format!("specify the type using the syntax `<{} as {}>::{}`",
+ type_str, trait_str, name))
+ .emit();
+
}
// Search for a bound on a type parameter which includes the associated item
}
if bounds.len() > 1 {
- let mut err = struct_span_err!(self.tcx().sess, span, E0221,
- "ambiguous associated type `{}` in bounds of `{}`",
- assoc_name,
- ty_param_name);
+ let mut err = struct_span_err!(
+ self.tcx().sess, span, E0221,
+ "ambiguous associated type `{}` in bounds of `{}`",
+ assoc_name,
+ ty_param_name);
+ err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));
for bound in &bounds {
span_note!(&mut err, span,
// item is declared.
let bound = match (&ty.sty, ty_path_def) {
(_, Def::SelfTy(Some(trait_did), Some(impl_id))) => {
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
// `Self` in an impl of a trait - we have a concrete self type and a
// trait reference.
let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
};
if self.ensure_super_predicates(span, trait_did).is_err() {
- return (tcx.types.err, ty_path_def);
+ return (tcx.types.err, Def::Err);
}
let candidates: Vec<ty::PolyTraitRef> =
&assoc_name.as_str(),
span) {
Ok(bound) => bound,
- Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+ Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
assoc_name,
span) {
Ok(bound) => bound,
- Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+ Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
assoc_name,
span) {
Ok(bound) => bound,
- Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+ Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
_ => {
&ty.to_string(),
"Trait",
&assoc_name.as_str());
- return (tcx.types.err, ty_path_def);
+ return (tcx.types.err, Def::Err);
}
};
}
Def::SelfTy(_, Some(impl_id)) => {
// Self in impl (we know the concrete type).
+
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
tcx.prohibit_type_params(base_segments);
let ty = tcx.node_id_to_type(impl_id);
if let Some(free_substs) = self.get_free_substs() {
return self.tcx().types.err;
}
_ => {
- span_err!(tcx.sess, span, E0248,
- "found value `{}` used as a type",
- tcx.item_path_str(def.def_id()));
+ struct_span_err!(tcx.sess, span, E0248,
+ "found value `{}` used as a type",
+ tcx.item_path_str(def.def_id()))
+ .span_label(span, &format!("value used as a type"))
+ .emit();
return self.tcx().types.err;
}
}
}
- // Note that both base_segments and assoc_segments may be empty, although not at
- // the same time.
+ // Resolve possibly associated type path into a type and final definition.
+ // Note that both base_segments and assoc_segments may be empty, although not at same time.
pub fn finish_resolving_def_to_ty(&self,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
- mut def: Def,
+ base_def: Def,
opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment],
assoc_segments: &[hir::PathSegment])
-> (Ty<'tcx>, Def) {
- debug!("finish_resolving_def_to_ty(def={:?}, \
+ // Convert the base type.
+ debug!("finish_resolving_def_to_ty(base_def={:?}, \
base_segments={:?}, \
assoc_segments={:?})",
- def,
+ base_def,
base_segments,
assoc_segments);
- let mut ty = self.base_def_to_ty(rscope,
- span,
- param_mode,
- def,
- opt_self_ty,
- base_path_ref_id,
- base_segments);
- debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", ty);
+ let base_ty = self.base_def_to_ty(rscope,
+ span,
+ param_mode,
+ base_def,
+ opt_self_ty,
+ base_path_ref_id,
+ base_segments);
+ debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
+
// If any associated type segments remain, attempt to resolve them.
+ let (mut ty, mut def) = (base_ty, base_def);
for segment in assoc_segments {
debug!("finish_resolving_def_to_ty: segment={:?}", segment);
- if ty.sty == ty::TyError {
+ // This is pretty bad (it will fail except for T::A and Self::A).
+ let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
+ ty = new_ty;
+ def = new_def;
+
+ if def == Def::Err {
break;
}
- // This is pretty bad (it will fail except for T::A and Self::A).
- let (a_ty, a_def) = self.associated_path_def_to_ty(span,
- ty,
- def,
- segment);
- ty = a_ty;
- def = a_def;
}
(ty, def)
}
let t = self.ast_ty_to_ty(rscope1, &mt.ty);
tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
}
+ hir::TyNever => {
+ tcx.types.never
+ },
hir::TyTup(ref fields) => {
let flds = fields.iter()
.map(|t| self.ast_ty_to_ty(rscope, &t))
}
hir::TyBareFn(ref bf) => {
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
- let bare_fn_ty = self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl);
+ let anon_scope = rscope.anon_type_scope();
+ let (bare_fn_ty, _) =
+ self.ty_of_method_or_bare_fn(bf.unsafety,
+ bf.abi,
+ None,
+ &bf.decl,
+ anon_scope,
+ anon_scope);
// Find any late-bound regions declared in return type that do
// not appear in the arguments. These are not wellformed.
hir::TyPolyTraitRef(ref bounds) => {
self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
}
+ hir::TyImplTrait(ref bounds) => {
+ use collect::{compute_bounds, SizedByDefault};
+
+ // Create the anonymized type.
+ let def_id = tcx.map.local_def_id(ast_ty.id);
+ if let Some(anon_scope) = rscope.anon_type_scope() {
+ let substs = anon_scope.fresh_substs(tcx);
+ let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
+
+ // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
+ let bounds = compute_bounds(self, ty, bounds,
+ SizedByDefault::Yes,
+ Some(anon_scope),
+ ast_ty.span);
+ let predicates = bounds.predicates(tcx, ty);
+ let predicates = tcx.lift_to_global(&predicates).unwrap();
+ tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates {
+ predicates: VecPerParamSpace::new(vec![], vec![], predicates)
+ });
+
+ ty
+ } else {
+ span_err!(tcx.sess, ast_ty.span, E0562,
+ "`impl Trait` not allowed outside of function \
+ and inherent method return types");
+ tcx.types.err
+ }
+ }
hir::TyPath(ref maybe_qself, ref path) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
let path_res = tcx.expect_resolution(ast_ty.id);
- let def = path_res.base_def;
let base_ty_end = path.segments.len() - path_res.depth;
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
self.ast_ty_to_ty(rscope, &qself.ty)
});
- let (ty, _def) = self.finish_resolving_def_to_ty(rscope,
- ast_ty.span,
- PathParamMode::Explicit,
- def,
- opt_self_ty,
- ast_ty.id,
- &path.segments[..base_ty_end],
- &path.segments[base_ty_end..]);
-
- if path_res.depth != 0 && ty.sty != ty::TyError {
- // Write back the new resolution.
- tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution::new(def));
+ let (ty, def) = self.finish_resolving_def_to_ty(rscope,
+ ast_ty.span,
+ PathParamMode::Explicit,
+ path_res.base_def,
+ opt_self_ty,
+ ast_ty.id,
+ &path.segments[..base_ty_end],
+ &path.segments[base_ty_end..]);
+
+ // Write back the new resolution.
+ if path_res.depth != 0 {
+ tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
}
ty
}
hir::TyFixedLengthVec(ref ty, ref e) => {
- let hint = UncheckedExprHint(tcx.types.usize);
- match eval_const_expr_partial(tcx.global_tcx(), &e, hint, None) {
- Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
- let i = i.as_u64(tcx.sess.target.uint_type);
- assert_eq!(i as usize as u64, i);
- tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), i as usize)
- },
- Ok(val) => {
- span_err!(tcx.sess, ast_ty.span, E0249,
- "expected usize value for array length, got {}",
- val.description());
- self.tcx().types.err
- },
- // array length errors happen before the global constant check
- // so we need to report the real error
- Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
- Err(r) => {
- let mut err = struct_span_err!(tcx.sess, r.span, E0250,
- "array length constant \
- evaluation error: {}",
- r.description());
- if !ast_ty.span.contains(r.span) {
- span_note!(&mut err, ast_ty.span, "for array length here")
- }
- err.emit();
- self.tcx().types.err
- }
+ if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+ tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
+ } else {
+ self.tcx().types.err
}
}
hir::TyTypeof(ref _e) => {
pub fn ty_of_method(&self,
sig: &hir::MethodSig,
- untransformed_self_ty: Ty<'tcx>)
+ untransformed_self_ty: Ty<'tcx>,
+ anon_scope: Option<AnonTypeScope>)
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
- let (bare_fn_ty, optional_explicit_self_category) =
- self.ty_of_method_or_bare_fn(sig.unsafety,
- sig.abi,
- Some(untransformed_self_ty),
- &sig.decl);
- (bare_fn_ty, optional_explicit_self_category)
+ self.ty_of_method_or_bare_fn(sig.unsafety,
+ sig.abi,
+ Some(untransformed_self_ty),
+ &sig.decl,
+ None,
+ anon_scope)
}
pub fn ty_of_bare_fn(&self,
unsafety: hir::Unsafety,
abi: abi::Abi,
- decl: &hir::FnDecl)
+ decl: &hir::FnDecl,
+ anon_scope: Option<AnonTypeScope>)
-> &'tcx ty::BareFnTy<'tcx> {
- self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0
+ self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
}
- fn ty_of_method_or_bare_fn<'a>(&self,
- unsafety: hir::Unsafety,
- abi: abi::Abi,
- opt_untransformed_self_ty: Option<Ty<'tcx>>,
- decl: &hir::FnDecl)
- -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
+ fn ty_of_method_or_bare_fn(&self,
+ unsafety: hir::Unsafety,
+ abi: abi::Abi,
+ opt_untransformed_self_ty: Option<Ty<'tcx>>,
+ decl: &hir::FnDecl,
+ arg_anon_scope: Option<AnonTypeScope>,
+ ret_anon_scope: Option<AnonTypeScope>)
+ -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
{
debug!("ty_of_method_or_bare_fn");
// New region names that appear inside of the arguments of the function
// declaration are bound to that function type.
- let rb = rscope::BindingRscope::new();
+ let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
// `implied_output_region` is the region that will be assumed for any
// region parameters in the return type. In accordance with the rules for
let output_ty = match decl.output {
hir::Return(ref output) =>
- ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
- &output)),
- hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
- hir::NoReturn(..) => ty::FnDiverging
+ self.convert_ty_with_lifetime_elision(implied_output_region,
+ &output,
+ ret_anon_scope),
+ hir::DefaultReturn(..) => self.tcx().mk_nil(),
};
(self.tcx().mk_bare_fn(ty::BareFnTy {
_ if is_infer && expected_ret_ty.is_some() =>
expected_ret_ty.unwrap(),
_ if is_infer =>
- ty::FnConverging(self.ty_infer(None, None, None, decl.output.span())),
+ self.ty_infer(None, None, None, decl.output.span()),
hir::Return(ref output) =>
- ty::FnConverging(self.ast_ty_to_ty(&rb, &output)),
+ self.ast_ty_to_ty(&rb, &output),
hir::DefaultReturn(..) => bug!(),
- hir::NoReturn(..) => ty::FnDiverging
};
debug!("ty_of_closure: input_tys={:?}", input_tys);
if !trait_bounds.is_empty() {
let b = &trait_bounds[0];
- span_err!(self.tcx().sess, b.trait_ref.path.span, E0225,
- "only the builtin traits can be used as closure or object bounds");
+ let span = b.trait_ref.path.span;
+ struct_span_err!(self.tcx().sess, span, E0225,
+ "only the builtin traits can be used as closure or object bounds")
+ .span_label(span, &format!("non-builtin trait used as bounds"))
+ .emit();
}
let region_bound =
} else {
"expected"
};
- span_err!(tcx.sess, span, E0243,
- "wrong number of type arguments: {} {}, found {}",
- expected, required, supplied);
+ struct_span_err!(tcx.sess, span, E0243, "wrong number of type arguments")
+ .span_label(
+ span,
+ &format!("{} {} type arguments, found {}", expected, required, supplied)
+ )
+ .emit();
} else if supplied > accepted {
- let expected = if required < accepted {
- "expected at most"
+ let expected = if required == 0 {
+ "expected no".to_string()
+ } else if required < accepted {
+ format!("expected at most {}", accepted)
} else {
- "expected"
+ format!("expected {}", accepted)
};
- span_err!(tcx.sess, span, E0244,
- "wrong number of type arguments: {} {}, found {}",
- expected,
- accepted,
- supplied);
+
+ struct_span_err!(tcx.sess, span, E0244, "wrong number of type arguments")
+ .span_label(
+ span,
+ &format!("{} type arguments, found {}", expected, supplied)
+ )
+ .emit();
}
}
fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) {
- span_err!(tcx.sess, span, E0107,
- "wrong number of lifetime parameters: expected {}, found {}",
- expected, number);
+ let label = if number < expected {
+ if expected == 1 {
+ format!("expected {} lifetime parameter", expected)
+ } else {
+ format!("expected {} lifetime parameters", expected)
+ }
+ } else {
+ let additional = number - expected;
+ if additional == 1 {
+ "unexpected lifetime parameter".to_string()
+ } else {
+ format!("{} unexpected lifetime parameters", additional)
+ }
+ };
+ struct_span_err!(tcx.sess, span, E0107,
+ "wrong number of lifetime parameters: expected {}, found {}",
+ expected, number)
+ .span_label(span, &label)
+ .emit();
}
// A helper struct for conveniently grouping a set of bounds which we pass to