mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 22:46:50 +00:00
Auto merge of #67917 - Dylan-DPC:rollup-id05y91, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #67800 (Fix ICE involving calling `Instance.ty` during const evaluation) - #67873 (change remove to have a PartialEq bound) - #67897 (Use `as_deref()` to replace `as_ref().map(...)`) - #67906 (Silence `TooGeneric` error) - #67912 (macros: typo fix) - #67915 (Use Self instead of $type) Failed merges: r? @ghost
This commit is contained in:
commit
a80e63f3fa
@ -11,6 +11,7 @@
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(binary_heap_into_iter_sorted)]
|
||||
#![feature(binary_heap_drain_sorted)]
|
||||
#![feature(vec_remove_item)]
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -131,6 +131,21 @@ fn test_extend_ref() {
|
||||
assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_item() {
|
||||
let mut v = vec![1, 2, 3];
|
||||
v.remove_item(&1);
|
||||
|
||||
assert_eq!(v.len(), 2);
|
||||
assert_eq!(v, [2, 3]);
|
||||
|
||||
let mut w = vec![1, 2, 3];
|
||||
w.remove_item(&4);
|
||||
|
||||
assert_eq!(w.len(), 3);
|
||||
w.remove_item(&4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_from_mut() {
|
||||
let mut values = vec![1, 2, 3, 4, 5];
|
||||
|
@ -1688,7 +1688,9 @@ impl<T: PartialEq> Vec<T> {
|
||||
pub fn dedup(&mut self) {
|
||||
self.dedup_by(|a, b| a == b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
/// Removes the first instance of `item` from the vector if the item exists.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1702,7 +1704,10 @@ impl<T: PartialEq> Vec<T> {
|
||||
/// assert_eq!(vec, vec![2, 3, 1]);
|
||||
/// ```
|
||||
#[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
|
||||
pub fn remove_item(&mut self, item: &T) -> Option<T> {
|
||||
pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
|
||||
where
|
||||
T: PartialEq<V>,
|
||||
{
|
||||
let pos = self.iter().position(|x| *x == *item)?;
|
||||
Some(self.remove(pos))
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ macro_rules! impl_from {
|
||||
#[doc = $doc]
|
||||
impl From<$Small> for $Large {
|
||||
#[inline]
|
||||
fn from(small: $Small) -> $Large {
|
||||
small as $Large
|
||||
fn from(small: $Small) -> Self {
|
||||
small as Self
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -177,7 +177,7 @@ macro_rules! try_from_unbounded {
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(value: $source) -> Result<Self, Self::Error> {
|
||||
Ok(value as $target)
|
||||
Ok(value as Self)
|
||||
}
|
||||
}
|
||||
)*}
|
||||
@ -194,9 +194,9 @@ macro_rules! try_from_lower_bounded {
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
if u >= 0 {
|
||||
Ok(u as $target)
|
||||
Ok(u as Self)
|
||||
} else {
|
||||
Err(TryFromIntError(()))
|
||||
}
|
||||
@ -216,11 +216,11 @@ macro_rules! try_from_upper_bounded {
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
|
||||
if u > (<$target>::max_value() as $source) {
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
if u > (Self::max_value() as $source) {
|
||||
Err(TryFromIntError(()))
|
||||
} else {
|
||||
Ok(u as $target)
|
||||
Ok(u as Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,13 +238,13 @@ macro_rules! try_from_both_bounded {
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
|
||||
let min = <$target>::min_value() as $source;
|
||||
let max = <$target>::max_value() as $source;
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
let min = Self::min_value() as $source;
|
||||
let max = Self::max_value() as $source;
|
||||
if u < min || u > max {
|
||||
Err(TryFromIntError(()))
|
||||
} else {
|
||||
Ok(u as $target)
|
||||
Ok(u as Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -385,10 +385,10 @@ macro_rules! nzint_impl_from {
|
||||
#[doc = $doc]
|
||||
impl From<$Small> for $Large {
|
||||
#[inline]
|
||||
fn from(small: $Small) -> $Large {
|
||||
fn from(small: $Small) -> Self {
|
||||
// SAFETY: input type guarantees the value is non-zero
|
||||
unsafe {
|
||||
<$Large>::new_unchecked(small.get().into())
|
||||
Self::new_unchecked(small.get().into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ trait Int:
|
||||
|
||||
macro_rules! doit {
|
||||
($($t:ident)*) => ($(impl Int for $t {
|
||||
fn zero() -> $t { 0 }
|
||||
fn from_u8(u: u8) -> $t { u as $t }
|
||||
fn zero() -> Self { 0 }
|
||||
fn from_u8(u: u8) -> Self { u as Self }
|
||||
fn to_u8(&self) -> u8 { *self as u8 }
|
||||
fn to_u16(&self) -> u16 { *self as u16 }
|
||||
fn to_u32(&self) -> u32 { *self as u32 }
|
||||
|
@ -44,28 +44,28 @@ macro_rules! integer_sum_product {
|
||||
(@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
|
||||
#[$attr]
|
||||
impl Sum for $a {
|
||||
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
@ -84,28 +84,28 @@ macro_rules! float_sum_product {
|
||||
($($a:ident)*) => ($(
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl Sum for $a {
|
||||
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(0.0, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(1.0, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(0.0, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(1.0, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ macro_rules! unreachable {
|
||||
|
||||
/// Indicates unimplemented code by panicking with a message of "not implemented".
|
||||
///
|
||||
/// This allows the your code to type-check, which is useful if you are prototyping or
|
||||
/// This allows your code to type-check, which is useful if you are prototyping or
|
||||
/// implementing a trait that requires multiple methods which you don't plan of using all of.
|
||||
///
|
||||
/// The difference between `unimplemented!` and [`todo!`](macro.todo.html) is that while `todo!`
|
||||
|
@ -505,15 +505,15 @@ macro_rules! impls {
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for $t<T> {
|
||||
fn clone(&self) -> $t<T> {
|
||||
$t
|
||||
fn clone(&self) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Default for $t<T> {
|
||||
fn default() -> $t<T> {
|
||||
$t
|
||||
fn default() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,8 +455,8 @@ macro_rules! define_bignum {
|
||||
}
|
||||
|
||||
impl crate::clone::Clone for $name {
|
||||
fn clone(&self) -> $name {
|
||||
$name { size: self.size, base: self.base }
|
||||
fn clone(&self) -> Self {
|
||||
Self { size: self.size, base: self.base }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ use crate::hir::Node;
|
||||
use crate::infer::error_reporting::TypeAnnotationNeeded as ErrorCode;
|
||||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::infer::{self, InferCtxt};
|
||||
use crate::mir::interpret::ErrorHandled;
|
||||
use crate::session::DiagnosticMessageId;
|
||||
use crate::ty::error::ExpectedFound;
|
||||
use crate::ty::fast_reject;
|
||||
@ -1086,6 +1087,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
// already reported in the query
|
||||
ConstEvalFailure(err) => {
|
||||
if let ErrorHandled::TooGeneric = err {
|
||||
// Silence this error, as it can be produced during intermediate steps
|
||||
// when a constant is not yet able to be evaluated (but will be later).
|
||||
return;
|
||||
}
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!("constant in type had an ignored error: {:?}", err),
|
||||
|
@ -62,10 +62,35 @@ pub enum InstanceDef<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> Instance<'tcx> {
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
/// Returns the `Ty` corresponding to this `Instance`,
|
||||
/// with generic substitutions applied and lifetimes erased.
|
||||
///
|
||||
/// This method can only be called when the 'substs' for this Instance
|
||||
/// are fully monomorphic (no `ty::Param`'s are present).
|
||||
/// This is usually the case (e.g. during codegen).
|
||||
/// However, during constant evaluation, we may want
|
||||
/// to try to resolve a `Instance` using generic parameters
|
||||
/// (e.g. when we are attempting to to do const-propagation).
|
||||
/// In this case, `Instance.ty_env` should be used to provide
|
||||
/// the `ParamEnv` for our generic context.
|
||||
pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
let ty = tcx.type_of(self.def.def_id());
|
||||
// There shouldn't be any params - if there are, then
|
||||
// Instance.ty_env should have been used to provide the proper
|
||||
// ParamEnv
|
||||
if self.substs.has_param_types() {
|
||||
bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
|
||||
}
|
||||
tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
|
||||
}
|
||||
|
||||
/// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during
|
||||
/// normalization. This method is only really useful during constant evaluation,
|
||||
/// where we are dealing with potentially generic types.
|
||||
pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||
let ty = tcx.type_of(self.def.def_id());
|
||||
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InstanceDef<'tcx> {
|
||||
|
@ -2301,7 +2301,7 @@ impl<'tcx> ty::Instance<'tcx> {
|
||||
// or should go through `FnAbi` instead, to avoid losing any
|
||||
// adjustments `FnAbi::of_instance` might be performing.
|
||||
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
|
||||
let ty = self.ty(tcx);
|
||||
let ty = self.monomorphic_ty(tcx);
|
||||
match ty.kind {
|
||||
ty::FnDef(..) |
|
||||
// Shims currently have type FnPtr. Not sure this should remain.
|
||||
|
@ -36,7 +36,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
|
||||
}
|
||||
|
||||
let sym = tcx.symbol_name(instance).name.as_str();
|
||||
debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym);
|
||||
debug!("get_fn({:?}: {:?}) => {}", instance, instance.monomorphic_ty(cx.tcx()), sym);
|
||||
|
||||
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
|
||||
|
||||
|
@ -204,7 +204,7 @@ impl CodegenCx<'ll, 'tcx> {
|
||||
def_id
|
||||
);
|
||||
|
||||
let ty = instance.ty(self.tcx);
|
||||
let ty = instance.monomorphic_ty(self.tcx);
|
||||
let sym = self.tcx.symbol_name(instance).name;
|
||||
|
||||
debug!("get_static: sym={} instance={:?}", sym, instance);
|
||||
@ -361,7 +361,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
||||
};
|
||||
|
||||
let instance = Instance::mono(self.tcx, def_id);
|
||||
let ty = instance.ty(self.tcx);
|
||||
let ty = instance.monomorphic_ty(self.tcx);
|
||||
let llty = self.layout_of(ty).llvm_type(self);
|
||||
let g = if val_llty == llty {
|
||||
g
|
||||
|
@ -2287,7 +2287,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
|
||||
};
|
||||
|
||||
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
||||
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx);
|
||||
let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
|
||||
let type_metadata = type_metadata(cx, variable_type, span);
|
||||
let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
|
||||
let linkage_name = if no_mangle {
|
||||
|
@ -89,7 +89,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
span: Span,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let callee_ty = instance.ty(tcx);
|
||||
let callee_ty = instance.monomorphic_ty(tcx);
|
||||
|
||||
let (def_id, substs) = match callee_ty.kind {
|
||||
ty::FnDef(def_id, substs) => (def_id, substs),
|
||||
|
@ -22,7 +22,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
symbol_name: &str,
|
||||
) {
|
||||
let instance = Instance::mono(self.tcx, def_id);
|
||||
let ty = instance.ty(self.tcx);
|
||||
let ty = instance.monomorphic_ty(self.tcx);
|
||||
let llty = self.layout_of(ty).llvm_type(self);
|
||||
|
||||
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
|
||||
|
@ -221,7 +221,7 @@ pub fn const_eval_validated_provider<'tcx>(
|
||||
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
|
||||
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
|
||||
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
|
||||
let ty = key.value.instance.ty(tcx);
|
||||
let ty = key.value.instance.ty_env(tcx, key.param_env);
|
||||
let substs = match ty.kind {
|
||||
ty::FnDef(_, substs) => substs,
|
||||
_ => bug!("intrinsic with type {:?}", ty),
|
||||
|
@ -204,7 +204,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// ABI check
|
||||
{
|
||||
let callee_abi = {
|
||||
let instance_ty = instance.ty(*self.tcx);
|
||||
let instance_ty = instance.ty_env(*self.tcx, self.param_env);
|
||||
match instance_ty.kind {
|
||||
ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
|
||||
ty::Closure(..) => Abi::RustCall,
|
||||
|
@ -140,7 +140,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// to determine the type.
|
||||
let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
|
||||
trace!("Found drop fn: {:?}", drop_instance);
|
||||
let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
|
||||
let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx);
|
||||
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
|
||||
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
|
||||
let args = fn_sig.inputs();
|
||||
|
@ -358,7 +358,7 @@ fn collect_items_rec<'tcx>(
|
||||
// Sanity check whether this ended up being collected accidentally
|
||||
debug_assert!(should_monomorphize_locally(tcx, &instance));
|
||||
|
||||
let ty = instance.ty(tcx);
|
||||
let ty = instance.monomorphic_ty(tcx);
|
||||
visit_drop_use(tcx, ty, true, &mut neighbors);
|
||||
|
||||
recursion_depth_reset = None;
|
||||
@ -1002,7 +1002,8 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
|
||||
def_id_to_string(self.tcx, def_id)
|
||||
);
|
||||
|
||||
let ty = Instance::new(def_id, InternalSubsts::empty()).ty(self.tcx);
|
||||
let ty =
|
||||
Instance::new(def_id, InternalSubsts::empty()).monomorphic_ty(self.tcx);
|
||||
visit_drop_use(self.tcx, ty, true, self.output);
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,10 @@ fn enforce_impl_params_are_constrained(
|
||||
// (#36836)
|
||||
tcx.sess.delay_span_bug(
|
||||
tcx.def_span(impl_def_id),
|
||||
"potentially unconstrained type parameters weren't evaluated",
|
||||
&format!(
|
||||
"potentially unconstrained type parameters weren't evaluated: {:?}",
|
||||
impl_self_ty,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -2152,7 +2152,7 @@ fn stability_tags(item: &clean::Item) -> String {
|
||||
}
|
||||
|
||||
if let Some(stab) = item.stability.as_ref().filter(|s| s.level == stability::Unstable) {
|
||||
if stab.feature.as_ref().map(|s| &**s) == Some("rustc_private") {
|
||||
if stab.feature.as_deref() == Some("rustc_private") {
|
||||
tags += &tag_html("internal", "Internal");
|
||||
} else {
|
||||
tags += &tag_html("unstable", "Experimental");
|
||||
@ -2205,7 +2205,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
||||
}
|
||||
|
||||
if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) {
|
||||
let is_rustc_private = stab.feature.as_ref().map(|s| &**s) == Some("rustc_private");
|
||||
let is_rustc_private = stab.feature.as_deref() == Some("rustc_private");
|
||||
|
||||
let mut message = if is_rustc_private {
|
||||
"<span class='emoji'>⚙️</span> This is an internal compiler API."
|
||||
@ -2214,7 +2214,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
||||
}
|
||||
.to_owned();
|
||||
|
||||
if let Some(feature) = stab.feature.as_ref() {
|
||||
if let Some(feature) = stab.feature.as_deref() {
|
||||
let mut feature = format!("<code>{}</code>", Escape(&feature));
|
||||
if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) {
|
||||
feature.push_str(&format!(
|
||||
|
@ -0,0 +1,23 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct ArithArrayLen<const N: usize>([u32; 0 + N]); // ok
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Config {
|
||||
arr_size: usize,
|
||||
}
|
||||
|
||||
struct B<const CFG: Config> {
|
||||
arr: [u8; CFG.arr_size], // ok
|
||||
}
|
||||
|
||||
const C: Config = Config { arr_size: 5 };
|
||||
|
||||
fn main() {
|
||||
let b = B::<C> { arr: [1, 2, 3, 4, 5] };
|
||||
assert_eq!(b.arr.len(), 5);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/array-size-in-generic-struct-param.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
@ -11,8 +11,8 @@ trait Int {
|
||||
}
|
||||
macro_rules! doit {
|
||||
($($t:ident)*) => ($(impl Int for $t {
|
||||
fn zero() -> $t { 0 }
|
||||
fn one() -> $t { 1 }
|
||||
fn zero() -> Self { 0 }
|
||||
fn one() -> Self { 1 }
|
||||
})*)
|
||||
}
|
||||
doit! { i8 i16 i32 i64 isize }
|
||||
|
34
src/test/ui/mir/issue-67639-normalization-ice.rs
Normal file
34
src/test/ui/mir/issue-67639-normalization-ice.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// compile-flags: -Z mir-opt-level=3
|
||||
// build-pass
|
||||
|
||||
// This used to ICE in const-prop due
|
||||
// to an empty ParamEnv being used during normalization
|
||||
// of a generic type
|
||||
|
||||
|
||||
fn main() {
|
||||
join_all::<u32>();
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
type Item;
|
||||
}
|
||||
|
||||
impl Foo for u32 {
|
||||
type Item = u8;
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
type Item2;
|
||||
}
|
||||
|
||||
impl Bar for u8 {
|
||||
type Item2 = u64;
|
||||
}
|
||||
|
||||
fn join_all<I>()
|
||||
where I: Foo,
|
||||
I::Item: Bar
|
||||
{
|
||||
Vec::<<I::Item as Bar>::Item2>::new(); // ICE occurs processing this line
|
||||
}
|
Loading…
Reference in New Issue
Block a user