From 04243e3c4f19bc7f7a8c0237943130a4e815da58 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 7 Jan 2020 23:45:54 +0000 Subject: [PATCH 01/14] Various cleanup on stability code --- src/librustc/middle/privacy.rs | 2 +- src/librustc_passes/reachable.rs | 2 +- src/librustc_passes/stability.rs | 27 +++++++++++++----------- src/test/ui/missing/missing-stability.rs | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 4756e83b5e980..6fe633eab295d 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -12,7 +12,7 @@ use std::hash::Hash; // Accessibility levels, sorted in ascending order #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, HashStable)] pub enum AccessLevel { - /// Superset of `AccessLevel::Reachable` used to mark impl Trait items. + /// Superset of `AccessLevel::Reachable` used to mark `impl Trait` items. ReachableFromImplTrait, /// Exported items + items participating in various kinds of public interfaces, /// but not directly nameable. For example, if function `fn f() -> T {...}` is diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 667898046ac36..4cb7b50c3bba9 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -303,7 +303,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => { self.visit_nested_body(body); } - // Nothing to recurse on for these + // Nothing to recurse on for these. Node::ForeignItem(_) | Node::Variant(_) | Node::Ctor(..) diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 320b433190e5e..6756b4970399c 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -28,15 +28,15 @@ use std::num::NonZeroU32; #[derive(PartialEq)] enum AnnotationKind { - // Annotation is required if not inherited from unstable parents + // Annotation is required if not inherited from unstable parents. Required, - // Annotation is useless, reject it + // Annotation is useless: reject it. Prohibited, - // Annotation itself is useless, but it can be propagated to children + // Annotation itself is useless, but it can be propagated to children. Container, } -// A private tree-walker for producing an Index. +// A private tree-walker for producing an index. struct Annotator<'a, 'tcx> { tcx: TyCtxt<'tcx>, index: &'a mut Index<'tcx>, @@ -65,7 +65,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { self.tcx.sess.span_err( item_sp, "`#[deprecated]` cannot be used in staged API; \ - use `#[rustc_deprecated]` instead", + use `#[rustc_deprecated]` instead", ); } let (stab, const_stab) = @@ -81,7 +81,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { && stab.level.is_stable() && stab.rustc_depr.is_none()) { - self.tcx.sess.span_err(item_sp, "This stability annotation is useless"); + self.tcx.sess.span_err(item_sp, "item does not require a stability annotation"); } debug!("annotate: found {:?}", stab); @@ -102,7 +102,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { &attr::Stable { since: stab_since }, ) = (&stab.rustc_depr, &stab.level) { - // Explicit version of iter::order::lt to handle parse errors properly + // Explicit version of `iter::order::lt` to handle parse errors properly. for (dep_v, stab_v) in dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) { @@ -111,8 +111,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { Ordering::Less => { self.tcx.sess.span_err( item_sp, - "An API can't be stabilized \ - after it is deprecated", + "an API cannot be stabilized after it has been deprecated", ); break; } @@ -124,8 +123,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // and this makes us not do anything else interesting. self.tcx.sess.span_err( item_sp, - "Invalid stability or deprecation \ - version found", + "item has an invalid stability or deprecation version", ); break; } @@ -140,6 +138,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } else { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { + // Instability (but not stability) is inherited from the parent. + // If something is unstable, everything inside it should also be + // considered unstable. if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } @@ -179,7 +180,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { if kind == AnnotationKind::Prohibited { - self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); + self.tcx + .sess + .span_err(item_sp, "item does not require a deprecation annotation"); } // `Deprecation` is just two pointers, no need to intern it diff --git a/src/test/ui/missing/missing-stability.rs b/src/test/ui/missing/missing-stability.rs index 0da5808b47dc2..a47c0849b4ef0 100644 --- a/src/test/ui/missing/missing-stability.rs +++ b/src/test/ui/missing/missing-stability.rs @@ -16,7 +16,7 @@ pub mod foo { pub fn unmarked() {} } -#[stable(feature = "stable_test_feature", since="1.0.0")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] pub mod bar { // #[stable] is not inherited pub fn unmarked() {} From 109d416e80877355eb4fc1873a5e8c7fb8681e7a Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 7 Jan 2020 23:46:46 +0000 Subject: [PATCH 02/14] Permit and require stability attributes on default type parameters Co-Authored-By: Avi Dessauer --- src/librustc_passes/reachable.rs | 1 + src/librustc_passes/stability.rs | 25 +++++++++++++++++++++++++ src/librustc_privacy/lib.rs | 14 ++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 4cb7b50c3bba9..296a9b1743851 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -309,6 +309,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { | Node::Ctor(..) | Node::Field(_) | Node::Ty(_) + | Node::GenericParam(_) | Node::MacroDef(_) => {} _ => { bug!( diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 6756b4970399c..8a2b53ee30bfc 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -278,6 +278,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { self.annotate(md.hir_id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + let kind = match &p.kind { + // FIXME(const_generics:defaults) + hir::GenericParamKind::Type { default, .. } if default.is_some() => { + AnnotationKind::Required + } + _ => AnnotationKind::Prohibited, + }; + + self.annotate(p.hir_id, &p.attrs, p.span, kind, |v| { + intravisit::walk_generic_param(v, p); + }); + } } struct MissingStabilityAnnotations<'a, 'tcx> { @@ -348,6 +362,17 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { self.check_missing_stability(md.hir_id, md.span, "macro"); } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + match &p.kind { + // FIXME(const_generics:defaults) + hir::GenericParamKind::Type { default, .. } if default.is_some() => { + self.check_missing_stability(p.hir_id, p.span, "default type parameter"); + } + _ => {} + } + intravisit::walk_generic_param(self, p); + } } fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 60bf271d2d2a8..cf8fc73e68c1e 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -946,6 +946,20 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { module_id = self.tcx.hir().get_parent_node(module_id); } } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + // Generic parameters cannot be directly accessed by users, so restricting privacy is + // unimportant here. + // However, parameters must be (at least) `Reachable` in order for stability requirements to + // be enforced (see `check_missing_stability` in `src/librustc_passes/stability.rs`). + match &p.kind { + // FIXME(const_generics:defaults) + hir::GenericParamKind::Type { default, .. } if default.is_some() => { + self.update(p.hir_id, Some(AccessLevel::Reachable)); + } + _ => {} + } + } } impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { From 1519c0a469067a25d0747bbf1e0660d0b422b42a Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 8 Jan 2020 00:02:51 +0000 Subject: [PATCH 03/14] Fix typo in diagnostic --- src/librustc_typeck/collect.rs | 2 +- .../feature-gate-default_type_parameter_fallback.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5821977391b0a..d9bc08794d183 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1155,7 +1155,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { param.span, &format!( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions." + `struct`, `enum`, `type`, or `trait` definitions" ), ); } diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr index f13803b80f308..5cd38ebab370e 100644 --- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr @@ -1,4 +1,4 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 | LL | fn avg(_: T) {} @@ -8,7 +8,7 @@ LL | fn avg(_: T) {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #36887 -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 | LL | impl S {} From 20cfb5902ce412575caa49d6a3edaf12742b8be6 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 8 Jan 2020 00:03:33 +0000 Subject: [PATCH 04/14] Make default type parameter stability optional Co-Authored-By: Avi Dessauer --- src/librustc_passes/reachable.rs | 1 - src/librustc_passes/stability.rs | 23 ++++++++--------------- src/librustc_privacy/lib.rs | 14 -------------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 296a9b1743851..4cb7b50c3bba9 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -309,7 +309,6 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { | Node::Ctor(..) | Node::Field(_) | Node::Ty(_) - | Node::GenericParam(_) | Node::MacroDef(_) => {} _ => { bug!( diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 8a2b53ee30bfc..ccc569f48988c 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -32,8 +32,8 @@ enum AnnotationKind { Required, // Annotation is useless: reject it. Prohibited, - // Annotation itself is useless, but it can be propagated to children. - Container, + // Annotation is optional. Stability can be propagated to children. + Optional, } // A private tree-walker for producing an index. @@ -77,7 +77,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if let Some(mut stab) = stab { // Error if prohibited, or can't inherit anything from a container. if kind == AnnotationKind::Prohibited - || (kind == AnnotationKind::Container + || (kind == AnnotationKind::Optional && stab.level.is_stable() && stab.rustc_depr.is_none()) { @@ -222,7 +222,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { // optional. They inherit stability from their parents when unannotated. hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => { self.in_trait_impl = false; - kind = AnnotationKind::Container; + kind = AnnotationKind::Optional; } hir::ItemKind::Impl { of_trait: Some(_), .. } => { self.in_trait_impl = true; @@ -283,7 +283,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { let kind = match &p.kind { // FIXME(const_generics:defaults) hir::GenericParamKind::Type { default, .. } if default.is_some() => { - AnnotationKind::Required + AnnotationKind::Optional } _ => AnnotationKind::Prohibited, }; @@ -363,16 +363,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { self.check_missing_stability(md.hir_id, md.span, "macro"); } - fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { - match &p.kind { - // FIXME(const_generics:defaults) - hir::GenericParamKind::Type { default, .. } if default.is_some() => { - self.check_missing_stability(p.hir_id, p.span, "default type parameter"); - } - _ => {} - } - intravisit::walk_generic_param(self, p); - } + // Note that we don't need to `check_missing_stability` for default generic parameters, + // as we assume that any default generic parameters without attributes are automatically + // stable (assuming they have not inherited instability from their parent). } fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cf8fc73e68c1e..60bf271d2d2a8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -946,20 +946,6 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { module_id = self.tcx.hir().get_parent_node(module_id); } } - - fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { - // Generic parameters cannot be directly accessed by users, so restricting privacy is - // unimportant here. - // However, parameters must be (at least) `Reachable` in order for stability requirements to - // be enforced (see `check_missing_stability` in `src/librustc_passes/stability.rs`). - match &p.kind { - // FIXME(const_generics:defaults) - hir::GenericParamKind::Type { default, .. } if default.is_some() => { - self.update(p.hir_id, Some(AccessLevel::Reachable)); - } - _ => {} - } - } } impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { From 4f27d22f3cb3d2d5985d12e94d889d7d62df37c1 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 8 Jan 2020 02:36:50 +0000 Subject: [PATCH 05/14] Initial stability checking on default type parameters Co-Authored-By: Avi Dessauer --- src/librustc_passes/stability.rs | 9 ++++++--- src/librustc_typeck/astconv.rs | 6 +++++- .../auxiliary/unstable_generic_param.rs | 10 ++++++++++ .../generics-default-stability.rs | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs create mode 100644 src/test/ui/stability-attribute/generics-default-stability.rs diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index ccc569f48988c..949cecf8b4f09 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -138,10 +138,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } else { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { - // Instability (but not stability) is inherited from the parent. + // Instability (but not typically stability) is inherited from the parent. // If something is unstable, everything inside it should also be // considered unstable. - if stab.level.is_unstable() { + // `AnnotationKind::Optional` items also inherit stability, as they may be + // considered stable-by-default items, requiring an instability attribute to + // override this. + if stab.level.is_unstable() || kind == AnnotationKind::Optional { self.index.stab_map.insert(hir_id, stab); } } @@ -173,7 +176,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Propagate unstability. This can happen even for non-staged-api crates in case // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { - if stab.level.is_unstable() { + if stab.level.is_unstable() || kind == AnnotationKind::Optional { self.index.stab_map.insert(hir_id, stab); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 89eeed8d11ebc..c8521c94f2f5d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -697,7 +697,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { self.ast_region_to_region(<, Some(param)).into() } - (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { + (GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { + if *has_default { + tcx.check_stability(param.def_id, Some(arg.id()), arg.span()); + } + self.ast_ty_to_ty(&ty).into() } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { diff --git a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs new file mode 100644 index 0000000000000..42a1d584cf36b --- /dev/null +++ b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] +#![feature(staged_api)] + +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait<#[unstable(feature = "ty", issue = "none")] T = ()> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} diff --git a/src/test/ui/stability-attribute/generics-default-stability.rs b/src/test/ui/stability-attribute/generics-default-stability.rs new file mode 100644 index 0000000000000..760146cddafae --- /dev/null +++ b/src/test/ui/stability-attribute/generics-default-stability.rs @@ -0,0 +1,15 @@ +// aux-build:unstable_generic_param.rs + +extern crate unstable_generic_param; + +use unstable_generic_param::Trait; + +struct S; + +impl Trait for S { + fn foo() -> usize { 0 } +} + +fn main() { + let _ = S; +} From f5edbe96c154c0dcc876d1696d68e5348a1f4740 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 8 Jan 2020 16:39:15 +0000 Subject: [PATCH 06/14] Encode stability for default generic parameters --- src/librustc_metadata/rmeta/encoder.rs | 4 ++++ src/librustc_passes/stability.rs | 13 +++++-------- .../auxiliary/unstable_generic_param.rs | 8 +++++++- .../generics-default-stability.rs | 14 ++++++++++++-- .../generics-default-stability.stderr | 11 +++++++++++ 5 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/stability-attribute/generics-default-stability.stderr diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 9d2bea28c8c2e..f489d9f0c0ec3 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1579,9 +1579,13 @@ impl EncodeContext<'tcx> { EntryKind::TypeParam, default.is_some(), ); + if default.is_some() { + self.encode_stability(def_id); + } } GenericParamKind::Const { .. } => { self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); + // FIXME(const_generics:defaults) } } } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 949cecf8b4f09..dd915a9470f3c 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -138,13 +138,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } else { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { - // Instability (but not typically stability) is inherited from the parent. - // If something is unstable, everything inside it should also be - // considered unstable. - // `AnnotationKind::Optional` items also inherit stability, as they may be - // considered stable-by-default items, requiring an instability attribute to - // override this. - if stab.level.is_unstable() || kind == AnnotationKind::Optional { + // Instability is inherited from the parent: if something is unstable, + // everything inside it should also be considered unstable for the same + // reason. + if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } @@ -176,7 +173,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Propagate unstability. This can happen even for non-staged-api crates in case // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { - if stab.level.is_unstable() || kind == AnnotationKind::Optional { + if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } diff --git a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs index 42a1d584cf36b..4807c486f13ca 100644 --- a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs +++ b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs @@ -4,7 +4,13 @@ #![stable(feature = "stable_test_feature", since = "1.0.0")] #[stable(feature = "stable_test_feature", since = "1.0.0")] -pub trait Trait<#[unstable(feature = "ty", issue = "none")] T = ()> { +pub trait Trait1<#[unstable(feature = "unstable_default", issue = "none")] T = ()> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait2 { #[stable(feature = "stable_test_feature", since = "1.0.0")] fn foo() -> T; } diff --git a/src/test/ui/stability-attribute/generics-default-stability.rs b/src/test/ui/stability-attribute/generics-default-stability.rs index 760146cddafae..8a8ee90dc00e6 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.rs +++ b/src/test/ui/stability-attribute/generics-default-stability.rs @@ -2,14 +2,24 @@ extern crate unstable_generic_param; -use unstable_generic_param::Trait; +use unstable_generic_param::{Trait1, Trait2}; + +struct R; + +impl Trait1 for S { + fn foo() -> () { () } // ok +} struct S; -impl Trait for S { +impl Trait1 for S { //~ ERROR use of unstable library feature 'unstable_default' fn foo() -> usize { 0 } } +impl Trait2 for S { + fn foo() -> usize { 0 } // ok +} + fn main() { let _ = S; } diff --git a/src/test/ui/stability-attribute/generics-default-stability.stderr b/src/test/ui/stability-attribute/generics-default-stability.stderr new file mode 100644 index 0000000000000..fb6deb7f477e4 --- /dev/null +++ b/src/test/ui/stability-attribute/generics-default-stability.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:15:13 + | +LL | impl Trait1 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 6233993a8df9886816a19f061b48897dcfa8f1e7 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 8 Jan 2020 16:47:26 +0000 Subject: [PATCH 07/14] Add a comment explaining how to go about handling stability attribute on a new node --- src/librustc_passes/stability.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index dd915a9470f3c..a9c9e0a62efdb 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -26,6 +26,20 @@ use std::cmp::Ordering; use std::mem::replace; use std::num::NonZeroU32; +/// *** Adding stability attributes to a new kind of node *** +/// +/// 1. In ``, visit the node and call `self.annotate` to record the new +/// stability attribute. This will also do some validity checking for the attributes. +/// 2. If stability attributes should be required, visit the node in +/// `` and call `self.check_missing_stability`. +/// 3. If using `check_missing_stability`, you'll also need to make sure the node is reachable. In +/// `ReachableContext::propagate_node` in `src/librustc_passes/reachable.rs`, make sure the node +/// is handled. Then, in `` in `src/librustc_privacy`, visit the node +/// and call `self.reach`. +/// 4. Finally, we need to make sure that stability information is recorded in crate metadata. In +/// `src/librustc_metadata/rmeta/encoder.rs`, make sure that `self.encode_stability(def_id)` is +/// called in the relevant `encode_info_for_[your node]` method. + #[derive(PartialEq)] enum AnnotationKind { // Annotation is required if not inherited from unstable parents. From 3c8f740edeffe6d622b01994be89b14c90d6784a Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Fri, 10 Jan 2020 09:01:15 -0500 Subject: [PATCH 08/14] Don't check generic parameter's parent deprecation --- src/librustc/middle/stability.rs | 34 +++++++++++++++++++---- src/librustc_typeck/astconv.rs | 7 ++++- src/librustc_typeck/check/method/probe.rs | 2 +- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 1176ffc79d26d..d0ee51fe7bd85 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -281,14 +281,21 @@ impl<'tcx> TyCtxt<'tcx> { /// If `id` is `Some(_)`, this function will also check if the item at `def_id` has been /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to /// `id`. - pub fn eval_stability(self, def_id: DefId, id: Option, span: Span) -> EvalResult { + pub fn eval_stability( + self, + def_id: DefId, + id: Option, + span: Span, + inherit_dep: bool, + ) -> EvalResult { // Deprecated attributes apply in-crate and cross-crate. if let Some(id) = id { if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) { let parent_def_id = self.hir().local_def_id(self.hir().get_parent_item(id)); - let skip = self - .lookup_deprecation_entry(parent_def_id) - .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); + let skip = !inherit_dep + || self + .lookup_deprecation_entry(parent_def_id) + .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); if !skip { let (message, lint) = @@ -386,9 +393,26 @@ impl<'tcx> TyCtxt<'tcx> { /// Additionally, this function will also check if the item is deprecated. If so, and `id` is /// not `None`, a deprecated lint attached to `id` will be emitted. pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { + self.check_stability_internal(def_id, id, span, true) + } + + /// Checks if an item is stable or error out. + /// + /// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not + /// exist, emits an error. + /// + /// Additionally when `inherit_dep` is `true`, this function will also check if the item is deprecated. If so, and `id` is + /// not `None`, a deprecated lint attached to `id` will be emitted. + pub fn check_stability_internal( + self, + def_id: DefId, + id: Option, + span: Span, + inherit_dep: bool, + ) { let soft_handler = |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg); - match self.eval_stability(def_id, id, span) { + match self.eval_stability(def_id, id, span, inherit_dep) { EvalResult::Allow => {} EvalResult::Deny { feature, reason, issue, is_soft } => { report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c8521c94f2f5d..ea2b8cf937702 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -699,7 +699,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } (GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { if *has_default { - tcx.check_stability(param.def_id, Some(arg.id()), arg.span()); + tcx.check_stability_internal( + param.def_id, + Some(arg.id()), + arg.span(), + false, + ); } self.ast_ty_to_ty(&ty).into() diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2adf125f048d0..7b306b3a461ef 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1252,7 +1252,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let Some(uc) = unstable_candidates { applicable_candidates.retain(|&(p, _)| { if let stability::EvalResult::Deny { feature, .. } = - self.tcx.eval_stability(p.item.def_id, None, self.span) + self.tcx.eval_stability(p.item.def_id, None, self.span, false) { uc.push((p, feature)); return false; From 72e4a24a00468872b4554d851c55fbbec49608d7 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Sat, 11 Jan 2020 13:22:09 -0500 Subject: [PATCH 09/14] Add inherit deprecations parameter --- src/librustc_passes/stability.rs | 47 ++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index a9c9e0a62efdb..46855cd9f6422 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -68,6 +68,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { attrs: &[Attribute], item_sp: Span, kind: AnnotationKind, + inherit_deprecation: bool, visit_children: F, ) where F: FnOnce(&mut Self), @@ -102,8 +103,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // If parent is deprecated and we're not, inherit this by merging // deprecated_since and its reason. if let Some(parent_stab) = self.parent_stab { - if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() { - stab.rustc_depr = parent_stab.rustc_depr + if inherit_deprecation + && parent_stab.rustc_depr.is_some() + && stab.rustc_depr.is_none() + { + stab.rustc_depr = parent_stab.rustc_depr.clone() } } @@ -155,7 +159,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Instability is inherited from the parent: if something is unstable, // everything inside it should also be considered unstable for the same // reason. - if stab.level.is_unstable() { + if inherit_deprecation && stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } @@ -187,7 +191,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Propagate unstability. This can happen even for non-staged-api crates in case // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { - if stab.level.is_unstable() { + if inherit_deprecation && stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } @@ -243,18 +247,25 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } hir::ItemKind::Struct(ref sd, _) => { if let Some(ctor_hir_id) = sd.ctor_hir_id() { - self.annotate(ctor_hir_id, &i.attrs, i.span, AnnotationKind::Required, |_| {}) + self.annotate( + ctor_hir_id, + &i.attrs, + i.span, + AnnotationKind::Required, + true, + |_| {}, + ) } } _ => {} } - self.annotate(i.hir_id, &i.attrs, i.span, kind, |v| intravisit::walk_item(v, i)); + self.annotate(i.hir_id, &i.attrs, i.span, kind, true, |v| intravisit::walk_item(v, i)); self.in_trait_impl = orig_in_trait_impl; } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - self.annotate(ti.hir_id, &ti.attrs, ti.span, AnnotationKind::Required, |v| { + self.annotate(ti.hir_id, &ti.attrs, ti.span, AnnotationKind::Required, true, |v| { intravisit::walk_trait_item(v, ti); }); } @@ -262,15 +273,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let kind = if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required }; - self.annotate(ii.hir_id, &ii.attrs, ii.span, kind, |v| { + self.annotate(ii.hir_id, &ii.attrs, ii.span, kind, true, |v| { intravisit::walk_impl_item(v, ii); }); } fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) { - self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required, |v| { + self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required, true, |v| { if let Some(ctor_hir_id) = var.data.ctor_hir_id() { - v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required, |_| {}); + v.annotate( + ctor_hir_id, + &var.attrs, + var.span, + AnnotationKind::Required, + true, + |_| {}, + ); } intravisit::walk_variant(v, var, g, item_id) @@ -278,19 +296,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) { - self.annotate(s.hir_id, &s.attrs, s.span, AnnotationKind::Required, |v| { + self.annotate(s.hir_id, &s.attrs, s.span, AnnotationKind::Required, true, |v| { intravisit::walk_struct_field(v, s); }); } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { - self.annotate(i.hir_id, &i.attrs, i.span, AnnotationKind::Required, |v| { + self.annotate(i.hir_id, &i.attrs, i.span, AnnotationKind::Required, true, |v| { intravisit::walk_foreign_item(v, i); }); } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - self.annotate(md.hir_id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); + self.annotate(md.hir_id, &md.attrs, md.span, AnnotationKind::Required, true, |_| {}); } fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { @@ -302,7 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { _ => AnnotationKind::Prohibited, }; - self.annotate(p.hir_id, &p.attrs, p.span, kind, |v| { + self.annotate(p.hir_id, &p.attrs, p.span, kind, false, |v| { intravisit::walk_generic_param(v, p); }); } @@ -442,6 +460,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { &krate.attrs, krate.span, AnnotationKind::Required, + true, |v| intravisit::walk_crate(v, krate), ); } From 6452165881d0b3180769bdb3f12fdc3ca33c77d8 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Sat, 11 Jan 2020 19:11:07 -0500 Subject: [PATCH 10/14] Ignore tidy filelength --- src/librustc_typeck/astconv.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ea2b8cf937702..5e89bf42cb805 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2,6 +2,7 @@ //! Conversion from AST representation of types to the `ty.rs` representation. //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. +// ignore-tidy-filelength // ignore-tidy-filelength From 57cdd3330851c874e6625be7486d6016dba1ae55 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Sun, 12 Jan 2020 16:18:33 -0500 Subject: [PATCH 11/14] Ignore unmarked generic params --- src/librustc/middle/stability.rs | 13 +++++++------ src/librustc_typeck/astconv.rs | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index d0ee51fe7bd85..fc8d8930cdf63 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -393,7 +393,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Additionally, this function will also check if the item is deprecated. If so, and `id` is /// not `None`, a deprecated lint attached to `id` will be emitted. pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { - self.check_stability_internal(def_id, id, span, true) + self.check_stability_internal(def_id, id, span, true, |span, def_id| { + // The API could be uncallable for other reasons, for example when a private module + // was referenced. + self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id)); + }) } /// Checks if an item is stable or error out. @@ -409,6 +413,7 @@ impl<'tcx> TyCtxt<'tcx> { id: Option, span: Span, inherit_dep: bool, + unmarked: impl FnOnce(Span, DefId) -> (), ) { let soft_handler = |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg); @@ -417,11 +422,7 @@ impl<'tcx> TyCtxt<'tcx> { EvalResult::Deny { feature, reason, issue, is_soft } => { report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler) } - EvalResult::Unmarked => { - // The API could be uncallable for other reasons, for example when a private module - // was referenced. - self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id)); - } + EvalResult::Unmarked => unmarked(span, def_id), } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5e89bf42cb805..fe4ff7d1b9b96 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -705,6 +705,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(arg.id()), arg.span(), false, + |_, _| (), ); } From 8bcf35dd2418b0e9c04e2825d5024594806790e6 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Sun, 19 Jan 2020 15:16:16 -0500 Subject: [PATCH 12/14] Fix stability-attribute-sanity --- src/test/ui/stability-attribute/stability-attribute-sanity.rs | 2 +- .../ui/stability-attribute/stability-attribute-sanity.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.rs b/src/test/ui/stability-attribute/stability-attribute-sanity.rs index 5db924642e59d..f0dbcb41fbfed 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.rs +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.rs @@ -63,7 +63,7 @@ fn multiple3() { } #[rustc_const_unstable(feature = "c", issue = "none")] #[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540] -//~^ ERROR Invalid stability or deprecation version found +//~^ ERROR item has an invalid stability or deprecation version #[rustc_deprecated(since = "a", reason = "text")] fn deprecated_without_unstable_or_stable() { } diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr index d0ca170503796..eb0c8fb889d3d 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr @@ -94,7 +94,7 @@ error[E0544]: multiple stability levels LL | #[rustc_const_unstable(feature = "d", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Invalid stability or deprecation version found +error: item has an invalid stability or deprecation version --> $DIR/stability-attribute-sanity.rs:65:1 | LL | pub const fn multiple4() { } From 5551143e54651a8347fbfeef10363373d9eb1e1e Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Thu, 23 Jan 2020 18:20:44 -0500 Subject: [PATCH 13/14] Additional default type parameter stability tests --- .../auxiliary/unstable_generic_param.rs | 19 +++++++++++++ .../generics-default-stability.rs | 28 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs index 4807c486f13ca..9f4889f59a564 100644 --- a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs +++ b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs @@ -14,3 +14,22 @@ pub trait Trait2 { #[stable(feature = "stable_test_feature", since = "1.0.0")] fn foo() -> T; } + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct1<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: T, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct2 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: T, +} + + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT1: Struct1 = Struct1 { field: 1 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT2: Struct2 = Struct2 { field: 1 }; diff --git a/src/test/ui/stability-attribute/generics-default-stability.rs b/src/test/ui/stability-attribute/generics-default-stability.rs index 8a8ee90dc00e6..0963bbec76bdc 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.rs +++ b/src/test/ui/stability-attribute/generics-default-stability.rs @@ -2,7 +2,7 @@ extern crate unstable_generic_param; -use unstable_generic_param::{Trait1, Trait2}; +use unstable_generic_param::*; struct R; @@ -22,4 +22,30 @@ impl Trait2 for S { fn main() { let _ = S; + + let _ = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + + let _ = STRUCT1; + let _: Struct1 = STRUCT1; // ok + let _: Struct1 = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1 = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' + let _ = STRUCT1.field; // ok + let _: usize = STRUCT1.field; //~ ERROR use of unstable library feature 'unstable_default' + let _ = STRUCT1.field + 1; //~ ERROR use of unstable library feature 'unstable_default' + let _ = STRUCT1.field + 1usize; //~ ERROR use of unstable library feature 'unstable_default' + + let _ = Struct2 { field: 1 }; // ok + let _: Struct2 = Struct2 { field: 1 }; // ok + let _: Struct2 = Struct2 { field: 1 }; // ok + + let _ = STRUCT2; + let _: Struct2 = STRUCT2; // ok + let _: Struct2 = STRUCT2; // ok + let _: Struct2 = STRUCT2; // ok + let _ = STRUCT2.field; // ok + let _: usize = STRUCT2.field; // ok + let _ = STRUCT2.field + 1; // ok + let _ = STRUCT2.field + 1usize; // ok } From 074ef54bfbab9c4185cd70702ac58c97a8345255 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Thu, 23 Jan 2020 19:35:17 -0500 Subject: [PATCH 14/14] Additional trait default parameter stability tests --- .../auxiliary/unstable_generic_param.rs | 8 +++++++- .../generics-default-stability.rs | 14 +++++++++++--- .../generics-default-stability.stderr | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs index 9f4889f59a564..7596fa07cbad4 100644 --- a/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs +++ b/src/test/ui/stability-attribute/auxiliary/unstable_generic_param.rs @@ -10,7 +10,13 @@ pub trait Trait1<#[unstable(feature = "unstable_default", issue = "none")] T = ( } #[stable(feature = "stable_test_feature", since = "1.0.0")] -pub trait Trait2 { +pub trait Trait2<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait3 { #[stable(feature = "stable_test_feature", since = "1.0.0")] fn foo() -> T; } diff --git a/src/test/ui/stability-attribute/generics-default-stability.rs b/src/test/ui/stability-attribute/generics-default-stability.rs index 0963bbec76bdc..1006d701117ff 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.rs +++ b/src/test/ui/stability-attribute/generics-default-stability.rs @@ -16,7 +16,15 @@ impl Trait1 for S { //~ ERROR use of unstable library feature 'unstable_d fn foo() -> usize { 0 } } -impl Trait2 for S { +impl Trait1 for S { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> usize { 0 } +} + +impl Trait2 for S { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> usize { 0 } +} + +impl Trait3 for S { fn foo() -> usize { 0 } // ok } @@ -25,9 +33,9 @@ fn main() { let _ = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' - let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' - let _ = STRUCT1; + let _ = STRUCT1; // ok let _: Struct1 = STRUCT1; // ok let _: Struct1 = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' let _: Struct1 = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' diff --git a/src/test/ui/stability-attribute/generics-default-stability.stderr b/src/test/ui/stability-attribute/generics-default-stability.stderr index fb6deb7f477e4..1b7f4b85b59ba 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.stderr +++ b/src/test/ui/stability-attribute/generics-default-stability.stderr @@ -6,6 +6,22 @@ LL | impl Trait1 for S { | = help: add `#![feature(unstable_default)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:19:13 + | +LL | impl Trait1 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:23:13 + | +LL | impl Trait2 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`.