use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
use rustc::ty::maps::Providers;
use rustc::ty::util::{Representability, IntTypeExt};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
use require_c_abi_if_variadic;
use session::{CompileIncomplete, Session};
use TypeAndSubsts;
use std::ops::{self, Deref};
use syntax::abi::Abi;
use syntax::ast;
+use syntax::attr;
use syntax::codemap::{self, original_sp, Spanned};
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::ptr::P;
pub mod dropck;
pub mod _match;
pub mod writeback;
-pub mod regionck;
+mod regionck;
pub mod coercion;
pub mod demand;
pub mod method;
// associated fresh inference variable. Writeback resolves these
// variables to get the concrete type, which can be used to
// deanonymize TyAnon, after typeck is done with all functions.
- anon_types: RefCell<NodeMap<Ty<'tcx>>>,
+ anon_types: RefCell<DefIdMap<AnonTypeDecl<'tcx>>>,
/// Each type parameter has an implicit region bound that
/// indicates it must outlive at least the function body (the user
body_id: Option<hir::BodyId>,
}
+/// Information about the anonymous, abstract types whose values we
+/// are inferring in this function (these are the `impl Trait` that
+/// appear in the return type).
+#[derive(Debug)]
+struct AnonTypeDecl<'tcx> {
+ /// The substitutions that we apply to the abstract that that this
+ /// `impl Trait` desugars to. e.g., if:
+ ///
+ /// fn foo<'a, 'b, T>() -> impl Trait<'a>
+ ///
+ /// winds up desugared to:
+ ///
+ /// abstract type Foo<'x, T>: Trait<'x>
+ /// fn foo<'a, 'b, T>() -> Foo<'a, T>
+ ///
+ /// then `substs` would be `['a, T]`.
+ substs: &'tcx Substs<'tcx>,
+
+ /// The type variable that represents the value of the abstract type
+ /// that we require. In other words, after we compile this function,
+ /// we will be created a constraint like:
+ ///
+ /// Foo<'a, T> = ?C
+ ///
+ /// where `?C` is the value of this type variable. =) It may
+ /// naturally refer to the type and lifetime parameters in scope
+ /// in this function, though ultimately it should only reference
+ /// those that are arguments to `Foo` in the constraint above. (In
+ /// other words, `?C` should not include `'b`, even though it's a
+ /// lifetime parameter on `foo`.)
+ concrete_ty: Ty<'tcx>,
+
+ /// A list of all required region bounds on the impl Trait type,
+ /// e.g. `'a` and `'b` in `fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b`.
+ required_region_bounds: Vec<ty::Region<'tcx>>,
+}
+
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
type Target = InferCtxt<'a, 'gcx, 'tcx>;
fn deref(&self) -> &Self::Target {
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_generator_interiors: RefCell::new(Vec::new()),
- anon_types: RefCell::new(NodeMap()),
+ anon_types: RefCell::new(DefIdMap()),
implicit_region_bound,
body_id,
}
value: &T) -> T
where T : TypeFoldable<'tcx>
{
- let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, param_env, value);
+ let ok = self.partially_normalize_associated_types_in(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>
- {
- debug!("normalize_associated_types_in(value={:?})", value);
- let mut selcx = traits::SelectionContext::new(self);
- let cause = ObligationCause::misc(span, body_id);
- let traits::Normalized { value, obligations } =
- traits::normalize(&mut selcx, param_env, cause, value);
- debug!("normalize_associated_types_in: result={:?} predicates={:?}",
- value,
- obligations);
- InferOk { value, obligations }
- }
-
/// Replace any late-bound regions bound in `value` with
/// free variants attached to `all_outlive_scope`.
fn liberate_late_bound_regions<T>(&self,
param_env,
&fn_sig);
- check_fn(&inh, param_env, fn_sig, decl, id, body, false).0
+ let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, false).0;
+ // Ensure anon_types have been instantiated prior to entering regionck
+ fcx.instantiate_anon_types(&fn_sig.output());
+ fcx
} else {
let fcx = FnCtxt::new(&inh, param_env, body.value.id);
let expected_type = tcx.type_of(def_id);
hir::ImplItemKind::Method(..) => {
let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id);
if ty_trait_item.kind == ty::AssociatedKind::Method {
- let err_count = tcx.sess.err_count();
compare_impl_method(tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
- trait_span,
- true); // start with old-broken-mode
- if err_count == tcx.sess.err_count() {
- // old broken mode did not report an error. Try with the new mode.
- compare_impl_method(tcx,
- &ty_impl_item,
- impl_item.span,
- &ty_trait_item,
- impl_trait_ref,
- trait_span,
- false); // use the new mode
- }
+ trait_span);
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324,
"item `{}` is an associated method, \
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
- if vs.is_empty() && tcx.has_attr(def_id, "repr") {
- struct_span_err!(
- tcx.sess, sp, E0084,
- "unsupported representation for zero-variant enum")
- .span_label(sp, "unsupported enum representation")
- .emit();
+ if vs.is_empty() {
+ let attributes = tcx.get_attrs(def_id);
+ if let Some(attr) = attr::find_by_name(&attributes, "repr") {
+ struct_span_err!(
+ tcx.sess, attr.span, E0084,
+ "unsupported representation for zero-variant enum")
+ .span_label(sp, "zero-variant enum")
+ .emit();
+ }
}
let repr_type_ty = def.repr.discr_type().to_ty(tcx);
/// Replace all anonymized types with fresh inference variables
/// and record them for writeback.
fn instantiate_anon_types<T: TypeFoldable<'tcx>>(&self, value: &T) -> T {
+ debug!("instantiate_anon_types(value={:?})", value);
value.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| {
if let ty::TyAnon(def_id, substs) = ty.sty {
+ debug!("instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})", def_id, substs);
+
// Use the same type variable if the exact same TyAnon appears more
// than once in the return type (e.g. if it's passed to a type alias).
- let id = self.tcx.hir.as_local_node_id(def_id).unwrap();
- if let Some(ty_var) = self.anon_types.borrow().get(&id) {
- return ty_var;
+ if let Some(anon_defn) = self.anon_types.borrow().get(&def_id) {
+ return anon_defn.concrete_ty;
}
let span = self.tcx.def_span(def_id);
let ty_var = self.next_ty_var(TypeVariableOrigin::TypeInference(span));
- self.anon_types.borrow_mut().insert(id, ty_var);
let predicates_of = self.tcx.predicates_of(def_id);
let bounds = predicates_of.instantiate(self.tcx, substs);
+ debug!("instantiate_anon_types: bounds={:?}", bounds);
+
+ let required_region_bounds =
+ self.tcx.required_region_bounds(ty, bounds.predicates.clone());
+ debug!("instantiate_anon_types: required_region_bounds={:?}",
+ required_region_bounds);
+
+ self.anon_types.borrow_mut().insert(def_id, AnonTypeDecl {
+ substs,
+ concrete_ty: ty_var,
+ required_region_bounds,
+ });
+ debug!("instantiate_anon_types: ty_var={:?}", ty_var);
for predicate in bounds.predicates {
// Change the predicate to refer to the type variable,
let predicate = self.instantiate_anon_types(&predicate);
// Require that the predicate holds for the concrete type.
- let cause = traits::ObligationCause::new(span, self.body_id,
+ let cause = traits::ObligationCause::new(span,
+ self.body_id,
traits::SizedReturnType);
+
+ debug!("instantiate_anon_types: predicate={:?}", predicate);
self.register_predicate(traits::Obligation::new(cause,
self.param_env,
predicate));
-> InferOk<'tcx, T>
where T : TypeFoldable<'tcx>
{
- self.inh.normalize_associated_types_in_as_infer_ok(span,
- self.body_id,
- self.param_env,
- value)
+ self.inh.partially_normalize_associated_types_in(span,
+ self.body_id,
+ self.param_env,
+ value)
}
pub fn require_type_meets(&self,
if expected_count == 1 {""} else {"s"},
arg_count,
if arg_count == 1 {" was"} else {"s were"}),
- error_code);
+ DiagnosticId::Error(error_code.to_owned()));
if let Some(def_s) = def_span {
err.span_label(def_s, "defined here");
hir::QPath::TypeRelative(ref qself, _) => qself.span
};
+ // Prohibit struct expressions when non exhaustive flag is set.
+ if let ty::TyAdt(adt, _) = struct_ty.sty {
+ if !adt.did.is_local() && adt.is_non_exhaustive() {
+ span_err!(self.tcx.sess, expr.span, E0639,
+ "cannot create non-exhaustive {} using struct expression",
+ adt.variant_descr());
+ }
+ }
+
self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
base_expr.is_none());
if let &Some(ref base_expr) = base_expr {
if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
tps_used[idx as usize - generics.lifetimes.len()] = true;
+ } else if let ty::TyError = leaf_ty.sty {
+ // If there already another error, do not emit an error for not using a type Parameter
+ assert!(tcx.sess.err_count() > 0);
+ return;
}
}