diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index eeaa4c1661e4e..a95d276f4a8b8 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -251,7 +251,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { bug!("unexpected const {:?}", ct) } - ty::ConstKind::Param(_) | ty::ConstKind::Value(_) | ty::ConstKind::Unevaluated(..) => {} + ty::ConstKind::Param(_) + | ty::ConstKind::Value(_) + | ty::ConstKind::Unevaluated(..) + | ty::ConstKind::Error => {} } ct.super_fold_with(self) diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index b908b75a257e3..bd9d108cfe871 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().consts.err; + return self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: c.ty }); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index a49dc105498ed..0762c0eed9959 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -182,7 +182,7 @@ pub struct CommonLifetimes<'tcx> { } pub struct CommonConsts<'tcx> { - pub err: &'tcx Const<'tcx>, + pub unit: &'tcx Const<'tcx>, } pub struct LocalTableInContext<'a, V> { @@ -858,9 +858,9 @@ impl<'tcx> CommonConsts<'tcx> { let mk_const = |c| interners.const_.intern(c, |c| Interned(interners.arena.alloc(c))).0; CommonConsts { - err: mk_const(ty::Const { + unit: mk_const(ty::Const { val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())), - ty: types.err, + ty: types.unit, }), } } diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index 172f6d4608b1f..a88f362810995 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -70,14 +70,7 @@ impl FlagComputation { | &ty::Str | &ty::Foreign(..) => {} - // You might think that we could just return Error for - // any type containing Error as a component, and get - // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with - // the exception of function types that return bot). - // But doing so caused sporadic memory corruption, and - // neither I (tjc) nor nmatsakis could figure out why, - // so we're doing it this way. - &ty::Error => self.add_flags(TypeFlags::HAS_TY_ERR), + &ty::Error => self.add_flags(TypeFlags::HAS_ERROR), &ty::Param(_) => { self.add_flags(TypeFlags::HAS_TY_PARAM); @@ -239,6 +232,7 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(_) => {} + ty::ConstKind::Error => self.add_flags(TypeFlags::HAS_ERROR), } } diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index d144e507691ce..248dd00ef47be 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -82,7 +82,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) } fn references_error(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_ERR) + self.has_type_flags(TypeFlags::HAS_ERROR) } fn has_param_types_or_consts(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 430ff67d56b68..25d900fbc878c 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -567,8 +567,8 @@ bitflags! { | TypeFlags::HAS_TY_OPAQUE.bits | TypeFlags::HAS_CT_PROJECTION.bits; - /// Is an error type reachable? - const HAS_TY_ERR = 1 << 13; + /// Is an error type/const reachable? + const HAS_ERROR = 1 << 13; /// Does this have any region that "appears free" in the type? /// Basically anything but [ReLateBound] and [ReErased]. diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index a8b7b6a4b97a4..2aa849f89c4f9 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -938,6 +938,7 @@ pub trait PrettyPrinter<'tcx>: self.pretty_print_bound_var(debruijn, bound_var)? } ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), + ty::ConstKind::Error => p!(write("[const error]")), }; Ok(self) } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 4d668e6ee5977..f4f0b6c41b92f 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -510,12 +510,21 @@ pub fn super_relate_consts>( let tcx = relation.tcx(); let eagerly_eval = |x: &'tcx ty::Const<'tcx>| { + // FIXME(eddyb) this doesn't account for lifetime inference variables + // being erased by `eval`, *nor* for the polymorphic aspect of `eval`. + // That is, we could always use `eval` and it will just return the + // old value back if it doesn't succeed. if !x.val.needs_infer() { return x.eval(tcx, relation.param_env()).val; } x.val }; + // FIXME(eddyb) doesn't look like everything below checks that `a.ty == b.ty`. + // We could probably always assert it early, as `const` generic parameters + // are not allowed to depend on other generic parameters, i.e. are concrete. + // (although there could be normalization differences) + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. @@ -524,6 +533,9 @@ pub fn super_relate_consts>( // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } + + (ty::ConstKind::Error, _) | (_, ty::ConstKind::Error) => Ok(ty::ConstKind::Error), + (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => { return Ok(a); } diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 0ac4466d34f5c..1c0ffe12314b3 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -1022,9 +1022,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { ty::ConstKind::Unevaluated(did, substs, promoted) => { ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted) } - ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => { - *self - } + ty::ConstKind::Value(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(..) + | ty::ConstKind::Error => *self, } } @@ -1033,9 +1034,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor), - ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - false - } + ty::ConstKind::Value(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Error => false, } } } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 248a2095d0a2c..644be1607f049 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2429,6 +2429,10 @@ pub enum ConstKind<'tcx> { /// Used to hold computed value. Value(ConstValue<'tcx>), + + /// A placeholder for a const which could not be computed; this is + /// propagated to avoid useless error messages. + Error, } #[cfg(target_arch = "x86_64")] diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index c7a317f39ad71..b6cadd0099656 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -170,7 +170,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) - | ty::ConstKind::Value(_) => {} + | ty::ConstKind::Value(_) + | ty::ConstKind::Error => {} ty::ConstKind::Unevaluated(_, substs, _) => { stack.extend(substs.iter().copied().rev()); diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 893f4c1db7e0a..648c1f5347c15 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -518,6 +518,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Early-return cases. let val_val = match val.val { ty::ConstKind::Param(_) => throw_inval!(TooGeneric), + ty::ConstKind::Error => throw_inval!(TypeckError), ty::ConstKind::Unevaluated(def_id, substs, promoted) => { let instance = self.resolve(def_id, substs)?; // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation. diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 0cb26e082280e..f67b8b87ced5f 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -972,7 +972,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().consts.err + self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 87e5baa57e963..4a8cd9e91e278 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -826,14 +826,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } GenericParamDefKind::Const => { + let ty = tcx.at(span).type_of(param.def_id); // FIXME(const_generics:defaults) if infer_args { // No const parameters were provided, we can infer all. - let ty = tcx.at(span).type_of(param.def_id); self.ct_infer(ty, Some(param), span).into() } else { // We've already errored above about the mismatch. - tcx.consts.err.into() + tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty }).into() } } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index f9100300e3add..990cc84d029a9 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -673,7 +673,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { // FIXME: we'd like to use `self.report_error`, but it doesn't yet // accept a &'tcx ty::Const. self.replaced_with_error = true; - self.tcx().consts.err + self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a327951b3b0dd..7794f62efb71f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -316,13 +316,13 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { fn ct_infer( &self, - _: Ty<'tcx>, + ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { bad_placeholder_type(self.tcx(), vec![span]).emit(); - self.tcx().consts.err + self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty }) } fn projected_ty_from_poly_trait_ref( @@ -2037,7 +2037,8 @@ fn associated_item_predicates( } ty::GenericParamDefKind::Const => { unimplemented_error("const"); - tcx.consts.err.into() + tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: tcx.type_of(param.def_id) }) + .into() } } };