about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2022-02-22 14:54:47 -0500
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-05-19 12:21:45 +0000
commit5ff331142e03bede7f9c8264b8625caf6b65989c (patch)
tree91b68c412532abe12f3cbd4e0a47f915db4b887f
parentf0620c95038c1e586f5165d5d3be7cf009aaf387 (diff)
downloadrust-5ff331142e03bede7f9c8264b8625caf6b65989c.tar.gz
rust-5ff331142e03bede7f9c8264b8625caf6b65989c.zip
Move check to existing pass
This alters the diagnostics a bit, as the trait method is still stable.
The only thing this check does is ensure that compilation fails if a
trait implementation is declared const-stable.
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_passes/src/stability.rs82
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/stability.rs43
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/stability.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.rs24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr26
7 files changed, 62 insertions, 158 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 7a6ab62ef67..00119267e85 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -970,10 +970,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
 
     sess.time("layout_testing", || layout_test::test_layout(tcx));
 
-    sess.time("stable_impl_const_trait_checking", || {
-        rustc_passes::stability::check_const_impl_trait(tcx)
-    });
-
     // Avoid overwhelming user with errors if borrow checking failed.
     // I'm not sure how helpful this is, to be honest, but it avoids a
     // lot of annoying errors in the ui tests (basically,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 7b8ffeaac24..8f8f677cad4 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -9,7 +9,6 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::AccessLevels;
@@ -606,44 +605,6 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
     // stable (assuming they have not inherited instability from their parent).
 }
 
-struct CheckStableConstImplTrait<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for CheckStableConstImplTrait<'tcx> {
-    fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
-        if !matches!(
-            item.kind,
-            hir::ItemKind::Impl(hir::Impl {
-                of_trait: Some(_),
-                constness: hir::Constness::Const,
-                ..
-            })
-        ) {
-            return;
-        }
-
-        if self.tcx.lookup_const_stability(item.def_id).map_or(false, |stab| stab.is_const_stable())
-        {
-            self.tcx
-                .sess
-                .struct_span_err(item.span, "trait implementations cannot be const stable yet")
-                .note("see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information")
-                .emit();
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {
-        // Nothing to do here.
-    }
-    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {
-        // Nothing to do here.
-    }
-    fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {
-        // Nothing to do here.
-    }
-}
-
 fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
     let mut index = Index {
         stab_map: Default::default(),
@@ -748,16 +709,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
-                if self.tcx.features().staged_api {
+            hir::ItemKind::Impl(hir::Impl {
+                of_trait: Some(ref t),
+                self_ty,
+                items,
+                constness,
+                ..
+            }) => {
+                let features = self.tcx.features();
+                if features.staged_api {
+                    let attrs = self.tcx.hir().attrs(item.hir_id());
+                    let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item.span);
+
                     // If this impl block has an #[unstable] attribute, give an
                     // error if all involved types and traits are stable, because
                     // it will have no effect.
                     // See: https://github.com/rust-lang/rust/issues/55436
-                    let attrs = self.tcx.hir().attrs(item.hir_id());
-                    if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) =
-                        attr::find_stability(&self.tcx.sess, attrs, item.span)
-                    {
+                    if let Some((Stability { level: attr::Unstable { .. }, .. }, span)) = stab {
                         let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
                         c.visit_ty(self_ty);
                         c.visit_trait_ref(t);
@@ -773,6 +741,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
                             );
                         }
                     }
+
+                    // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
+                    // needs to have an error emitted.
+                    if features.const_trait_impl
+                        && constness == hir::Constness::Const
+                        && const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
+                    {
+                        self.tcx
+                            .sess
+                            .struct_span_err(item.span, "trait implementations cannot be const stable yet")
+                            .note("see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information")
+                            .emit();
+                    }
                 }
 
                 for impl_item_ref in *items {
@@ -864,17 +845,6 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
     }
 }
 
-pub fn check_const_impl_trait(tcx: TyCtxt<'_>) {
-    let features = tcx.features(); // FIXME How cheap is this call?
-    // Both feature gates have to be enabled for this check to have any effect.
-    if !features.staged_api || !features.const_trait_impl {
-        return;
-    }
-
-    let mut visitor = CheckStableConstImplTrait { tcx };
-    tcx.hir().visit_all_item_likes(&mut visitor);
-}
-
 /// Given the list of enabled features that were not language features (i.e., that
 /// were expected to be library features), and the list of features used from
 /// libraries, identify activated features that don't exist and error about them.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs
deleted file mode 100644
index 15f1db18f89..00000000000
--- a/src/test/ui/rfc-2632-const-trait-impl/stability.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-#![feature(const_trait_impl)]
-#![feature(staged_api)]
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Int(i32);
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
-impl const std::ops::Sub for Int {
-    //~^ ERROR trait implementations cannot be const stable yet
-    type Output = Self;
-
-    fn sub(self, rhs: Self) -> Self {
-        Int(self.0 - rhs.0)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_add", issue = "none")]
-impl const std::ops::Add for Int {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        Int(self.0 + rhs.0)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
-pub const fn const_err() {
-    Int(0) + Int(0);
-    //~^ ERROR not yet stable as a const fn
-    Int(0) - Int(0);
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn non_const_success() {
-    Int(0) + Int(0);
-    Int(0) - Int(0);
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr
deleted file mode 100644
index fa3d85a3e6a..00000000000
--- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error: `<Int as Add>::add` is not yet stable as a const fn
-  --> $DIR/stability.rs:32:5
-   |
-LL |     Int(0) + Int(0);
-   |     ^^^^^^^^^^^^^^^
-   |
-   = help: const-stable functions can only call other const-stable functions
-
-error: trait implementations cannot be const stable yet
-  --> $DIR/stability.rs:10:1
-   |
-LL | / impl const std::ops::Sub for Int {
-LL | |
-LL | |     type Output = Self;
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^
-   |
-   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
index 903ced42698..f8a55a0a4a0 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
@@ -11,26 +11,36 @@ extern crate staged_api;
 use staged_api::*;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Stable;
+pub struct Foo;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stable, rustc_const_stable(feature = "rust1", since = "1.0.0"))]
-impl const MyTrait for Stable {
+#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+impl const MyTrait for Foo {
     //[stable]~^ ERROR trait implementations cannot be const stable yet
-    //[unstable]~^^ ERROR implementation has missing const stability attribute
     fn func() {}
 }
 
+// Const stability has no impact on usage in non-const contexts.
 fn non_const_context() {
     Unstable::func();
-    Stable::func();
+    Foo::func();
 }
 
 #[unstable(feature = "none", issue = "none")]
 const fn const_context() {
     Unstable::func();
-    //[stable]~^ ERROR `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-    Stable::func();
+    // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+    // not const-stable.
+    Foo::func();
+    //[unstable]~^ not yet stable as a const fn
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+const fn stable_const_context() {
+    Unstable::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
+    Foo::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
index 2fde51217f5..25407a0b43c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
@@ -1,22 +1,11 @@
-error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:31:5
-   |
-LL |     Unstable::func();
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-
-error: trait implementations cannot be const stable yet
+error: implementation has missing const stability attribute
   --> $DIR/staged-api.rs:18:1
    |
-LL | / impl const MyTrait for Stable {
-LL | |
+LL | / impl const MyTrait for Foo {
 LL | |
 LL | |     fn func() {}
 LL | | }
    | |_^
-   |
-   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
index 4ea1be69b3b..30fe97bb884 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
@@ -1,12 +1,18 @@
-error: implementation has missing const stability attribute
-  --> $DIR/staged-api.rs:18:1
-   |
-LL | / impl const MyTrait for Stable {
-LL | |
-LL | |
-LL | |     fn func() {}
-LL | | }
-   | |_^
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:34:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:42:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors