Skip to content

Commit fb5308d

Browse files
committed
Make stability attribute not to error when unstable feature bound is in effect
1 parent a28329a commit fb5308d

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

compiler/rustc_passes/src/stability.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,22 +802,50 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
802802
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
803803
let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
804804

805+
let unstable_feature_stab =
806+
find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i)
807+
.map(|i| i.as_slice())
808+
.unwrap_or_default();
809+
805810
// If this impl block has an #[unstable] attribute, give an
806811
// error if all involved types and traits are stable, because
807812
// it will have no effect.
808813
// See: https://github.com/rust-lang/rust/issues/55436
814+
//
815+
// The exception is when there are both #[unstable_feature_bound(..)] and
816+
// #![unstable(feature = "..", issue = "..")] that have the same symbol because
817+
// that can effectively mark an impl as unstable.
818+
//
819+
// For example:
820+
// ```
821+
// #[unstable_feature_bound(feat_foo)]
822+
// #[unstable(feature = "feat_foo", issue = "none")]
823+
// impl Foo for Bar {}
824+
// ```
809825
if let Some((
810-
Stability { level: attrs::StabilityLevel::Unstable { .. }, .. },
826+
Stability { level: attrs::StabilityLevel::Unstable { .. }, feature },
811827
span,
812828
)) = stab
813829
{
814830
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
815831
c.visit_ty_unambig(self_ty);
816832
c.visit_trait_ref(t);
817833

834+
// Skip the lint if the impl is marked as unstable using
835+
// #[unstable_feature_bound(..)]
836+
let mut unstable_feature_bound_in_effect = false;
837+
for (unstable_bound_feat_name, _) in unstable_feature_stab {
838+
if *unstable_bound_feat_name == feature {
839+
unstable_feature_bound_in_effect = true;
840+
}
841+
}
842+
818843
// do not lint when the trait isn't resolved, since resolution error should
819844
// be fixed first
820-
if t.path.res != Res::Err && c.fully_stable {
845+
if t.path.res != Res::Err
846+
&& c.fully_stable
847+
&& !unstable_feature_bound_in_effect
848+
{
821849
self.tcx.emit_node_span_lint(
822850
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
823851
item.hir_id(),
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#![allow(internal_features)]
2+
//~^ ERROR: module has missing stability attribute
3+
#![feature(staged_api)]
4+
#![allow(dead_code)]
5+
6+
/// If #[unstable(..)] and #[unstable_feature_name(..)] have the same feature name,
7+
/// the error should not be thrown as it can effectively mark an impl as unstable.
8+
///
9+
/// If the feature name in #[feature] does not exist in #[unstable_feature_bound(..)]
10+
/// an error should still be thrown because that feature will not be unstable.
11+
12+
#[stable(feature = "a", since = "1.1.1" )]
13+
trait Moo {}
14+
#[stable(feature = "a", since = "1.1.1" )]
15+
trait Foo {}
16+
#[stable(feature = "a", since = "1.1.1" )]
17+
trait Boo {}
18+
#[stable(feature = "a", since = "1.1.1" )]
19+
pub struct Bar;
20+
21+
22+
#[unstable(feature = "feat_moo", issue = "none" )]
23+
#[unstable_feature_bound(feat_foo)] //~^ ERROR: an `#[unstable]` annotation here has no effect
24+
impl Moo for Bar {}
25+
26+
#[unstable(feature = "feat_foo", issue = "none" )]
27+
#[unstable_feature_bound(feat_foo)]
28+
impl Foo for Bar {}
29+
30+
31+
#[unstable(feature = "feat_foo", issue = "none" )]
32+
#[unstable_feature_bound(feat_foo, feat_bar)]
33+
impl Boo for Bar {}
34+
35+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: an `#[unstable]` annotation here has no effect
2+
--> $DIR/unstable-feature-bound-no-effect.rs:22:1
3+
|
4+
LL | #[unstable(feature = "feat_moo", issue = "none" )]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
8+
= note: `#[deny(ineffective_unstable_trait_impl)]` on by default
9+
10+
error: module has missing stability attribute
11+
--> $DIR/unstable-feature-bound-no-effect.rs:1:1
12+
|
13+
LL | / #![allow(internal_features)]
14+
LL | |
15+
LL | | #![feature(staged_api)]
16+
LL | | #![allow(dead_code)]
17+
... |
18+
LL | | fn main() {}
19+
| |____________^
20+
21+
error: aborting due to 2 previous errors
22+

0 commit comments

Comments
 (0)