Auto merge of #60058 - varkor:const-generics-ty-refactor, r=cramertj
Make const parameters enforce no variance constraints Fixes https://github.com/rust-lang/rust/issues/60047. Also includes some minor const refactoring for convenience.
This commit is contained in:
commit
e577e49b9f
8 changed files with 47 additions and 38 deletions
|
@ -934,12 +934,10 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
|
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
|
||||||
for param in &self.params {
|
if self.own_requires_monomorphization() {
|
||||||
match param.kind {
|
return true;
|
||||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
|
|
||||||
GenericParamDefKind::Lifetime => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(parent_def_id) = self.parent {
|
if let Some(parent_def_id) = self.parent {
|
||||||
let parent = tcx.generics_of(parent_def_id);
|
let parent = tcx.generics_of(parent_def_id);
|
||||||
parent.requires_monomorphization(tcx)
|
parent.requires_monomorphization(tcx)
|
||||||
|
@ -948,6 +946,16 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn own_requires_monomorphization(&self) -> bool {
|
||||||
|
for param in &self.params {
|
||||||
|
match param.kind {
|
||||||
|
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
|
||||||
|
GenericParamDefKind::Lifetime => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn region_param(&'tcx self,
|
pub fn region_param(&'tcx self,
|
||||||
param: &EarlyBoundRegion,
|
param: &EarlyBoundRegion,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||||
|
|
|
@ -480,6 +480,8 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let type_length_limit = *tcx.sess.type_length_limit.get();
|
let type_length_limit = *tcx.sess.type_length_limit.get();
|
||||||
// We include the const length in the type length, as it's better
|
// We include the const length in the type length, as it's better
|
||||||
// to be overly conservative.
|
// to be overly conservative.
|
||||||
|
// FIXME(const_generics): we should instead uniformly walk through `substs`,
|
||||||
|
// ignoring lifetimes.
|
||||||
if type_length + const_length > type_length_limit {
|
if type_length + const_length > type_length_limit {
|
||||||
// The instance name is already known to be too long for rustc.
|
// The instance name is already known to be too long for rustc.
|
||||||
// Show only the first and last 32 characters to avoid blasting
|
// Show only the first and last 32 characters to avoid blasting
|
||||||
|
@ -1135,8 +1137,7 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let counts = tcx.generics_of(method.def_id).own_counts();
|
if tcx.generics_of(method.def_id).own_requires_monomorphization() {
|
||||||
if counts.types + counts.consts != 0 {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -560,8 +560,7 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
|
||||||
|
|
||||||
// FIXME: when we make this a hard error, this should have its
|
// FIXME: when we make this a hard error, this should have its
|
||||||
// own error code.
|
// own error code.
|
||||||
let counts = tcx.generics_of(def_id).own_counts();
|
let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
|
||||||
let message = if counts.types + counts.consts != 0 {
|
|
||||||
"#[derive] can't be used on a #[repr(packed)] struct with \
|
"#[derive] can't be used on a #[repr(packed)] struct with \
|
||||||
type or const parameters (error E0133)".to_string()
|
type or const parameters (error E0133)".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
//! We walk the set of items and, for each member, generate new constraints.
|
//! We walk the set of items and, for each member, generate new constraints.
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use rustc::mir::interpret::ConstValue;
|
|
||||||
use rustc::ty::subst::{SubstsRef, UnpackedKind};
|
use rustc::ty::subst::{SubstsRef, UnpackedKind};
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
@ -239,8 +238,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
UnpackedKind::Type(ty) => {
|
UnpackedKind::Type(ty) => {
|
||||||
self.add_constraints_from_ty(current, ty, variance_i)
|
self.add_constraints_from_ty(current, ty, variance_i)
|
||||||
}
|
}
|
||||||
UnpackedKind::Const(ct) => {
|
UnpackedKind::Const(_) => {
|
||||||
self.add_constraints_from_const(current, ct, variance_i)
|
// Consts impose no constraints.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,9 +274,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
|
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Array(typ, len) => {
|
ty::Array(typ, _) => {
|
||||||
self.add_constraints_from_ty(current, typ, variance);
|
self.add_constraints_from_ty(current, typ, variance);
|
||||||
self.add_constraints_from_const(current, len, variance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Slice(typ) => {
|
ty::Slice(typ) => {
|
||||||
|
@ -395,8 +393,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
UnpackedKind::Type(ty) => {
|
UnpackedKind::Type(ty) => {
|
||||||
self.add_constraints_from_ty(current, ty, variance_i)
|
self.add_constraints_from_ty(current, ty, variance_i)
|
||||||
}
|
}
|
||||||
UnpackedKind::Const(ct) => {
|
UnpackedKind::Const(_) => {
|
||||||
self.add_constraints_from_const(current, ct, variance_i)
|
// Consts impose no constraints.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,24 +447,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_constraints_from_const(
|
|
||||||
&mut self,
|
|
||||||
current: &CurrentItem,
|
|
||||||
ct: &ty::Const<'tcx>,
|
|
||||||
variance: VarianceTermPtr<'a>
|
|
||||||
) {
|
|
||||||
debug!(
|
|
||||||
"add_constraints_from_const(ct={:?}, variance={:?})",
|
|
||||||
ct,
|
|
||||||
variance
|
|
||||||
);
|
|
||||||
|
|
||||||
self.add_constraints_from_ty(current, ct.ty, variance);
|
|
||||||
if let ConstValue::Param(ref data) = ct.val {
|
|
||||||
self.add_constraint(current, data.index, variance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds constraints appropriate for a mutability-type pair
|
/// Adds constraints appropriate for a mutability-type pair
|
||||||
/// appearing in a context with ambient variance `variance`
|
/// appearing in a context with ambient variance `variance`
|
||||||
fn add_constraints_from_mt(&mut self,
|
fn add_constraints_from_mt(&mut self,
|
||||||
|
|
|
@ -85,12 +85,19 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
|
||||||
self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
|
self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
|
||||||
let def_id = tcx.hir().local_def_id_from_hir_id(id);
|
let def_id = tcx.hir().local_def_id_from_hir_id(id);
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
|
let count = generics.count();
|
||||||
|
|
||||||
let mut variances = solutions[start..start+generics.count()].to_vec();
|
let mut variances = solutions[start..(start + count)].to_vec();
|
||||||
|
|
||||||
debug!("id={} variances={:?}", id, variances);
|
debug!("id={} variances={:?}", id, variances);
|
||||||
|
|
||||||
// Functions can have unused type parameters: make those invariant.
|
// Const parameters are always invariant.
|
||||||
|
for (idx, param) in generics.params.iter().enumerate() {
|
||||||
|
if let ty::GenericParamDefKind::Const = param.kind {
|
||||||
|
variances[idx] = ty::Invariant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions are permitted to have unused generic parameters: make those invariant.
|
||||||
if let ty::FnDef(..) = tcx.type_of(def_id).sty {
|
if let ty::FnDef(..) = tcx.type_of(def_id).sty {
|
||||||
for variance in &mut variances {
|
for variance in &mut variances {
|
||||||
if *variance == ty::Bivariant {
|
if *variance == ty::Bivariant {
|
||||||
|
|
|
@ -119,7 +119,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
||||||
// for a particular item are assigned continuous indices.
|
// for a particular item are assigned continuous indices.
|
||||||
|
|
||||||
let arena = self.arena;
|
let arena = self.arena;
|
||||||
self.inferred_terms.extend((start..start+count).map(|i| {
|
self.inferred_terms.extend((start..(start + count)).map(|i| {
|
||||||
&*arena.alloc(InferredTerm(InferredIndex(i)))
|
&*arena.alloc(InferredTerm(InferredIndex(i)))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
8
src/test/ui/const-generics/unused-const-param.rs
Normal file
8
src/test/ui/const-generics/unused-const-param.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(const_generics)]
|
||||||
|
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
|
||||||
|
struct A<const N: usize>; // ok
|
||||||
|
|
||||||
|
fn main() {}
|
6
src/test/ui/const-generics/unused-const-param.stderr
Normal file
6
src/test/ui/const-generics/unused-const-param.stderr
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
--> $DIR/unused-const-param.rs:3:12
|
||||||
|
|
|
||||||
|
LL | #![feature(const_generics)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue