mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #91665 - matthiaskrgr:rollup-o3wnkam, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #90709 (Only shown relevant type params in E0283 label) - #91551 (Allow for failure of subst_normalize_erasing_regions in const_eval) - #91570 (Evaluate inline const pat early and report error if too generic) - #91571 (Remove unneeded access to pretty printer's `s` field in favor of deref) - #91610 (Link to rustdoc_json_types docs instead of rustdoc-json RFC) - #91619 (Update cargo) - #91630 (Add missing whitespace before disabled HTML attribute) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e6b883c74f
@ -558,11 +558,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0",
|
||||
"ansi_term 0.12.1",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo};
|
||||
use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::{
|
||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
||||
@ -14,7 +15,7 @@ use rustc_middle::ty::{
|
||||
use rustc_mir_dataflow::storage::AlwaysLiveLocals;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::{Pos, Span};
|
||||
use rustc_span::{Pos, Span, DUMMY_SP};
|
||||
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||
|
||||
use super::{
|
||||
@ -508,7 +509,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
value: T,
|
||||
) -> T {
|
||||
) -> Result<T, InterpError<'tcx>> {
|
||||
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
||||
}
|
||||
|
||||
@ -518,8 +519,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
&self,
|
||||
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
||||
value: T,
|
||||
) -> T {
|
||||
frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
|
||||
) -> Result<T, InterpError<'tcx>> {
|
||||
frame
|
||||
.instance
|
||||
.try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
|
||||
.or_else(|e| {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
format!("failed to normalize {}", e.get_type_for_failure()).as_str(),
|
||||
);
|
||||
|
||||
Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric))
|
||||
})
|
||||
}
|
||||
|
||||
/// The `substs` are assumed to already be in our interpreter "universe" (param_env).
|
||||
@ -554,7 +565,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
||||
let local_ty = frame.body.local_decls[local].ty;
|
||||
let local_ty =
|
||||
self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
|
||||
self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
||||
self.layout_of(local_ty)
|
||||
})?;
|
||||
if let Some(state) = frame.locals.get(local) {
|
||||
@ -702,7 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
for const_ in &body.required_consts {
|
||||
let span = const_.span;
|
||||
let const_ =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal);
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?;
|
||||
self.mir_const_to_op(&const_, None).map_err(|err| {
|
||||
// If there was an error, set the span of the current frame to this constant.
|
||||
// Avoiding doing this when evaluation succeeds.
|
||||
|
@ -512,7 +512,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
self.param_env,
|
||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||
))?,
|
||||
)?)?,
|
||||
op.layout,
|
||||
));
|
||||
Ok(op)
|
||||
@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
Constant(ref constant) => {
|
||||
let val =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal);
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
|
||||
// This can still fail:
|
||||
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
||||
// checked yet.
|
||||
|
@ -643,7 +643,7 @@ where
|
||||
self.param_env,
|
||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||
))?,
|
||||
)?)?,
|
||||
place_ty.layout,
|
||||
));
|
||||
Ok(place_ty)
|
||||
|
@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
NullaryOp(null_op, ty) => {
|
||||
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
|
||||
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
|
||||
let layout = self.layout_of(ty)?;
|
||||
if layout.is_unsized() {
|
||||
// FIXME: This should be a span_bug (#80742)
|
||||
@ -302,7 +302,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
Cast(cast_kind, ref operand, cast_ty) => {
|
||||
let src = self.eval_operand(operand, None)?;
|
||||
let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
|
||||
let cast_ty =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?;
|
||||
self.cast(&src, cast_kind, cast_ty, &dest)?;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
use crate::infer::type_variable::TypeVariableOriginKind;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::rustc_middle::ty::TypeFoldable;
|
||||
use crate::infer::{InferCtxt, Symbol};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Namespace};
|
||||
@ -11,7 +10,7 @@ use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::Span;
|
||||
use std::borrow::Cow;
|
||||
@ -306,6 +305,15 @@ pub enum UnderspecifiedArgKind {
|
||||
Const { is_parameter: bool },
|
||||
}
|
||||
|
||||
impl UnderspecifiedArgKind {
|
||||
fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Type { .. } => "type",
|
||||
Self::Const { .. } => "const",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InferenceDiagnosticsData {
|
||||
/// Generate a label for a generic argument which can't be inferred. When not
|
||||
/// much is known about the argument, `use_diag` may be used to describe the
|
||||
@ -588,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let param_type = arg_data.kind.descr();
|
||||
let suffix = match local_visitor.found_node_ty {
|
||||
Some(ty) if ty.is_closure() => {
|
||||
let substs =
|
||||
@ -626,13 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
|
||||
let ty = ty_to_string(ty);
|
||||
format!("the explicit type `{}`, with the type parameters specified", ty)
|
||||
format!("the explicit type `{}`, with the {} parameters specified", ty, param_type)
|
||||
}
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
|
||||
let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty);
|
||||
let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty);
|
||||
let ty = ty_to_string(ty);
|
||||
format!(
|
||||
"the explicit type `{}`, where the type parameter `{}` is specified",
|
||||
ty, arg_data.name,
|
||||
"the explicit type `{}`, where the {} parameter `{}` is specified",
|
||||
ty, param_type, arg_data.name,
|
||||
)
|
||||
}
|
||||
_ => "a type".to_string(),
|
||||
@ -908,3 +919,117 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After
|
||||
/// performing that replacement, we'll turn all remaining infer type params to use their name from
|
||||
/// their definition, and replace all the `[type error]`s back to being infer so they display in
|
||||
/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
|
||||
/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
|
||||
/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
|
||||
struct ResolvedTypeParamEraser<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
level: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> ResolvedTypeParamEraser<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
ResolvedTypeParamEraser { tcx, level: 0 }
|
||||
}
|
||||
|
||||
/// Replace not yet inferred const params with their def name.
|
||||
fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> {
|
||||
match c.val {
|
||||
ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty),
|
||||
_ => c,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.level += 1;
|
||||
let t = match t.kind() {
|
||||
// We'll hide this type only if all its type params are hidden as well.
|
||||
ty::Adt(def, substs) => {
|
||||
let generics = self.tcx().generics_of(def.did);
|
||||
// Account for params with default values, like `Vec`, where we
|
||||
// want to show `Vec<T>`, not `Vec<T, _>`. If we replaced that
|
||||
// subst, then we'd get the incorrect output, so we passthrough.
|
||||
let substs: Vec<_> = substs
|
||||
.iter()
|
||||
.zip(generics.params.iter())
|
||||
.map(|(subst, param)| match &(subst.unpack(), ¶m.kind) {
|
||||
(_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst,
|
||||
(crate::infer::GenericArgKind::Const(c), _) => {
|
||||
self.replace_infers(c, param.index, param.name).into()
|
||||
}
|
||||
_ => subst.super_fold_with(self),
|
||||
})
|
||||
.collect();
|
||||
let should_keep = |subst: &GenericArg<'_>| match subst.unpack() {
|
||||
ty::subst::GenericArgKind::Type(t) => match t.kind() {
|
||||
ty::Error(_) => false,
|
||||
_ => true,
|
||||
},
|
||||
// Account for `const` params here, otherwise `doesnt_infer.rs`
|
||||
// shows `_` instead of `Foo<{ _: u32 }>`
|
||||
ty::subst::GenericArgKind::Const(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
if self.level == 1 || substs.iter().any(should_keep) {
|
||||
let substs = self.tcx().intern_substs(&substs[..]);
|
||||
self.tcx().mk_ty(ty::Adt(def, substs))
|
||||
} else {
|
||||
self.tcx().ty_error()
|
||||
}
|
||||
}
|
||||
ty::Ref(_, ty, _) => {
|
||||
let ty = self.fold_ty(ty);
|
||||
match ty.kind() {
|
||||
// Avoid `&_`, these can be safely presented as `_`.
|
||||
ty::Error(_) => self.tcx().ty_error(),
|
||||
_ => t.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
// We could account for `()` if we wanted to replace it, but it's assured to be short.
|
||||
ty::Tuple(_)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Opaque(..)
|
||||
| ty::Projection(_)
|
||||
| ty::Never => t.super_fold_with(self),
|
||||
ty::Array(ty, c) => self
|
||||
.tcx()
|
||||
.mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))),
|
||||
// We don't want to hide type params that haven't been resolved yet.
|
||||
// This would be the type that will be written out with the type param
|
||||
// name in the output.
|
||||
ty::Infer(_) => t,
|
||||
// We don't want to hide the outermost type, only its type params.
|
||||
_ if self.level == 1 => t.super_fold_with(self),
|
||||
// Hide this type
|
||||
_ => self.tcx().ty_error(),
|
||||
};
|
||||
self.level -= 1;
|
||||
t
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`.
|
||||
struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>);
|
||||
impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
||||
self.0
|
||||
}
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match t.kind() {
|
||||
ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)),
|
||||
_ => t.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@ -575,6 +576,23 @@ impl<'tcx> Instance<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn try_subst_mir_and_normalize_erasing_regions<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
v: T,
|
||||
) -> Result<T, NormalizationError<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<'tcx> + Clone,
|
||||
{
|
||||
if let Some(substs) = self.substs_for_mir_body() {
|
||||
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
|
||||
} else {
|
||||
tcx.try_normalize_erasing_regions(param_env, v)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
|
||||
/// identity parameters if they are determined to be unused in `instance.def`.
|
||||
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
|
||||
|
@ -115,6 +115,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Monomorphizes a type from the AST by first applying the
|
||||
/// in-scope substitutions and then normalizing any associated
|
||||
/// types.
|
||||
/// Panics if normalization fails. In case normalization might fail
|
||||
/// use `try_subst_and_normalize_erasing_regions` instead.
|
||||
pub fn subst_and_normalize_erasing_regions<T>(
|
||||
self,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
@ -134,6 +136,30 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
let substituted = value.subst(self, param_substs);
|
||||
self.normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
|
||||
/// Monomorphizes a type from the AST by first applying the
|
||||
/// in-scope substitutions and then trying to normalize any associated
|
||||
/// types. Contrary to `subst_and_normalize_erasing_regions` this does
|
||||
/// not assume that normalization succeeds.
|
||||
pub fn try_subst_and_normalize_erasing_regions<T>(
|
||||
self,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
) -> Result<T, NormalizationError<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
debug!(
|
||||
"subst_and_normalize_erasing_regions(\
|
||||
param_substs={:?}, \
|
||||
value={:?}, \
|
||||
param_env={:?})",
|
||||
param_substs, value, param_env,
|
||||
);
|
||||
let substituted = value.subst(self, param_substs);
|
||||
self.try_normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
}
|
||||
|
||||
struct NormalizeAfterErasingRegionsFolder<'tcx> {
|
||||
|
@ -533,43 +533,64 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts inline const patterns.
|
||||
fn lower_inline_const(
|
||||
&mut self,
|
||||
anon_const: &'tcx hir::AnonConst,
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
) -> PatKind<'tcx> {
|
||||
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
|
||||
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
|
||||
|
||||
// Evaluate early like we do in `lower_path`.
|
||||
let value = value.eval(self.tcx, self.param_env);
|
||||
|
||||
match value.val {
|
||||
ConstKind::Param(_) => {
|
||||
self.errors.push(PatternError::ConstParamInPattern(span));
|
||||
return PatKind::Wild;
|
||||
}
|
||||
ConstKind::Unevaluated(_) => {
|
||||
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
|
||||
self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
|
||||
return PatKind::Wild;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
*self.const_to_pat(value, id, span, false).kind
|
||||
}
|
||||
|
||||
/// Converts literals, paths and negation of literals to patterns.
|
||||
/// The special case for negation exists to allow things like `-128_i8`
|
||||
/// which would overflow if we tried to evaluate `128_i8` and then negate
|
||||
/// afterwards.
|
||||
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
|
||||
if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
||||
*self.lower_path(qpath, expr.hir_id, expr.span).kind
|
||||
} else {
|
||||
let (lit, neg) = match expr.kind {
|
||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
|
||||
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
|
||||
if matches!(value.val, ConstKind::Param(_)) {
|
||||
let span = self.tcx.hir().span(anon_const.hir_id);
|
||||
self.errors.push(PatternError::ConstParamInPattern(span));
|
||||
return PatKind::Wild;
|
||||
}
|
||||
return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind;
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => (lit, false),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
|
||||
let lit = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => lit,
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
(lit, true)
|
||||
}
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
|
||||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
|
||||
Err(LitToConstError::Reported) => PatKind::Wild,
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
let (lit, neg) = match expr.kind {
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
|
||||
}
|
||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => (lit, false),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
|
||||
let lit = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => lit,
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
(lit, true)
|
||||
}
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
|
||||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
|
||||
Err(LitToConstError::Reported) => PatKind::Wild,
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ Note that the third item is the crate root, which in this case is undocumented.
|
||||
### `-w`/`--output-format`: output format
|
||||
|
||||
`--output-format json` emits documentation in the experimental
|
||||
[JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect,
|
||||
[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect,
|
||||
and is also accepted on stable toolchains.
|
||||
|
||||
It can also be used with `--show-coverage`. Take a look at its
|
||||
|
@ -20,7 +20,7 @@
|
||||
id="mainThemeStyle"> {#- -#}
|
||||
{%- for theme in themes -%}
|
||||
<link rel="stylesheet" type="text/css" {# -#}
|
||||
href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {#- -#}
|
||||
href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
|
||||
{%- if theme == "light" -%}
|
||||
id="themeStyle"
|
||||
{%- else -%}
|
||||
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>`
|
||||
LL | let foo = Foo::foo();
|
||||
| --- ^^^^^^^^ cannot infer the value of const parameter `N`
|
||||
| |
|
||||
| consider giving `foo` the explicit type `Foo<{_: u32}>`, where the type parameter `N` is specified
|
||||
| consider giving `foo` the explicit type `Foo<N>`, where the const parameter `N` is specified
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
49
src/test/ui/const-generics/issues/issue-72845.rs
Normal file
49
src/test/ui/const-generics/issues/issue-72845.rs
Normal file
@ -0,0 +1,49 @@
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(specialization)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
trait Depth {
|
||||
const C: usize;
|
||||
}
|
||||
|
||||
trait Type {
|
||||
type AT: Depth;
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
enum Predicate<const B: bool> {}
|
||||
|
||||
trait Satisfied {}
|
||||
|
||||
impl Satisfied for Predicate<true> {}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
trait Spec1 {}
|
||||
|
||||
impl<T: Type> Spec1 for T where Predicate<{T::AT::C > 0}>: Satisfied {}
|
||||
|
||||
trait Spec2 {}
|
||||
|
||||
//impl<T: Type > Spec2 for T where Predicate<{T::AT::C > 1}>: Satisfied {}
|
||||
impl<T: Type > Spec2 for T where Predicate<true>: Satisfied {}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
trait Foo {
|
||||
fn Bar();
|
||||
}
|
||||
|
||||
impl<T: Spec1> Foo for T {
|
||||
default fn Bar() {}
|
||||
}
|
||||
|
||||
impl<T: Spec2> Foo for T {
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
fn Bar() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/const-generics/issues/issue-72845.stderr
Normal file
12
src/test/ui/const-generics/issues/issue-72845.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `Foo`
|
||||
--> $DIR/issue-72845.rs:44:1
|
||||
|
|
||||
LL | impl<T: Spec1> Foo for T {
|
||||
| ------------------------ first implementation here
|
||||
...
|
||||
LL | impl<T: Spec2> Foo for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
|
||||
LL | let x: &'static i32 = &X;
|
||||
| ^ referenced constant has errors
|
||||
query stack during panic:
|
||||
#0 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
|
||||
#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
|
||||
#1 [optimized_mir] optimizing MIR for `main`
|
||||
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
||||
end of query stack
|
||||
|
27
src/test/ui/inference/erase-type-params-in-label.rs
Normal file
27
src/test/ui/inference/erase-type-params-in-label.rs
Normal file
@ -0,0 +1,27 @@
|
||||
fn main() {
|
||||
let foo = foo(1, ""); //~ ERROR E0283
|
||||
}
|
||||
fn baz() {
|
||||
let bar = bar(1, ""); //~ ERROR E0283
|
||||
}
|
||||
|
||||
struct Bar<T, K, N: Default> {
|
||||
t: T,
|
||||
k: K,
|
||||
n: N,
|
||||
}
|
||||
|
||||
fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
|
||||
Bar { t, k, n: Default::default() }
|
||||
}
|
||||
|
||||
struct Foo<T, K, N: Default, M: Default> {
|
||||
t: T,
|
||||
k: K,
|
||||
n: N,
|
||||
m: M,
|
||||
}
|
||||
|
||||
fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
|
||||
Foo { t, k, n: Default::default(), m: Default::default() }
|
||||
}
|
41
src/test/ui/inference/erase-type-params-in-label.stderr
Normal file
41
src/test/ui/inference/erase-type-params-in-label.stderr
Normal file
@ -0,0 +1,41 @@
|
||||
error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
|
||||
--> $DIR/erase-type-params-in-label.rs:2:15
|
||||
|
|
||||
LL | let foo = foo(1, "");
|
||||
| --- ^^^ cannot infer type for type parameter `W` declared on the function `foo`
|
||||
| |
|
||||
| consider giving `foo` the explicit type `Foo<_, _, W, Z>`, where the type parameter `W` is specified
|
||||
|
|
||||
= note: cannot satisfy `_: Default`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/erase-type-params-in-label.rs:25:17
|
||||
|
|
||||
LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
|
||||
| ^^^^^^^ required by this bound in `foo`
|
||||
help: consider specifying the type arguments in the function call
|
||||
|
|
||||
LL | let foo = foo::<T, K, W, Z>(1, "");
|
||||
| ++++++++++++++
|
||||
|
||||
error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
|
||||
--> $DIR/erase-type-params-in-label.rs:5:15
|
||||
|
|
||||
LL | let bar = bar(1, "");
|
||||
| --- ^^^ cannot infer type for type parameter `Z` declared on the function `bar`
|
||||
| |
|
||||
| consider giving `bar` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified
|
||||
|
|
||||
= note: cannot satisfy `_: Default`
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/erase-type-params-in-label.rs:14:17
|
||||
|
|
||||
LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
|
||||
| ^^^^^^^ required by this bound in `bar`
|
||||
help: consider specifying the type arguments in the function call
|
||||
|
|
||||
LL | let bar = bar::<T, K, Z>(1, "");
|
||||
| +++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]`
|
||||
LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
|
||||
| - ^^^ cannot infer the value of const parameter `N` declared on the function `foo`
|
||||
| |
|
||||
| consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified
|
||||
| consider giving this pattern the explicit type `[_; N]`, where the const parameter `N` is specified
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,16 +1,31 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const_pat)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
|
||||
|
||||
fn foo<const V: usize>() {
|
||||
match 0 {
|
||||
const { V } => {},
|
||||
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
|
||||
_ => {},
|
||||
}
|
||||
match 0 {
|
||||
const { V } => {},
|
||||
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
const fn f(x: usize) -> usize {
|
||||
x + 1
|
||||
}
|
||||
|
||||
fn bar<const V: usize>() where [(); f(V)]: {
|
||||
match 0 {
|
||||
const { f(V) } => {},
|
||||
//~^ ERROR constant pattern depends on a generic parameter
|
||||
//~| ERROR constant pattern depends on a generic parameter
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::<1>();
|
||||
bar::<1>();
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
error[E0158]: const parameters cannot be referenced in patterns
|
||||
--> $DIR/const-match-pat-generic.rs:8:11
|
||||
--> $DIR/const-match-pat-generic.rs:9:9
|
||||
|
|
||||
LL | const { V } => {},
|
||||
| ^^^^^
|
||||
LL | const { V } => {},
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:21:9
|
||||
|
|
||||
LL | const { f(V) } => {},
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:21:9
|
||||
|
|
||||
LL | const { f(V) } => {},
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7
|
||||
Subproject commit 40dc281755137ee804bc9b3b08e782773b726e44
|
Loading…
Reference in New Issue
Block a user