Auto merge of #98900 - lcnr:region-stuff, r=jackh726
const_generics: correctly deal with bound variables removes the hack in `resolve` which was needed because we evaluated constants without caring about their bound variables. Each commit should be fairly self-contained, even if they build on each other r? `@jackh726`
This commit is contained in:
commit
ccb5595df2
@ -79,9 +79,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
|||||||
ty::Projection(_)
|
ty::Projection(_)
|
||||||
| ty::Opaque(_, _)
|
| ty::Opaque(_, _)
|
||||||
| ty::Param(_)
|
| ty::Param(_)
|
||||||
| ty::Bound(_, _)
|
|
||||||
| ty::Placeholder(_)
|
| ty::Placeholder(_)
|
||||||
| ty::Infer(_) => throw_inval!(TooGeneric),
|
| ty::Infer(_) => throw_inval!(TooGeneric),
|
||||||
|
ty::Bound(_, _) => bug!("bound ty during ctfe"),
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
|
@ -559,7 +559,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
layout: Option<TyAndLayout<'tcx>>,
|
layout: Option<TyAndLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => throw_inval!(TooGeneric),
|
||||||
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
|
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
|
||||||
throw_inval!(AlreadyReported(reported))
|
throw_inval!(AlreadyReported(reported))
|
||||||
}
|
}
|
||||||
@ -567,7 +567,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
let instance = self.resolve(uv.def, uv.substs)?;
|
let instance = self.resolve(uv.def, uv.substs)?;
|
||||||
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
|
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
|
||||||
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
|
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(valtree) => {
|
ty::ConstKind::Value(valtree) => {
|
||||||
|
@ -486,7 +486,7 @@ struct Generalizer<'cx, 'tcx> {
|
|||||||
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
cache: SsoHashMap<Ty<'tcx>, RelateResult<'tcx, Ty<'tcx>>>,
|
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result from a generalization operation. This includes
|
/// Result from a generalization operation. This includes
|
||||||
@ -593,8 +593,8 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||||
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
||||||
|
|
||||||
if let Some(result) = self.cache.get(&t) {
|
if let Some(&result) = self.cache.get(&t) {
|
||||||
return result.clone();
|
return Ok(result);
|
||||||
}
|
}
|
||||||
debug!("generalize: t={:?}", t);
|
debug!("generalize: t={:?}", t);
|
||||||
|
|
||||||
@ -664,10 +664,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
_ => relate::super_relate_tys(self, t, t),
|
_ => relate::super_relate_tys(self, t, t),
|
||||||
};
|
}?;
|
||||||
|
|
||||||
self.cache.insert(t, result.clone());
|
self.cache.insert(t, result);
|
||||||
return result;
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regions(
|
fn regions(
|
||||||
@ -743,9 +743,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
if self.tcx().lazy_normalization() =>
|
|
||||||
{
|
|
||||||
assert_eq!(promoted, None);
|
assert_eq!(promoted, None);
|
||||||
let substs = self.relate_with_variance(
|
let substs = self.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
@ -967,9 +965,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
if self.tcx().lazy_normalization() =>
|
|
||||||
{
|
|
||||||
assert_eq!(promoted, None);
|
assert_eq!(promoted, None);
|
||||||
let substs = self.relate_with_variance(
|
let substs = self.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
|
@ -180,6 +180,7 @@ impl<'tcx> ConstKind<'tcx> {
|
|||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
eval_mode: EvalMode,
|
eval_mode: EvalMode,
|
||||||
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
|
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
|
||||||
|
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
||||||
if let ConstKind::Unevaluated(unevaluated) = self {
|
if let ConstKind::Unevaluated(unevaluated) = self {
|
||||||
use crate::mir::interpret::ErrorHandled;
|
use crate::mir::interpret::ErrorHandled;
|
||||||
|
|
||||||
|
@ -594,10 +594,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let eagerly_eval = |x: ty::Const<'tcx>| x.eval(tcx, relation.param_env());
|
|
||||||
let a = eagerly_eval(a);
|
|
||||||
let b = eagerly_eval(b);
|
|
||||||
|
|
||||||
// Currently, the values that can be unified are primitive types,
|
// Currently, the values that can be unified are primitive types,
|
||||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||||
// to structural-match types.
|
// to structural-match types.
|
||||||
|
@ -635,13 +635,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
|||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
|
let tcx = self.selcx.tcx();
|
||||||
|
if tcx.lazy_normalization() {
|
||||||
constant
|
constant
|
||||||
} else {
|
} else {
|
||||||
let constant = constant.super_fold_with(self);
|
let constant = constant.super_fold_with(self);
|
||||||
debug!(?constant);
|
debug!(?constant, ?self.param_env);
|
||||||
debug!("self.param_env: {:?}", self.param_env);
|
with_replaced_escaping_bound_vars(
|
||||||
constant.eval(self.selcx.tcx(), self.param_env)
|
self.selcx.infcx(),
|
||||||
|
&mut self.universes,
|
||||||
|
constant,
|
||||||
|
|constant| constant.eval(tcx, self.param_env),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,6 +676,41 @@ pub struct BoundVarReplacer<'me, 'tcx> {
|
|||||||
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
|
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
|
||||||
|
/// and then replaces these placeholders with the original bound variables in the result.
|
||||||
|
///
|
||||||
|
/// In most places, bound variables should be replaced right when entering a binder, making
|
||||||
|
/// this function unnecessary. However, normalization currently does not do that, so we have
|
||||||
|
/// to do this lazily.
|
||||||
|
///
|
||||||
|
/// You should not add any additional uses of this function, at least not without first
|
||||||
|
/// discussing it with t-types.
|
||||||
|
///
|
||||||
|
/// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
|
||||||
|
/// normalization as well, at which point this function will be unnecessary and can be removed.
|
||||||
|
pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: TypeFoldable<'tcx>>(
|
||||||
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
|
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
|
||||||
|
value: T,
|
||||||
|
f: impl FnOnce(T) -> R,
|
||||||
|
) -> R {
|
||||||
|
if value.has_escaping_bound_vars() {
|
||||||
|
let (value, mapped_regions, mapped_types, mapped_consts) =
|
||||||
|
BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
|
||||||
|
let result = f(value);
|
||||||
|
PlaceholderReplacer::replace_placeholders(
|
||||||
|
infcx,
|
||||||
|
mapped_regions,
|
||||||
|
mapped_types,
|
||||||
|
mapped_consts,
|
||||||
|
universe_indices,
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
f(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
|
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
|
||||||
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
|
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
|
||||||
/// use a binding level above `universe_indices.len()`, we fail.
|
/// use a binding level above `universe_indices.len()`, we fail.
|
||||||
|
@ -6,7 +6,7 @@ use crate::infer::at::At;
|
|||||||
use crate::infer::canonical::OriginalQueryValues;
|
use crate::infer::canonical::OriginalQueryValues;
|
||||||
use crate::infer::{InferCtxt, InferOk};
|
use crate::infer::{InferCtxt, InferOk};
|
||||||
use crate::traits::error_reporting::InferCtxtExt;
|
use crate::traits::error_reporting::InferCtxtExt;
|
||||||
use crate::traits::project::needs_normalization;
|
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
|
||||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
|
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
|
||||||
use rustc_data_structures::sso::SsoHashMap;
|
use rustc_data_structures::sso::SsoHashMap;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
@ -283,11 +283,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let infcx = self.infcx;
|
let infcx = self.infcx;
|
||||||
let (data, mapped_regions, mapped_types, mapped_consts) =
|
let (data, mapped_regions, mapped_types, mapped_consts) =
|
||||||
crate::traits::project::BoundVarReplacer::replace_bound_vars(
|
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
|
||||||
infcx,
|
|
||||||
&mut self.universes,
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
let data = data.try_fold_with(self)?;
|
let data = data.try_fold_with(self)?;
|
||||||
|
|
||||||
let mut orig_values = OriginalQueryValues::default();
|
let mut orig_values = OriginalQueryValues::default();
|
||||||
@ -313,8 +309,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||||||
debug!("QueryNormalizer: result = {:#?}", result);
|
debug!("QueryNormalizer: result = {:#?}", result);
|
||||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||||
self.obligations.extend(obligations);
|
self.obligations.extend(obligations);
|
||||||
|
let res = PlaceholderReplacer::replace_placeholders(
|
||||||
let res = crate::traits::project::PlaceholderReplacer::replace_placeholders(
|
|
||||||
infcx,
|
infcx,
|
||||||
mapped_regions,
|
mapped_regions,
|
||||||
mapped_types,
|
mapped_types,
|
||||||
@ -343,7 +338,13 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||||||
constant: ty::Const<'tcx>,
|
constant: ty::Const<'tcx>,
|
||||||
) -> Result<ty::Const<'tcx>, Self::Error> {
|
) -> Result<ty::Const<'tcx>, Self::Error> {
|
||||||
let constant = constant.try_super_fold_with(self)?;
|
let constant = constant.try_super_fold_with(self)?;
|
||||||
Ok(constant.eval(self.infcx.tcx, self.param_env))
|
debug!(?constant, ?self.param_env);
|
||||||
|
Ok(crate::traits::project::with_replaced_escaping_bound_vars(
|
||||||
|
self.infcx,
|
||||||
|
&mut self.universes,
|
||||||
|
constant,
|
||||||
|
|constant| constant.eval(self.infcx.tcx, self.param_env),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fold_mir_const(
|
fn try_fold_mir_const(
|
||||||
|
@ -495,13 +495,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
pub fn to_const(&self, ast_c: &hir::AnonConst) -> ty::Const<'tcx> {
|
pub fn to_const(&self, ast_c: &hir::AnonConst) -> ty::Const<'tcx> {
|
||||||
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
||||||
|
let span = self.tcx.hir().span(ast_c.hir_id);
|
||||||
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
||||||
self.register_wf_obligation(
|
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
||||||
c.into(),
|
self.normalize_associated_types_in(span, c)
|
||||||
self.tcx.hir().span(ast_c.hir_id),
|
|
||||||
ObligationCauseCode::WellFormed(None),
|
|
||||||
);
|
|
||||||
c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_arg_to_const(
|
pub fn const_arg_to_const(
|
||||||
|
@ -2,5 +2,4 @@ fn main() {
|
|||||||
[(); &(&'static: loop { |x| {}; }) as *const _ as usize]
|
[(); &(&'static: loop { |x| {}; }) as *const _ as usize]
|
||||||
//~^ ERROR: invalid label name `'static`
|
//~^ ERROR: invalid label name `'static`
|
||||||
//~| ERROR: type annotations needed
|
//~| ERROR: type annotations needed
|
||||||
//~| ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,6 @@ help: consider giving this closure parameter an explicit type
|
|||||||
LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
|
LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
|
||||||
| +++
|
| +++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/issue-52437.rs:2:5
|
|
||||||
|
|
|
||||||
LL | fn main() {
|
|
||||||
| - expected `()` because of default return type
|
|
||||||
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[(); _]`
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
For more information about this error, try `rustc --explain E0282`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0308.
|
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
|
||||||
|
@ -2,7 +2,6 @@ fn a() {
|
|||||||
[0; [|_: _ &_| ()].len()]
|
[0; [|_: _ &_| ()].len()]
|
||||||
//~^ ERROR expected `,`, found `&`
|
//~^ ERROR expected `,`, found `&`
|
||||||
//~| ERROR type annotations needed
|
//~| ERROR type annotations needed
|
||||||
//~| ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b() {
|
fn b() {
|
||||||
@ -13,13 +12,11 @@ fn b() {
|
|||||||
fn c() {
|
fn c() {
|
||||||
[0; [|&_: _ &_| {}; 0 ].len()]
|
[0; [|&_: _ &_| {}; 0 ].len()]
|
||||||
//~^ ERROR expected `,`, found `&`
|
//~^ ERROR expected `,`, found `&`
|
||||||
//~| ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn d() {
|
fn d() {
|
||||||
[0; match [|f @ &ref _| () ] {} ]
|
[0; match [|f @ &ref _| () ] {} ]
|
||||||
//~^ ERROR expected identifier, found reserved identifier `_`
|
//~^ ERROR expected identifier, found reserved identifier `_`
|
||||||
//~| ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -7,13 +7,13 @@ LL | [0; [|_: _ &_| ()].len()]
|
|||||||
| help: missing `,`
|
| help: missing `,`
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/issue-66706.rs:9:20
|
--> $DIR/issue-66706.rs:8:20
|
||||||
|
|
|
|
||||||
LL | [0; [|f @ &ref _| {} ; 0 ].len() ];
|
LL | [0; [|f @ &ref _| {} ; 0 ].len() ];
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected `,`, found `&`
|
error: expected `,`, found `&`
|
||||||
--> $DIR/issue-66706.rs:14:17
|
--> $DIR/issue-66706.rs:13:17
|
||||||
|
|
|
|
||||||
LL | [0; [|&_: _ &_| {}; 0 ].len()]
|
LL | [0; [|&_: _ &_| {}; 0 ].len()]
|
||||||
| -^ expected `,`
|
| -^ expected `,`
|
||||||
@ -21,7 +21,7 @@ LL | [0; [|&_: _ &_| {}; 0 ].len()]
|
|||||||
| help: missing `,`
|
| help: missing `,`
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/issue-66706.rs:20:26
|
--> $DIR/issue-66706.rs:18:26
|
||||||
|
|
|
|
||||||
LL | [0; match [|f @ &ref _| () ] {} ]
|
LL | [0; match [|f @ &ref _| () ] {} ]
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
@ -32,31 +32,6 @@ error[E0282]: type annotations needed
|
|||||||
LL | [0; [|_: _ &_| ()].len()]
|
LL | [0; [|_: _ &_| ()].len()]
|
||||||
| ^ cannot infer type
|
| ^ cannot infer type
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to 5 previous errors
|
||||||
--> $DIR/issue-66706.rs:2:5
|
|
||||||
|
|
|
||||||
LL | fn a() {
|
|
||||||
| - help: try adding a return type: `-> [i32; _]`
|
|
||||||
LL | [0; [|_: _ &_| ()].len()]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
For more information about this error, try `rustc --explain E0282`.
|
||||||
--> $DIR/issue-66706.rs:14:5
|
|
||||||
|
|
|
||||||
LL | fn c() {
|
|
||||||
| - help: try adding a return type: `-> [i32; _]`
|
|
||||||
LL | [0; [|&_: _ &_| {}; 0 ].len()]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/issue-66706.rs:20:5
|
|
||||||
|
|
|
||||||
LL | fn d() {
|
|
||||||
| - help: try adding a return type: `-> [i32; _]`
|
|
||||||
LL | [0; match [|f @ &ref _| () ] {} ]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
|
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0308.
|
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user