diff options
| author | bors <bors@rust-lang.org> | 2020-09-14 04:07:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-09-14 04:07:08 +0000 |
| commit | 56d8a933b3a344aa8980a17e2dbf338c177178fc (patch) | |
| tree | 7d89bab8ef1e4f4a80c167087fca199dbd2f62df | |
| parent | 0b65a3d0a6a3ae8d1f35d95f18210f894a1d6c98 (diff) | |
| parent | 90dd798cf53320b3478119d06d2d8c47880c9247 (diff) | |
| download | rust-56d8a933b3a344aa8980a17e2dbf338c177178fc.tar.gz rust-56d8a933b3a344aa8980a17e2dbf338c177178fc.zip | |
Auto merge of #76195 - lcnr:const-Self, r=varkor
allow concrete self types in consts This is quite a bad hack to fix #75486. There might be a better way to check if the self type depends on generic parameters, but I wasn't able to come up with one. r? `@varkor` cc `@petrochenkov`
| -rw-r--r-- | compiler/rustc_hir/src/def.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/astconv/mod.rs | 23 | ||||
| -rw-r--r-- | src/librustdoc/clean/utils.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/const-generics/issues/issue-62504.min.stderr | 10 | ||||
| -rw-r--r-- | src/test/ui/const-generics/issues/issue-62504.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr | 22 | ||||
| -rw-r--r-- | src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr | 14 |
13 files changed, 146 insertions, 20 deletions
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index b019e518d0c..96fde48d96c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -199,7 +199,16 @@ pub enum Res<Id = hir::HirId> { // Type namespace PrimTy(hir::PrimTy), - SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */), + /// `Self`, with both an optional trait and impl `DefId`. + /// + /// HACK(min_const_generics): impl self types also have an optional requirement to not mention + /// any generic parameters to allow the following with `min_const_generics`: + /// ```rust + /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] {} } + /// ``` + /// + /// FIXME(lazy_normalization_consts): Remove this bodge once this feature is stable. + SelfTy(Option<DefId> /* trait */, Option<(DefId, bool)> /* impl */), ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` // Value namespace diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c79542342ba..fe6653e98da 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -104,7 +104,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(t) = t { self.check_def_id(t); } - if let Some(i) = i { + if let Some((i, _)) = i { self.check_def_id(i); } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7a0503d68f3..b80da641491 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -112,7 +112,7 @@ impl<'a> Resolver<'a> { match outer_res { Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => { if let Some(impl_span) = - maybe_impl_defid.and_then(|def_id| self.opt_span(def_id)) + maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id)) { err.span_label( reduce_impl_span_to_impl_keyword(sm, impl_span), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 07f36c7b7ad..6788df9be78 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -110,6 +110,9 @@ crate enum RibKind<'a> { ItemRibKind(HasGenericParams), /// We're in a constant item. Can't refer to dynamic stuff. + /// + /// The `bool` indicates if this constant may reference generic parameters + /// and is used to only allow generic parameters to be used in trivial constant expressions. ConstantItemRibKind(bool), /// We passed through a module. @@ -848,7 +851,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.with_current_self_item(item, |this| { this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { let item_def_id = this.r.local_def_id(item.id).to_def_id(); - this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| { + this.with_self_rib(Res::SelfTy(None, Some((item_def_id, false))), |this| { visit::walk_item(this, item); }); }); @@ -1215,7 +1218,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { let item_def_id = this.r.local_def_id(item_id).to_def_id(); - this.with_self_rib(Res::SelfTy(trait_id, Some(item_def_id)), |this| { + this.with_self_rib(Res::SelfTy(trait_id, Some((item_def_id, false))), |this| { if let Some(trait_ref) = opt_trait_reference.as_ref() { // Resolve type arguments in the trait path. visit::walk_trait_ref(this, trait_ref); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0f5b9b51816..00a37d908cd 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2539,7 +2539,7 @@ impl<'a> Resolver<'a> { &mut self, rib_index: usize, rib_ident: Ident, - res: Res, + mut res: Res, record_used: bool, span: Span, all_ribs: &[Rib<'a>], @@ -2629,13 +2629,22 @@ impl<'a> Resolver<'a> { ConstantItemRibKind(trivial) => { // HACK(min_const_generics): We currently only allow `N` or `{ N }`. if !trivial && self.session.features_untracked().min_const_generics { - if record_used { - self.report_error( - span, - ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name), - ); + // HACK(min_const_generics): If we encounter `Self` in an anonymous constant + // we can't easily tell if it's generic at this stage, so we instead remember + // this and then enforce the self type to be concrete later on. + if let Res::SelfTy(trait_def, Some((impl_def, _))) = res { + res = Res::SelfTy(trait_def, Some((impl_def, true))); + } else { + if record_used { + self.report_error( + span, + ResolutionError::ParamInNonTrivialAnonConst( + rib_ident.name, + ), + ); + } + return Res::Err; } - return Res::Err; } if in_ty_param_default { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 9e339b1082c..a743dc1cd20 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1460,7 +1460,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Find the type of the associated item, and the trait where the associated // item is declared. let bound = match (&qself_ty.kind(), qself_res) { - (_, Res::SelfTy(Some(_), Some(impl_def_id))) => { + (_, Res::SelfTy(Some(_), Some((impl_def_id, _)))) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. let trait_ref = match tcx.impl_trait_ref(impl_def_id) { @@ -1917,12 +1917,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.prohibit_generics(path.segments); tcx.types.self_param } - Res::SelfTy(_, Some(def_id)) => { + Res::SelfTy(_, Some((def_id, forbid_generic))) => { // `Self` in impl (we know the concrete type). assert_eq!(opt_self_ty, None); self.prohibit_generics(path.segments); // Try to evaluate any array length constants. - self.normalize_ty(span, tcx.at(span).type_of(def_id)) + let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id)); + if forbid_generic && normalized_ty.needs_subst() { + let mut err = tcx.sess.struct_span_err( + path.span, + "generic `Self` types are currently not permitted in anonymous constants", + ); + if let Some(hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Impl { self_ty, .. }, + .. + })) = tcx.hir().get_if_local(def_id) + { + err.span_note(self_ty.span, "not a concrete type"); + } + err.emit(); + tcx.ty_error() + } else { + normalized_ty + } } Res::Def(DefKind::AssocTy, def_id) => { debug_assert!(path.segments.len() >= 2); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index c577b771d60..58b76d24a5b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -601,7 +601,7 @@ pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { }, Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias), Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), - Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id, + Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id, _ => return res.def_id(), }; if did.is_local() { diff --git a/src/test/ui/const-generics/issues/issue-62504.min.stderr b/src/test/ui/const-generics/issues/issue-62504.min.stderr index 752df17aad6..8f794312834 100644 --- a/src/test/ui/const-generics/issues/issue-62504.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.min.stderr @@ -1,10 +1,14 @@ -error: generic parameters must not be used inside of non trivial constant values +error: generic `Self` types are currently not permitted in anonymous constants --> $DIR/issue-62504.rs:19:25 | LL | ArrayHolder([0; Self::SIZE]) - | ^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self` + | ^^^^^^^^^^ | - = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants +note: not a concrete type + --> $DIR/issue-62504.rs:17:22 + | +LL | impl<const X: usize> ArrayHolder<X> { + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index b520dbe4e80..015f170f00d 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -18,7 +18,7 @@ impl<const X: usize> ArrayHolder<X> { pub const fn new() -> Self { ArrayHolder([0; Self::SIZE]) //[full]~^ ERROR constant expression depends on a generic parameter - //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values + //[min]~^^ ERROR generic `Self` types are currently } } diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs new file mode 100644 index 00000000000..0973b373c12 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs @@ -0,0 +1,27 @@ +#![feature(min_const_generics)] + +trait Foo { + fn t1() -> [u8; std::mem::size_of::<Self>()]; //~ERROR generic parameters +} + +struct Bar<T>(T); + +impl Bar<u8> { + fn t2() -> [u8; std::mem::size_of::<Self>()] { todo!() } // ok +} + +impl<T> Bar<T> { + fn t3() -> [u8; std::mem::size_of::<Self>()] {} //~ERROR generic `Self` +} + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; // ok + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr new file mode 100644 index 00000000000..89ce58564e4 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -0,0 +1,22 @@ +error: generic parameters must not be used inside of non trivial constant values + --> $DIR/self-ty-in-const-1.rs:4:41 + | +LL | fn t1() -> [u8; std::mem::size_of::<Self>()]; + | ^^^^ non-trivial anonymous constants must not depend on the parameter `Self` + | + = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-1.rs:14:41 + | +LL | fn t3() -> [u8; std::mem::size_of::<Self>()] {} + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-1.rs:13:9 + | +LL | impl<T> Bar<T> { + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs new file mode 100644 index 00000000000..e7f80d50082 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs @@ -0,0 +1,21 @@ +#![feature(min_const_generics)] + +struct Bar<T>(T); + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; // ok + } +} + +impl<T> Baz for Bar<T> { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; //~ERROR generic `Self` + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr new file mode 100644 index 00000000000..9ac6410a290 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-2.rs:17:41 + | +LL | let _: [u8; std::mem::size_of::<Self>()]; + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-2.rs:15:17 + | +LL | impl<T> Baz for Bar<T> { + | ^^^^^^ + +error: aborting due to previous error + |
