Auto merge of #92003 - matthiaskrgr:rollup-obgv0rt, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #91172 (Warn when a `#[test]`-like built-in attribute macro is present multiple times.) - #91796 (Fix since attribute for const_manually_drop feature) - #91879 (Remove `in_band_lifetimes` from `rustc_borrowck`) - #91947 (Add `io::Error::other`) - #91967 (Pull in libdevstat on FreeBSD) - #91987 (Add module documentation for rustdoc passes) - #92001 (Fix default_method_body_is_const when used across crates) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
23c2723269
41 changed files with 250 additions and 42 deletions
|
@ -3688,6 +3688,7 @@ dependencies = [
|
||||||
"rustc_expand",
|
"rustc_expand",
|
||||||
"rustc_feature",
|
"rustc_feature",
|
||||||
"rustc_lexer",
|
"rustc_lexer",
|
||||||
|
"rustc_lint_defs",
|
||||||
"rustc_parse",
|
"rustc_parse",
|
||||||
"rustc_parse_format",
|
"rustc_parse_format",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
|
|
|
@ -84,7 +84,7 @@ pub enum LocalsStateAtExit {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalsStateAtExit {
|
impl LocalsStateAtExit {
|
||||||
fn build(
|
fn build<'tcx>(
|
||||||
locals_are_invalidated_at_exit: bool,
|
locals_are_invalidated_at_exit: bool,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum UniverseInfoInner<'tcx> {
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniverseInfo<'tcx> {
|
impl<'tcx> UniverseInfo<'tcx> {
|
||||||
crate fn other() -> UniverseInfo<'tcx> {
|
crate fn other() -> UniverseInfo<'tcx> {
|
||||||
UniverseInfo(UniverseInfoInner::Other)
|
UniverseInfo(UniverseInfoInner::Other)
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ struct PredicateQuery<'tcx> {
|
||||||
base_universe: ty::UniverseIndex,
|
base_universe: ty::UniverseIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
||||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
|
let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
|
||||||
err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
|
err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
|
||||||
|
@ -231,7 +231,7 @@ struct NormalizeQuery<'tcx, T> {
|
||||||
base_universe: ty::UniverseIndex,
|
base_universe: ty::UniverseIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
|
impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
|
||||||
where
|
where
|
||||||
T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
|
T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
|
||||||
{
|
{
|
||||||
|
@ -291,7 +291,7 @@ struct AscribeUserTypeQuery<'tcx> {
|
||||||
base_universe: ty::UniverseIndex,
|
base_universe: ty::UniverseIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
||||||
// and is only the fallback when the nice error fails. Consider improving this some more.
|
// and is only the fallback when the nice error fails. Consider improving this some more.
|
||||||
|
|
|
@ -1598,8 +1598,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
location: Location,
|
location: Location,
|
||||||
mpi: MovePathIndex,
|
mpi: MovePathIndex,
|
||||||
) -> (Vec<MoveSite>, Vec<Location>) {
|
) -> (Vec<MoveSite>, Vec<Location>) {
|
||||||
fn predecessor_locations(
|
fn predecessor_locations<'a>(
|
||||||
body: &'a mir::Body<'tcx>,
|
body: &'a mir::Body<'_>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> impl Iterator<Item = Location> + 'a {
|
) -> impl Iterator<Item = Location> + 'a {
|
||||||
if location.statement_index == 0 {
|
if location.statement_index == 0 {
|
||||||
|
|
|
@ -409,7 +409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
/// Add a note that a type does not implement `Copy`
|
/// Add a note that a type does not implement `Copy`
|
||||||
pub(super) fn note_type_does_not_implement_copy(
|
pub(super) fn note_type_does_not_implement_copy(
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'a>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
place_desc: &str,
|
place_desc: &str,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
|
@ -733,7 +733,7 @@ pub(super) enum BorrowedContentSource<'tcx> {
|
||||||
OverloadedIndex(Ty<'tcx>),
|
OverloadedIndex(Ty<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorrowedContentSource<'tcx> {
|
impl<'tcx> BorrowedContentSource<'tcx> {
|
||||||
pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
|
pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
|
BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
|
||||||
|
|
|
@ -747,7 +747,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
HirId, ImplItem, ImplItemKind, Item, ItemKind,
|
HirId, ImplItem, ImplItemKind, Item, ItemKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option<BodyId> {
|
fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option<BodyId> {
|
||||||
match hir_map.find(id) {
|
match hir_map.find(id) {
|
||||||
Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
|
Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
|
||||||
| Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
|
| Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
|
||||||
|
@ -1066,7 +1066,7 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool {
|
||||||
/// LL | s: &'a String
|
/// LL | s: &'a String
|
||||||
/// | ---------- use `&'a mut String` here to make mutable
|
/// | ---------- use `&'a mut String` here to make mutable
|
||||||
/// ```
|
/// ```
|
||||||
fn annotate_struct_field(
|
fn annotate_struct_field<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
field: &mir::Field,
|
field: &mir::Field,
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(in_band_lifetimes)]
|
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
|
@ -53,7 +53,7 @@ rustc_index::newtype_index! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MemberConstraintSet<'tcx, ty::RegionVid> {
|
impl Default for MemberConstraintSet<'_, ty::RegionVid> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
first_constraints: Default::default(),
|
first_constraints: Default::default(),
|
||||||
|
@ -97,7 +97,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R1> MemberConstraintSet<'tcx, R1>
|
impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
|
||||||
where
|
where
|
||||||
R1: Copy + Hash + Eq,
|
R1: Copy + Hash + Eq,
|
||||||
{
|
{
|
||||||
|
@ -140,7 +140,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> MemberConstraintSet<'tcx, R>
|
impl<R> MemberConstraintSet<'_, R>
|
||||||
where
|
where
|
||||||
R: Copy + Hash + Eq,
|
R: Copy + Hash + Eq,
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,7 +141,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool {
|
||||||
/// then returns the index of the field being projected. Note that this closure will always
|
/// then returns the index of the field being projected. Note that this closure will always
|
||||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||||
/// of a closure type.
|
/// of a closure type.
|
||||||
pub(crate) fn is_upvar_field_projection(
|
pub(crate) fn is_upvar_field_projection<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
upvars: &[Upvar<'tcx>],
|
upvars: &[Upvar<'tcx>],
|
||||||
place_ref: PlaceRef<'tcx>,
|
place_ref: PlaceRef<'tcx>,
|
||||||
|
|
|
@ -58,7 +58,7 @@ crate struct CreateResult<'tcx> {
|
||||||
crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn create(
|
crate fn create<'tcx>(
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
implicit_region_bound: Option<ty::Region<'tcx>>,
|
implicit_region_bound: Option<ty::Region<'tcx>>,
|
||||||
|
@ -81,7 +81,7 @@ crate fn create(
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniversalRegionRelations<'tcx> {
|
impl UniversalRegionRelations<'_> {
|
||||||
/// Records in the `outlives_relation` (and
|
/// Records in the `outlives_relation` (and
|
||||||
/// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
|
/// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
|
||||||
/// builder below.
|
/// builder below.
|
||||||
|
@ -110,7 +110,7 @@ impl UniversalRegionRelations<'tcx> {
|
||||||
/// outlives `fr` and (b) is not local.
|
/// outlives `fr` and (b) is not local.
|
||||||
///
|
///
|
||||||
/// (*) If there are multiple competing choices, we return all of them.
|
/// (*) If there are multiple competing choices, we return all of them.
|
||||||
crate fn non_local_upper_bounds(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> {
|
crate fn non_local_upper_bounds<'a>(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> {
|
||||||
debug!("non_local_upper_bound(fr={:?})", fr);
|
debug!("non_local_upper_bound(fr={:?})", fr);
|
||||||
let res = self.non_local_bounds(&self.inverse_outlives, fr);
|
let res = self.non_local_bounds(&self.inverse_outlives, fr);
|
||||||
assert!(!res.is_empty(), "can't find an upper bound!?");
|
assert!(!res.is_empty(), "can't find an upper bound!?");
|
||||||
|
@ -232,7 +232,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
|
||||||
region_bound_pairs: RegionBoundPairs<'tcx>,
|
region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
|
impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
crate fn create(mut self) -> CreateResult<'tcx> {
|
crate fn create(mut self) -> CreateResult<'tcx> {
|
||||||
let unnormalized_input_output_tys = self
|
let unnormalized_input_output_tys = self
|
||||||
.universal_regions
|
.universal_regions
|
||||||
|
|
|
@ -152,7 +152,7 @@ impl LocalUseMapBuild<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitor<'tcx> for LocalUseMapBuild<'_> {
|
impl Visitor<'_> for LocalUseMapBuild<'_> {
|
||||||
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
||||||
if self.locals_with_use_data[local] {
|
if self.locals_with_use_data[local] {
|
||||||
match def_use::categorize(context) {
|
match def_use::categorize(context) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub(super) fn generate<'mir, 'tcx>(
|
||||||
// to compute whether a variable `X` is live if that variable contains
|
// to compute whether a variable `X` is live if that variable contains
|
||||||
// some region `R` in its type where `R` is not known to outlive a free
|
// some region `R` in its type where `R` is not known to outlive a free
|
||||||
// region (i.e., where `R` may be valid for just a subset of the fn body).
|
// region (i.e., where `R` may be valid for just a subset of the fn body).
|
||||||
fn compute_live_locals(
|
fn compute_live_locals<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
free_regions: &FxHashSet<RegionVid>,
|
free_regions: &FxHashSet<RegionVid>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
|
@ -104,7 +104,7 @@ fn compute_live_locals(
|
||||||
/// regions. For these regions, we do not need to compute
|
/// regions. For these regions, we do not need to compute
|
||||||
/// liveness, since the outlives constraints will ensure that they
|
/// liveness, since the outlives constraints will ensure that they
|
||||||
/// are live over the whole fn body anyhow.
|
/// are live over the whole fn body anyhow.
|
||||||
fn regions_that_outlive_free_regions(
|
fn regions_that_outlive_free_regions<'tcx>(
|
||||||
num_region_vars: usize,
|
num_region_vars: usize,
|
||||||
universal_regions: &UniversalRegions<'tcx>,
|
universal_regions: &UniversalRegions<'tcx>,
|
||||||
constraint_set: &OutlivesConstraintSet<'tcx>,
|
constraint_set: &OutlivesConstraintSet<'tcx>,
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitor<'tcx> for UseFactsExtractor<'_> {
|
impl Visitor<'_> for UseFactsExtractor<'_> {
|
||||||
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
||||||
match def_use::categorize(context) {
|
match def_use::categorize(context) {
|
||||||
Some(DefUse::Def) => self.insert_def(local, location),
|
Some(DefUse::Def) => self.insert_def(local, location),
|
||||||
|
@ -63,7 +63,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) {
|
||||||
self.super_place(place, context, location);
|
self.super_place(place, context, location);
|
||||||
match context {
|
match context {
|
||||||
PlaceContext::NonMutatingUse(_) => {
|
PlaceContext::NonMutatingUse(_) => {
|
||||||
|
@ -82,7 +82,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn populate_access_facts(
|
pub(super) fn populate_access_facts<'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
location_table: &LocationTable,
|
location_table: &LocationTable,
|
||||||
|
@ -123,7 +123,7 @@ pub(super) fn populate_access_facts(
|
||||||
|
|
||||||
// For every potentially drop()-touched region `region` in `local`'s type
|
// For every potentially drop()-touched region `region` in `local`'s type
|
||||||
// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
|
// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
|
||||||
pub(super) fn add_drop_of_var_derefs_origin(
|
pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
local: Local,
|
local: Local,
|
||||||
kind: &GenericArg<'tcx>,
|
kind: &GenericArg<'tcx>,
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::{
|
||||||
/// DROP-LIVE set are to the liveness sets for regions found in the
|
/// DROP-LIVE set are to the liveness sets for regions found in the
|
||||||
/// `dropck_outlives` result of the variable's type (in particular,
|
/// `dropck_outlives` result of the variable's type (in particular,
|
||||||
/// this respects `#[may_dangle]` annotations).
|
/// this respects `#[may_dangle]` annotations).
|
||||||
pub(super) fn trace(
|
pub(super) fn trace<'mir, 'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<RegionValueElements>,
|
||||||
|
@ -119,7 +119,7 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||||
stack: Vec<PointIndex>,
|
stack: Vec<PointIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||||
fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self {
|
fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self {
|
||||||
let num_points = cx.elements.num_points();
|
let num_points = cx.elements.num_points();
|
||||||
LivenessResults {
|
LivenessResults {
|
||||||
|
@ -418,7 +418,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LivenessContext<'_, '_, '_, 'tcx> {
|
impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
/// Returns `true` if the local variable (or some part of it) is initialized at the current
|
/// Returns `true` if the local variable (or some part of it) is initialized at the current
|
||||||
/// cursor position. Callers should call one of the `seek` methods immediately before to point
|
/// cursor position. Callers should call one of the `seek` methods immediately before to point
|
||||||
/// the cursor to the desired location.
|
/// the cursor to the desired location.
|
||||||
|
|
|
@ -945,7 +945,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
|
||||||
crate type_tests: Vec<TypeTest<'tcx>>,
|
crate type_tests: Vec<TypeTest<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MirTypeckRegionConstraints<'tcx> {
|
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
|
||||||
fn placeholder_region(
|
fn placeholder_region(
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
universe_info: UniverseInfo<'tcx>,
|
universe_info: UniverseInfo<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
|
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
|
@ -62,7 +62,7 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
|
impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.type_checker.param_env
|
self.type_checker.param_env
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_errors = { path = "../rustc_errors" }
|
rustc_errors = { path = "../rustc_errors" }
|
||||||
rustc_feature = { path = "../rustc_feature" }
|
rustc_feature = { path = "../rustc_feature" }
|
||||||
rustc_lexer = { path = "../rustc_lexer" }
|
rustc_lexer = { path = "../rustc_lexer" }
|
||||||
|
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||||
rustc_parse = { path = "../rustc_parse" }
|
rustc_parse = { path = "../rustc_parse" }
|
||||||
rustc_target = { path = "../rustc_target" }
|
rustc_target = { path = "../rustc_target" }
|
||||||
rustc_session = { path = "../rustc_session" }
|
rustc_session = { path = "../rustc_session" }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::util::check_builtin_macro_attribute;
|
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::mut_visit::MutVisitor;
|
use rustc_ast::mut_visit::MutVisitor;
|
||||||
|
@ -25,6 +25,7 @@ crate fn expand(
|
||||||
annotatable: Annotatable,
|
annotatable: Annotatable,
|
||||||
) -> Vec<Annotatable> {
|
) -> Vec<Annotatable> {
|
||||||
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
|
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
|
||||||
|
warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval);
|
||||||
vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
|
vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/// The expansion from a test function to the appropriate test struct for libtest
|
/// The expansion from a test function to the appropriate test struct for libtest
|
||||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||||
use crate::util::check_builtin_macro_attribute;
|
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
|
@ -27,6 +27,7 @@ pub fn expand_test_case(
|
||||||
anno_item: Annotatable,
|
anno_item: Annotatable,
|
||||||
) -> Vec<Annotatable> {
|
) -> Vec<Annotatable> {
|
||||||
check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
|
check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
|
||||||
|
warn_on_duplicate_attribute(&ecx, &anno_item, sym::test_case);
|
||||||
|
|
||||||
if !ecx.ecfg.should_test {
|
if !ecx.ecfg.should_test {
|
||||||
return vec![];
|
return vec![];
|
||||||
|
@ -55,6 +56,7 @@ pub fn expand_test(
|
||||||
item: Annotatable,
|
item: Annotatable,
|
||||||
) -> Vec<Annotatable> {
|
) -> Vec<Annotatable> {
|
||||||
check_builtin_macro_attribute(cx, meta_item, sym::test);
|
check_builtin_macro_attribute(cx, meta_item, sym::test);
|
||||||
|
warn_on_duplicate_attribute(&cx, &item, sym::test);
|
||||||
expand_test_or_bench(cx, attr_sp, item, false)
|
expand_test_or_bench(cx, attr_sp, item, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +67,7 @@ pub fn expand_bench(
|
||||||
item: Annotatable,
|
item: Annotatable,
|
||||||
) -> Vec<Annotatable> {
|
) -> Vec<Annotatable> {
|
||||||
check_builtin_macro_attribute(cx, meta_item, sym::bench);
|
check_builtin_macro_attribute(cx, meta_item, sym::bench);
|
||||||
|
warn_on_duplicate_attribute(&cx, &item, sym::bench);
|
||||||
expand_test_or_bench(cx, attr_sp, item, true)
|
expand_test_or_bench(cx, attr_sp, item, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use rustc_ast::MetaItem;
|
use rustc_ast::{Attribute, MetaItem};
|
||||||
use rustc_expand::base::ExtCtxt;
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_feature::AttributeTemplate;
|
use rustc_feature::AttributeTemplate;
|
||||||
|
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
|
@ -10,3 +11,33 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na
|
||||||
let attr = ecx.attribute(meta_item.clone());
|
let attr = ecx.attribute(meta_item.clone());
|
||||||
validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
|
validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when
|
||||||
|
/// an attribute may have been mistakenly duplicated.
|
||||||
|
pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) {
|
||||||
|
let attrs: Option<&[Attribute]> = match item {
|
||||||
|
Annotatable::Item(item) => Some(&item.attrs),
|
||||||
|
Annotatable::TraitItem(item) => Some(&item.attrs),
|
||||||
|
Annotatable::ImplItem(item) => Some(&item.attrs),
|
||||||
|
Annotatable::ForeignItem(item) => Some(&item.attrs),
|
||||||
|
Annotatable::Expr(expr) => Some(&expr.attrs),
|
||||||
|
Annotatable::Arm(arm) => Some(&arm.attrs),
|
||||||
|
Annotatable::ExprField(field) => Some(&field.attrs),
|
||||||
|
Annotatable::PatField(field) => Some(&field.attrs),
|
||||||
|
Annotatable::GenericParam(param) => Some(¶m.attrs),
|
||||||
|
Annotatable::Param(param) => Some(¶m.attrs),
|
||||||
|
Annotatable::FieldDef(def) => Some(&def.attrs),
|
||||||
|
Annotatable::Variant(variant) => Some(&variant.attrs),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(attrs) = attrs {
|
||||||
|
if let Some(attr) = ecx.sess.find_by_name(attrs, name) {
|
||||||
|
ecx.parse_sess().buffer_lint(
|
||||||
|
DUPLICATE_MACRO_ATTRIBUTES,
|
||||||
|
attr.span,
|
||||||
|
ecx.current_expansion.lint_node_id,
|
||||||
|
"duplicated attribute",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3066,6 +3066,7 @@ declare_lint_pass! {
|
||||||
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
|
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
|
||||||
DEREF_INTO_DYN_SUPERTRAIT,
|
DEREF_INTO_DYN_SUPERTRAIT,
|
||||||
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
||||||
|
DUPLICATE_MACRO_ATTRIBUTES,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3603,3 +3604,32 @@ declare_lint! {
|
||||||
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro
|
||||||
|
/// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test`
|
||||||
|
/// and `test_case`.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust,ignore (needs --test)
|
||||||
|
/// #[test]
|
||||||
|
/// #[test]
|
||||||
|
/// fn foo() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// A duplicated attribute may erroneously originate from a copy-paste and the effect of it
|
||||||
|
/// being duplicated may not be obvious or desireable.
|
||||||
|
///
|
||||||
|
/// For instance, doubling the `#[test]` attributes registers the test to be run twice with no
|
||||||
|
/// change to its environment.
|
||||||
|
///
|
||||||
|
/// [issue #90979]: https://github.com/rust-lang/rust/issues/90979
|
||||||
|
pub DUPLICATE_MACRO_ATTRIBUTES,
|
||||||
|
Warn,
|
||||||
|
"duplicated attribute"
|
||||||
|
}
|
||||||
|
|
|
@ -870,8 +870,9 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
|
||||||
let needs_inline = (generics.requires_monomorphization(tcx)
|
let needs_inline = (generics.requires_monomorphization(tcx)
|
||||||
|| tcx.codegen_fn_attrs(def_id).requests_inline())
|
|| tcx.codegen_fn_attrs(def_id).requests_inline())
|
||||||
&& tcx.sess.opts.output_types.should_codegen();
|
&& tcx.sess.opts.output_types.should_codegen();
|
||||||
// Only check the presence of the `const` modifier.
|
// The function has a `const` modifier or is annotated with `default_method_body_is_const`.
|
||||||
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id());
|
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
|
||||||
|
|| tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const);
|
||||||
let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir;
|
let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||||
(is_const_fn, needs_inline || always_encode_mir)
|
(is_const_fn, needs_inline || always_encode_mir)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl<T> ManuallyDrop<T> {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
|
#[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
|
||||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||||
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
|
#[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn new(value: T) -> ManuallyDrop<T> {
|
pub const fn new(value: T) -> ManuallyDrop<T> {
|
||||||
ManuallyDrop { value }
|
ManuallyDrop { value }
|
||||||
|
@ -82,7 +82,7 @@ impl<T> ManuallyDrop<T> {
|
||||||
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
|
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||||
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
|
#[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
|
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
|
||||||
slot.value
|
slot.value
|
||||||
|
|
|
@ -417,6 +417,33 @@ impl Error {
|
||||||
Self::_new(kind, error.into())
|
Self::_new(kind, error.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new I/O error from an arbitrary error payload.
|
||||||
|
///
|
||||||
|
/// This function is used to generically create I/O errors which do not
|
||||||
|
/// originate from the OS itself. It is a shortcut for [`Error::new`]
|
||||||
|
/// with [`ErrorKind::Other`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(io_error_other)]
|
||||||
|
///
|
||||||
|
/// use std::io::Error;
|
||||||
|
///
|
||||||
|
/// // errors can be created from strings
|
||||||
|
/// let custom_error = Error::other("oh no!");
|
||||||
|
///
|
||||||
|
/// // errors can also be created from other errors
|
||||||
|
/// let custom_error2 = Error::other(custom_error);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "io_error_other", issue = "91946")]
|
||||||
|
pub fn other<E>(error: E) -> Error
|
||||||
|
where
|
||||||
|
E: Into<Box<dyn error::Error + Send + Sync>>,
|
||||||
|
{
|
||||||
|
Self::_new(ErrorKind::Other, error.into())
|
||||||
|
}
|
||||||
|
|
||||||
fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
|
fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
|
||||||
Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
|
Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ files_to_extract=(
|
||||||
for lib in c cxxrt gcc_s m thr util; do
|
for lib in c cxxrt gcc_s m thr util; do
|
||||||
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
|
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
|
||||||
done
|
done
|
||||||
for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do
|
for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do
|
||||||
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
|
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Detects links that are not linkified, e.g., in Markdown such as `Go to https://example.com/.`
|
||||||
|
//! Suggests wrapping the link with angle brackets: `Go to <https://example.com/>.` to linkify it.
|
||||||
use super::Pass;
|
use super::Pass;
|
||||||
use crate::clean::*;
|
use crate::clean::*;
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Calculates information used for the --show-coverage flag.
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::html::markdown::{find_testable_code, ErrorCodes};
|
use crate::html::markdown::{find_testable_code, ErrorCodes};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Validates syntax inside Rust code blocks (\`\`\`rust).
|
||||||
use rustc_data_structures::sync::{Lock, Lrc};
|
use rustc_data_structures::sync::{Lock, Lrc};
|
||||||
use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
|
use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
|
||||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Looks for items missing (or incorrectly having) doctests.
|
||||||
|
//!
|
||||||
//! This pass is overloaded and runs two different lints.
|
//! This pass is overloaded and runs two different lints.
|
||||||
//!
|
//!
|
||||||
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests.
|
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests.
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Collects trait impls for each item in the crate. For example, if a crate
|
||||||
|
//! defines a struct that implements a trait, this pass will note that the
|
||||||
|
//! struct implements that trait.
|
||||||
use super::Pass;
|
use super::Pass;
|
||||||
use crate::clean::*;
|
use crate::clean::*;
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Detects invalid HTML (like an unclosed `<span>`) in doc comments.
|
||||||
use super::Pass;
|
use super::Pass;
|
||||||
use crate::clean::*;
|
use crate::clean::*;
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Propagates [`#[doc(cfg(...))]`](https://github.com/rust-lang/rust/issues/43781) to child items.
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::clean::cfg::Cfg;
|
use crate::clean::cfg::Cfg;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Strip all doc(hidden) items from the output.
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Strips all private import statements (use, extern crate) from a
|
||||||
|
//! crate.
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Strip all private items from the output. Additionally implies strip_priv_imports.
|
||||||
|
//! Basically, the goal is to remove items that are not relevant for public documentation.
|
||||||
use crate::clean::{self, ItemIdSet};
|
use crate::clean::{self, ItemIdSet};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! A collection of utility functions for the `strip_*` passes.
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::middle::privacy::AccessLevels;
|
use rustc_middle::middle::privacy::AccessLevels;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
//! Removes excess indentation on comments in order for the Markdown
|
||||||
|
//! to be parsed correctly. This is necessary because the convention for
|
||||||
|
//! writing documentation is to provide a space between the /// or //! marker
|
||||||
|
//! and the doc text, but Markdown is whitespace-sensitive. For example,
|
||||||
|
//! a block of text with four-space indentation is parsed as a code block,
|
||||||
|
//! so if we didn't unindent comments, these list items
|
||||||
|
//!
|
||||||
|
//! /// A list:
|
||||||
|
//! ///
|
||||||
|
//! /// - Foo
|
||||||
|
//! /// - Bar
|
||||||
|
//!
|
||||||
|
//! would be parsed as if they were in a code block, which is likely not what the user intended.
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
|
41
src/test/ui/attributes/duplicated-attributes.rs
Normal file
41
src/test/ui/attributes/duplicated-attributes.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Test that, if an item is annotated with a builtin attribute more than once, a warning is
|
||||||
|
// emitted.
|
||||||
|
// Tests https://github.com/rust-lang/rust/issues/90979
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: --test
|
||||||
|
|
||||||
|
#![feature(test)]
|
||||||
|
#![feature(cfg_eval)]
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[test]
|
||||||
|
//~^ WARNING duplicated attribute
|
||||||
|
fn f() {}
|
||||||
|
|
||||||
|
// The following shouldn't trigger an error. The attribute is not duplicated.
|
||||||
|
#[test]
|
||||||
|
fn f2() {}
|
||||||
|
|
||||||
|
// The following shouldn't trigger an error either. The second attribute is not #[test].
|
||||||
|
#[test]
|
||||||
|
#[inline]
|
||||||
|
fn f3() {}
|
||||||
|
|
||||||
|
extern crate test;
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
#[bench]
|
||||||
|
//~^ WARNING duplicated attribute
|
||||||
|
fn f4(_: &mut Bencher) {}
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[cfg_eval]
|
||||||
|
//~^ WARNING duplicated attribute
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
struct S2;
|
||||||
|
|
||||||
|
fn main() {}
|
22
src/test/ui/attributes/duplicated-attributes.stderr
Normal file
22
src/test/ui/attributes/duplicated-attributes.stderr
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
warning: duplicated attribute
|
||||||
|
--> $DIR/duplicated-attributes.rs:12:1
|
||||||
|
|
|
||||||
|
LL | #[test]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(duplicate_macro_attributes)]` on by default
|
||||||
|
|
||||||
|
warning: duplicated attribute
|
||||||
|
--> $DIR/duplicated-attributes.rs:29:1
|
||||||
|
|
|
||||||
|
LL | #[bench]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: duplicated attribute
|
||||||
|
--> $DIR/duplicated-attributes.rs:34:1
|
||||||
|
|
|
||||||
|
LL | #[cfg_eval]
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: 3 warnings emitted
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
#![feature(const_fn_trait_bound)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
pub trait MyTrait {
|
pub trait MyTrait {
|
||||||
|
#[default_method_body_is_const]
|
||||||
|
fn defaulted_func(&self) {}
|
||||||
fn func(self);
|
fn func(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// This tests that `default_method_body_is_const` methods can
|
||||||
|
// be called from a const context when used across crates.
|
||||||
|
//
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
|
// aux-build: cross-crate.rs
|
||||||
|
extern crate cross_crate;
|
||||||
|
|
||||||
|
use cross_crate::*;
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
Const.func();
|
||||||
|
Const.defaulted_func();
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue