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]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.3"
|
version = "2.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.11.0",
|
"ansi_term 0.12.1",
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"strsim",
|
"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_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::mir;
|
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::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
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_mir_dataflow::storage::AlwaysLiveLocals;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_session::Limit;
|
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 rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||||
|
|
||||||
use super::{
|
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>>(
|
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
value: T,
|
value: T,
|
||||||
) -> T {
|
) -> Result<T, InterpError<'tcx>> {
|
||||||
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
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,
|
&self,
|
||||||
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
||||||
value: T,
|
value: T,
|
||||||
) -> T {
|
) -> Result<T, InterpError<'tcx>> {
|
||||||
frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
|
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).
|
/// 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 layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
||||||
let local_ty = frame.body.local_decls[local].ty;
|
let local_ty = frame.body.local_decls[local].ty;
|
||||||
let 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)
|
self.layout_of(local_ty)
|
||||||
})?;
|
})?;
|
||||||
if let Some(state) = frame.locals.get(local) {
|
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 {
|
for const_ in &body.required_consts {
|
||||||
let span = const_.span;
|
let span = const_.span;
|
||||||
let const_ =
|
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| {
|
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.
|
// If there was an error, set the span of the current frame to this constant.
|
||||||
// Avoiding doing this when evaluation succeeds.
|
// 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.param_env,
|
||||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||||
))?,
|
)?)?,
|
||||||
op.layout,
|
op.layout,
|
||||||
));
|
));
|
||||||
Ok(op)
|
Ok(op)
|
||||||
@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
Constant(ref constant) => {
|
Constant(ref constant) => {
|
||||||
let val =
|
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:
|
// This can still fail:
|
||||||
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
||||||
// checked yet.
|
// checked yet.
|
||||||
|
@ -643,7 +643,7 @@ where
|
|||||||
self.param_env,
|
self.param_env,
|
||||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||||
))?,
|
)?)?,
|
||||||
place_ty.layout,
|
place_ty.layout,
|
||||||
));
|
));
|
||||||
Ok(place_ty)
|
Ok(place_ty)
|
||||||
|
@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NullaryOp(null_op, ty) => {
|
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)?;
|
let layout = self.layout_of(ty)?;
|
||||||
if layout.is_unsized() {
|
if layout.is_unsized() {
|
||||||
// FIXME: This should be a span_bug (#80742)
|
// 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) => {
|
Cast(cast_kind, ref operand, cast_ty) => {
|
||||||
let src = self.eval_operand(operand, None)?;
|
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)?;
|
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::type_variable::TypeVariableOriginKind;
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::{InferCtxt, Symbol};
|
||||||
use crate::rustc_middle::ty::TypeFoldable;
|
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Namespace};
|
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::infer::unify_key::ConstVariableOriginKind;
|
||||||
use rustc_middle::ty::print::Print;
|
use rustc_middle::ty::print::Print;
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
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::symbol::kw;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -306,6 +305,15 @@ pub enum UnderspecifiedArgKind {
|
|||||||
Const { is_parameter: bool },
|
Const { is_parameter: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UnderspecifiedArgKind {
|
||||||
|
fn descr(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Type { .. } => "type",
|
||||||
|
Self::Const { .. } => "const",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl InferenceDiagnosticsData {
|
impl InferenceDiagnosticsData {
|
||||||
/// Generate a label for a generic argument which can't be inferred. When not
|
/// 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
|
/// 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 {
|
let suffix = match local_visitor.found_node_ty {
|
||||||
Some(ty) if ty.is_closure() => {
|
Some(ty) if ty.is_closure() => {
|
||||||
let substs =
|
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 == "_" => {
|
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
|
||||||
let ty = ty_to_string(ty);
|
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 => {
|
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);
|
let ty = ty_to_string(ty);
|
||||||
format!(
|
format!(
|
||||||
"the explicit type `{}`, where the type parameter `{}` is specified",
|
"the explicit type `{}`, where the {} parameter `{}` is specified",
|
||||||
ty, arg_data.name,
|
ty, param_type, arg_data.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => "a type".to_string(),
|
_ => "a type".to_string(),
|
||||||
@ -908,3 +919,117 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
err
|
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::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||||
|
|
||||||
use std::fmt;
|
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
|
/// 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`.
|
/// identity parameters if they are determined to be unused in `instance.def`.
|
||||||
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
|
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
|
/// Monomorphizes a type from the AST by first applying the
|
||||||
/// in-scope substitutions and then normalizing any associated
|
/// in-scope substitutions and then normalizing any associated
|
||||||
/// types.
|
/// 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>(
|
pub fn subst_and_normalize_erasing_regions<T>(
|
||||||
self,
|
self,
|
||||||
param_substs: SubstsRef<'tcx>,
|
param_substs: SubstsRef<'tcx>,
|
||||||
@ -134,6 +136,30 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
let substituted = value.subst(self, param_substs);
|
let substituted = value.subst(self, param_substs);
|
||||||
self.normalize_erasing_regions(param_env, substituted)
|
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> {
|
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.
|
/// Converts literals, paths and negation of literals to patterns.
|
||||||
/// The special case for negation exists to allow things like `-128_i8`
|
/// 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
|
/// which would overflow if we tried to evaluate `128_i8` and then negate
|
||||||
/// afterwards.
|
/// afterwards.
|
||||||
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
|
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
|
||||||
if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
let (lit, neg) = match expr.kind {
|
||||||
*self.lower_path(qpath, expr.hir_id, expr.span).kind
|
hir::ExprKind::Path(ref qpath) => {
|
||||||
} else {
|
return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
|
||||||
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"),
|
|
||||||
}
|
}
|
||||||
|
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
|
### `-w`/`--output-format`: output format
|
||||||
|
|
||||||
`--output-format json` emits documentation in the experimental
|
`--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.
|
and is also accepted on stable toolchains.
|
||||||
|
|
||||||
It can also be used with `--show-coverage`. Take a look at its
|
It can also be used with `--show-coverage`. Take a look at its
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
id="mainThemeStyle"> {#- -#}
|
id="mainThemeStyle"> {#- -#}
|
||||||
{%- for theme in themes -%}
|
{%- for theme in themes -%}
|
||||||
<link rel="stylesheet" type="text/css" {# -#}
|
<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" -%}
|
{%- if theme == "light" -%}
|
||||||
id="themeStyle"
|
id="themeStyle"
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>`
|
|||||||
LL | let foo = Foo::foo();
|
LL | let foo = Foo::foo();
|
||||||
| --- ^^^^^^^^ cannot infer the value of const parameter `N`
|
| --- ^^^^^^^^ 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
|
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;
|
LL | let x: &'static i32 = &X;
|
||||||
| ^ referenced constant has errors
|
| ^ referenced constant has errors
|
||||||
query stack during panic:
|
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`
|
#1 [optimized_mir] optimizing MIR for `main`
|
||||||
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
||||||
end of query stack
|
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");`!
|
LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
|
||||||
| - ^^^ cannot infer the value of const parameter `N` declared on the function `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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,16 +1,31 @@
|
|||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(inline_const_pat)]
|
#![feature(inline_const_pat)]
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
|
||||||
// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
|
// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
|
||||||
|
|
||||||
fn foo<const V: usize>() {
|
fn foo<const V: usize>() {
|
||||||
match 0 {
|
match 0 {
|
||||||
const { V } => {},
|
const { V } => {},
|
||||||
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
|
//~^ 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() {
|
fn main() {
|
||||||
foo::<1>();
|
foo::<1>();
|
||||||
|
bar::<1>();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,21 @@
|
|||||||
error[E0158]: const parameters cannot be referenced in patterns
|
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`.
|
For more information about this error, try `rustc --explain E0158`.
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7
|
Subproject commit 40dc281755137ee804bc9b3b08e782773b726e44
|
Loading…
x
Reference in New Issue
Block a user