1
Fork 0

Auto merge of #99520 - matthiaskrgr:rollup-05uuv5s, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #99212 (introduce `implied_by` in `#[unstable]` attribute)
 - #99352 (Use `typeck_results` to avoid duplicate `ast_ty_to_ty` call)
 - #99355 (better error for bad depth parameter on macro metavar expr)
 - #99480 (Diagnostic width span is not added when '0$' is used as width in format strings)
 - #99488 (compiletest: Allow using revisions with debuginfo tests.)
 - #99489 (rustdoc UI fixes)
 - #99508 (Avoid `Symbol` to `String` conversions)
 - #99510 (adapt assembly/static-relocation-model test for LLVM change)
 - #99516 (Use new tracking issue for proc_macro::tracked_*.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-07-20 19:37:17 +00:00
commit d68e7ebc38
60 changed files with 584 additions and 254 deletions

View file

@ -135,9 +135,42 @@ impl ConstStability {
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
pub enum StabilityLevel {
// Reason for the current stability level and the relevant rust-lang issue
Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
Stable { since: Symbol, allowed_through_unstable_modules: bool },
/// `#[unstable]`
Unstable {
/// Reason for the current stability level.
reason: Option<Symbol>,
/// Relevant `rust-lang/rust` issue.
issue: Option<NonZeroU32>,
is_soft: bool,
/// If part of a feature is stabilized and a new feature is added for the remaining parts,
/// then the `implied_by` attribute is used to indicate which now-stable feature previously
/// contained a item.
///
/// ```pseudo-Rust
/// #[unstable(feature = "foo", issue = "...")]
/// fn foo() {}
/// #[unstable(feature = "foo", issue = "...")]
/// fn foobar() {}
/// ```
///
/// ...becomes...
///
/// ```pseudo-Rust
/// #[stable(feature = "foo", since = "1.XX.X")]
/// fn foo() {}
/// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
/// fn foobar() {}
/// ```
implied_by: Option<Symbol>,
},
/// `#[stable]`
Stable {
/// Rust release which stabilized this feature.
since: Symbol,
/// Is this item allowed to be referred to on stable, despite being contained in unstable
/// modules?
allowed_through_unstable_modules: bool,
},
}
impl StabilityLevel {
@ -243,6 +276,7 @@ where
let mut issue = None;
let mut issue_num = None;
let mut is_soft = false;
let mut implied_by = None;
for meta in metas {
let Some(mi) = meta.meta_item() else {
handle_errors(
@ -308,6 +342,11 @@ where
}
is_soft = true;
}
sym::implied_by => {
if !get(mi, &mut implied_by) {
continue 'outer;
}
}
_ => {
handle_errors(
&sess.parse_sess,
@ -332,7 +371,7 @@ where
);
continue;
}
let level = Unstable { reason, issue: issue_num, is_soft };
let level = Unstable { reason, issue: issue_num, is_soft, implied_by };
if sym::unstable == meta_name {
stab = Some((Stability { level, feature }, attr.span));
} else {
@ -391,7 +430,7 @@ where
meta.span(),
AttrError::UnknownMetaItem(
pprust::path_to_string(&mi.path),
&["since", "note"],
&["feature", "since"],
),
);
continue 'outer;

View file

@ -485,7 +485,7 @@ impl<'a, 'b> Context<'a, 'b> {
if let Some(span) = fmt.width_span {
let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
match fmt.width {
parse::CountIsParam(pos) if pos > self.num_args() => {
parse::CountIsParam(pos) if pos >= self.num_args() => {
e.span_label(
span,
&format!(
@ -1004,9 +1004,7 @@ fn lint_named_arguments_used_positionally(
node_id: ast::CRATE_NODE_ID,
lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally(
arg_span,
span,
symbol.to_string(),
arg_span, span, symbol,
),
});
}

View file

@ -390,18 +390,17 @@ impl Diagnostic {
expected: DiagnosticStyledString,
found: DiagnosticStyledString,
) -> &mut Self {
let mut msg: Vec<_> =
vec![("required when trying to coerce from type `".to_string(), Style::NoStyle)];
let mut msg: Vec<_> = vec![("required when trying to coerce from type `", Style::NoStyle)];
msg.extend(expected.0.iter().map(|x| match *x {
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
}));
msg.push(("` to type '".to_string(), Style::NoStyle));
msg.push(("` to type '", Style::NoStyle));
msg.extend(found.0.iter().map(|x| match *x {
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
}));
msg.push(("`".to_string(), Style::NoStyle));
msg.push(("`", Style::NoStyle));
// For now, just attach these as notes
self.highlighted_note(msg);

View file

@ -512,7 +512,18 @@ fn out_of_bounds_err<'a>(
span: Span,
ty: &str,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
cx.struct_span_err(span, &format!("{ty} depth must be less than {max}"))
let msg = if max == 0 {
format!(
"meta-variable expression `{ty}` with depth parameter \
must be called inside of a macro repetition"
)
} else {
format!(
"depth parameter on meta-variable expression `{ty}` \
must be less than {max}"
)
};
cx.struct_span_err(span, &msg)
}
fn transcribe_metavar_expr<'a>(

View file

@ -467,7 +467,7 @@ pub enum BuiltinLintDiagnostics {
/// If true, the lifetime will be fully elided.
use_span: Option<(Span, bool)>,
},
NamedArgumentUsedPositionally(Option<Span>, Span, String),
NamedArgumentUsedPositionally(Option<Span>, Span, Symbol),
}
/// Lints that are buffered up early on in the `Session` before the

View file

@ -951,6 +951,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
}
/// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
/// has an `implied_by` meta item, then the mapping from the implied feature to the actual
/// feature is a stability implication).
fn get_stability_implications(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
}
/// Iterates over the language items in the given crate.
fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
tcx.arena.alloc_from_iter(

View file

@ -291,6 +291,9 @@ provide! { <'tcx> tcx, def_id, other, cdata,
tcx.arena.alloc_slice(&result)
}
defined_lib_features => { cdata.get_lib_features(tcx) }
stability_implications => {
cdata.get_stability_implications(tcx).iter().copied().collect()
}
is_intrinsic => { cdata.get_is_intrinsic(def_id.index) }
defined_lang_items => { cdata.get_lang_items(tcx) }
diagnostic_items => { cdata.get_diagnostic_items() }

View file

@ -538,6 +538,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let lib_features = self.encode_lib_features();
let lib_feature_bytes = self.position() - i;
// Encode the stability implications.
i = self.position();
let stability_implications = self.encode_stability_implications();
let stability_implications_bytes = self.position() - i;
// Encode the language items.
i = self.position();
let lang_items = self.encode_lang_items();
@ -686,6 +691,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
crate_deps,
dylib_dependency_formats,
lib_features,
stability_implications,
lang_items,
diagnostic_items,
lang_items_missing,
@ -710,6 +716,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let computed_total_bytes = preamble_bytes
+ dep_bytes
+ lib_feature_bytes
+ stability_implications_bytes
+ lang_item_bytes
+ diagnostic_item_bytes
+ native_lib_bytes
@ -761,6 +768,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
p("preamble", preamble_bytes);
p("dep", dep_bytes);
p("lib feature", lib_feature_bytes);
p("stability_implications", stability_implications_bytes);
p("lang item", lang_item_bytes);
p("diagnostic item", diagnostic_item_bytes);
p("native lib", native_lib_bytes);
@ -1777,6 +1785,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_array(lib_features.to_vec())
}
fn encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let implications = tcx.stability_implications(LOCAL_CRATE);
self.lazy_array(implications.iter().map(|(k, v)| (*k, *v)))
}
fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
empty_proc_macro!(self);
let tcx = self.tcx;

View file

@ -226,6 +226,7 @@ pub(crate) struct CrateRoot {
crate_deps: LazyArray<CrateDep>,
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
stability_implications: LazyArray<(Symbol, Symbol)>,
lang_items: LazyArray<(DefIndex, usize)>,
lang_items_missing: LazyArray<lang_items::LangItem>,
diagnostic_items: LazyArray<(Symbol, DefIndex)>,

View file

@ -3,14 +3,14 @@ pub mod dependency_format;
pub mod exported_symbols;
pub mod lang_items;
pub mod lib_features {
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_span::symbol::Symbol;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{symbol::Symbol, Span};
#[derive(HashStable, Debug)]
pub struct LibFeatures {
// A map from feature to stabilisation version.
pub stable: FxHashMap<Symbol, Symbol>,
pub unstable: FxHashSet<Symbol>,
/// A map from feature to stabilisation version.
pub stable: FxHashMap<Symbol, (Symbol, Span)>,
pub unstable: FxHashMap<Symbol, Span>,
}
impl LibFeatures {
@ -18,8 +18,8 @@ pub mod lib_features {
let mut all_features: Vec<_> = self
.stable
.iter()
.map(|(f, s)| (*f, Some(*s)))
.chain(self.unstable.iter().map(|f| (*f, None)))
.map(|(f, (s, _))| (*f, Some(*s)))
.chain(self.unstable.iter().map(|(f, _)| (*f, None)))
.collect();
all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
all_features

View file

@ -62,6 +62,19 @@ pub struct Index {
pub stab_map: FxHashMap<LocalDefId, Stability>,
pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
/// exists, then this map will have a `impliee -> implier` entry.
///
/// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
/// specify their implications (both `implies` and `implied_by`). If only one of the two
/// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
/// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
/// reported, only the `#[stable]` attribute information is available, so the map is necessary
/// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
/// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
/// unstable feature" error for a feature that was implied.
pub implications: FxHashMap<Symbol, Symbol>,
}
impl Index {
@ -423,7 +436,9 @@ impl<'tcx> TyCtxt<'tcx> {
match stability {
Some(Stability {
level: attr::Unstable { reason, issue, is_soft }, feature, ..
level: attr::Unstable { reason, issue, is_soft, implied_by },
feature,
..
}) => {
if span.allows_unstable(feature) {
debug!("stability: skipping span={:?} since it is internal", span);
@ -433,6 +448,13 @@ impl<'tcx> TyCtxt<'tcx> {
return EvalResult::Allow;
}
// If this item was previously part of a now-stabilized feature which is still
// active (i.e. the user hasn't removed the attribute for the stabilized feature
// yet) then allow use of this item.
if let Some(implied_by) = implied_by && self.features().active(implied_by) {
return EvalResult::Allow;
}
// When we're compiling the compiler itself we may pull in
// crates from crates.io, but those crates may depend on other
// crates also pulled in from crates.io. We want to ideally be

View file

@ -1634,11 +1634,15 @@ rustc_queries! {
storage(ArenaCacheSelector<'tcx>)
desc { "calculating the lib features map" }
}
query defined_lib_features(_: CrateNum)
-> &'tcx [(Symbol, Option<Symbol>)] {
query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
}
query stability_implications(_: CrateNum) -> FxHashMap<Symbol, Symbol> {
storage(ArenaCacheSelector<'tcx>)
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
separate_provide_extern
}
/// Whether the function is an intrinsic
query is_intrinsic(def_id: DefId) -> bool {
desc { |tcx| "is_intrinsic({})", tcx.def_path_str(def_id) }

View file

@ -572,9 +572,10 @@ impl<'a> Parser<'a> {
// '0' flag and then an ill-formatted format string with just a '$'
// and no count, but this is better if we instead interpret this as
// no '0' flag and '0$' as the width instead.
if self.consume('$') {
if let Some(end) = self.consume_pos('$') {
spec.width = CountIsParam(0);
havewidth = true;
spec.width_span = Some(self.to_span_index(end - 1).to(self.to_span_index(end + 1)));
} else {
spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
}

View file

@ -178,6 +178,23 @@ fn format_counts() {
},
})],
);
same(
"{1:0$.10x}",
&[NextArgument(Argument {
position: ArgumentIs(1),
format: FormatSpec {
fill: None,
align: AlignUnknown,
flags: 0,
precision: CountIs(10),
width: CountIsParam(0),
precision_span: None,
width_span: Some(InnerSpan::new(4, 6)),
ty: "x",
ty_span: None,
},
})],
);
same(
"{:.*x}",
&[NextArgument(Argument {

View file

@ -1,8 +1,8 @@
// Detecting lib features (i.e., features that are not lang features).
//
// These are declared using stability attributes (e.g., `#[stable (..)]`
// and `#[unstable (..)]`), but are not declared in one single location
// (unlike lang features), which means we need to collect them instead.
//! Detecting lib features (i.e., features that are not lang features).
//!
//! These are declared using stability attributes (e.g., `#[stable (..)]` and `#[unstable (..)]`),
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.
use rustc_ast::{Attribute, MetaItemKind};
use rustc_errors::struct_span_err;
@ -71,11 +71,11 @@ impl<'tcx> LibFeatureCollector<'tcx> {
fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
let already_in_stable = self.lib_features.stable.contains_key(&feature);
let already_in_unstable = self.lib_features.unstable.contains(&feature);
let already_in_unstable = self.lib_features.unstable.contains_key(&feature);
match (since, already_in_stable, already_in_unstable) {
(Some(since), _, false) => {
if let Some(prev_since) = self.lib_features.stable.get(&feature) {
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
if *prev_since != since {
self.span_feature_error(
span,
@ -89,10 +89,10 @@ impl<'tcx> LibFeatureCollector<'tcx> {
}
}
self.lib_features.stable.insert(feature, since);
self.lib_features.stable.insert(feature, (since, span));
}
(None, false, _) => {
self.lib_features.unstable.insert(feature);
self.lib_features.unstable.insert(feature, span);
}
(Some(_), _, true) | (None, true, _) => {
self.span_feature_error(

View file

@ -2,9 +2,9 @@
//! propagating default levels lexically from parent to children ast nodes.
use attr::StabilityLevel;
use rustc_attr::{self as attr, ConstStability, Stability};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_errors::struct_span_err;
use rustc_attr::{self as attr, ConstStability, Stability, Unstable};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@ -29,13 +29,13 @@ 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,
// Deprecation annotation is useless, reject it. (Stability attribute is still required.)
/// Deprecation annotation is useless, reject it. (Stability attribute is still required.)
DeprecationProhibited,
// Annotation itself is useless, but it can be propagated to children
/// Annotation itself is useless, but it can be propagated to children.
Container,
}
@ -83,7 +83,7 @@ impl InheritStability {
}
}
// 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,
@ -94,9 +94,9 @@ struct Annotator<'a, 'tcx> {
}
impl<'a, 'tcx> Annotator<'a, 'tcx> {
// Determine the stability for a node based on its attributes and inherited
// stability. The stability is recorded in the index and used as the parent.
// If the node is a function, `fn_sig` is its signature
/// Determine the stability for a node based on its attributes and inherited stability. The
/// stability is recorded in the index and used as the parent. If the node is a function,
/// `fn_sig` is its signature.
fn annotate<F>(
&mut self,
def_id: LocalDefId,
@ -265,6 +265,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}
if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab {
self.index.implications.insert(implied_by, feature);
}
self.index.stab_map.insert(def_id, stab);
stab
});
@ -610,6 +614,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
stab_map: Default::default(),
const_stab_map: Default::default(),
depr_map: Default::default(),
implications: Default::default(),
};
{
@ -637,6 +642,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
reason: Some(Symbol::intern(reason)),
issue: NonZeroU32::new(27812),
is_soft: false,
implied_by: None,
},
feature: sym::rustc_private,
};
@ -667,6 +673,7 @@ pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
check_mod_unstable_api_usage,
stability_index,
stability_implications: |tcx, _| tcx.stability().implications.clone(),
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
lookup_deprecation_entry: |tcx, id| {
@ -945,12 +952,45 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
remaining_lib_features.remove(&sym::libc);
remaining_lib_features.remove(&sym::test);
let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| {
for &(feature, since) in defined_features {
if let Some(since) = since {
if let Some(span) = remaining_lib_features.get(&feature) {
// Warn if the user has enabled an already-stable lib feature.
unnecessary_stable_feature_lint(tcx, *span, feature, since);
// We always collect the lib features declared in the current crate, even if there are
// no unknown features, because the collection also does feature attribute validation.
let local_defined_features = tcx.lib_features(());
let mut all_lib_features: FxHashMap<_, _> =
local_defined_features.to_vec().iter().map(|el| *el).collect();
let mut implications = tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone();
for &cnum in tcx.crates(()) {
implications.extend(tcx.stability_implications(cnum));
all_lib_features.extend(tcx.defined_lib_features(cnum).iter().map(|el| *el));
}
// Check that every feature referenced by an `implied_by` exists (for features defined in the
// local crate).
for (implied_by, feature) in tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE) {
// Only `implied_by` needs to be checked, `feature` is guaranteed to exist.
if !all_lib_features.contains_key(implied_by) {
let span = local_defined_features
.stable
.get(feature)
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(feature))
.expect("feature that implied another does not exist");
tcx.sess
.struct_span_err(
*span,
format!("feature `{implied_by}` implying `{feature}` does not exist"),
)
.emit();
}
}
if !remaining_lib_features.is_empty() {
for (feature, since) in all_lib_features.iter() {
if let Some(since) = since && let Some(span) = remaining_lib_features.get(&feature) {
// Warn if the user has enabled an already-stable lib feature.
if let Some(implies) = implications.get(&feature) {
unnecessary_partially_stable_feature_lint(tcx, *span, *feature, *implies, *since);
} else {
unnecessary_stable_feature_lint(tcx, *span, *feature, *since);
}
}
remaining_lib_features.remove(&feature);
@ -958,20 +998,6 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
break;
}
}
};
// We always collect the lib features declared in the current crate, even if there are
// no unknown features, because the collection also does feature attribute validation.
let local_defined_features = tcx.lib_features(()).to_vec();
if !remaining_lib_features.is_empty() {
check_features(&mut remaining_lib_features, &local_defined_features);
for &cnum in tcx.crates(()) {
if remaining_lib_features.is_empty() {
break;
}
check_features(&mut remaining_lib_features, tcx.defined_lib_features(cnum));
}
}
for (feature, span) in remaining_lib_features {
@ -982,12 +1008,41 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
// don't lint about unused features. We should re-enable this one day!
}
fn unnecessary_partially_stable_feature_lint(
tcx: TyCtxt<'_>,
span: Span,
feature: Symbol,
implies: Symbol,
since: Symbol,
) {
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
lint.build(&format!(
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
by the feature `{implies}`"
))
.span_suggestion(
span,
&format!(
"if you are using features which are still unstable, change to using `{implies}`"
),
implies,
Applicability::MaybeIncorrect,
)
.span_suggestion(
tcx.sess.source_map().span_extend_to_line(span),
"if you are using features which are now stable, remove this line",
"",
Applicability::MaybeIncorrect,
)
.emit();
});
}
fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) {
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
lint.build(&format!(
"the feature `{}` has been stable since {} and no longer requires \
an attribute to enable",
feature, since
"the feature `{feature}` has been stable since {since} and no longer requires an \
attribute to enable",
))
.emit();
});

View file

@ -2603,9 +2603,9 @@ fn show_candidates(
.skip(1)
.all(|(_, descr, _, _)| descr == descr_first)
{
descr_first.to_string()
descr_first
} else {
"item".to_string()
"item"
};
let plural_descr =
if descr.ends_with("s") { format!("{}es", descr) } else { format!("{}s", descr) };

View file

@ -796,9 +796,16 @@ impl<'a> Resolver<'a> {
) {
let span = path.span;
if let Some(stability) = &ext.stability {
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level
{
let feature = stability.feature;
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
let is_allowed = |feature| {
self.active_features.contains(&feature) || span.allows_unstable(feature)
};
let allowed_by_implication =
implied_by.map(|feature| is_allowed(feature)).unwrap_or(false);
if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer;
let soft_handler =
|lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);

View file

@ -718,6 +718,11 @@ impl SourceMap {
sp
}
/// Extends the given `Span` to contain the entire line it is on.
pub fn span_extend_to_line(&self, sp: Span) -> Span {
self.span_extend_to_prev_char(self.span_extend_to_next_char(sp, '\n', true), '\n', true)
}
/// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
/// `c`.
pub fn span_until_char(&self, sp: Span, c: char) -> Span {

View file

@ -800,6 +800,7 @@ symbols! {
impl_lint_pass,
impl_macros,
impl_trait_in_bindings,
implied_by,
import,
import_shadowing,
imported_main,

View file

@ -1757,19 +1757,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.flat_map(|a| a.args.iter())
{
if let hir::GenericArg::Type(hir_ty) = &arg {
if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
&hir_ty.kind
{
// Avoid ICE with associated types. As this is best
// effort only, it's ok to ignore the case. It
// would trigger in `is_send::<T::AssocType>();`
// from `typeck-default-trait-impl-assoc-type.rs`.
} else {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
let ty = self.resolve_vars_if_possible(ty);
if ty == predicate.self_ty() {
error.obligation.cause.span = hir_ty.span;
}
let ty = self.resolve_vars_if_possible(
self.typeck_results.borrow().node_type(hir_ty.hir_id),
);
if ty == predicate.self_ty() {
error.obligation.cause.span = hir_ty.span;
}
}
}

View file

@ -1484,7 +1484,7 @@ impl fmt::Debug for Literal {
}
/// Tracked access to environment variables.
#[unstable(feature = "proc_macro_tracked_env", issue = "74690")]
#[unstable(feature = "proc_macro_tracked_env", issue = "99515")]
pub mod tracked_env {
use std::env::{self, VarError};
use std::ffi::OsStr;
@ -1494,7 +1494,7 @@ pub mod tracked_env {
/// compilation, and will be able to rerun the build when the value of that variable changes.
/// Besides the dependency tracking this function should be equivalent to `env::var` from the
/// standard library, except that the argument must be UTF-8.
#[unstable(feature = "proc_macro_tracked_env", issue = "74690")]
#[unstable(feature = "proc_macro_tracked_env", issue = "99515")]
pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> {
let key: &str = key.as_ref();
let value = env::var(key);
@ -1504,13 +1504,13 @@ pub mod tracked_env {
}
/// Tracked access to additional files.
#[unstable(feature = "track_path", issue = "73921")]
#[unstable(feature = "track_path", issue = "99515")]
pub mod tracked_path {
/// Track a file explicitly.
///
/// Commonly used for tracking asset preprocessing.
#[unstable(feature = "track_path", issue = "73921")]
#[unstable(feature = "track_path", issue = "99515")]
pub fn path<P: AsRef<str>>(path: P) {
let path: &str = path.as_ref();
crate::bridge::client::FreeFunctions::track_path(path);

View file

@ -949,7 +949,7 @@ table,
#crate-search {
min-width: 115px;
margin-top: 5px;
padding-left: 0.3125em;
padding-left: 0.15em;
padding-right: 23px;
border: 1px solid;
border-radius: 4px;
@ -958,8 +958,6 @@ table,
-moz-appearance: none;
-webkit-appearance: none;
/* Removes default arrow from firefox */
text-indent: 0.01px;
text-overflow: "";
background-repeat: no-repeat;
background-color: transparent;
background-size: 20px;
@ -986,7 +984,6 @@ table,
border-radius: 2px;
padding: 8px;
font-size: 1rem;
transition: border-color 300ms ease;
width: 100%;
}

View file

@ -184,7 +184,13 @@ details.rustdoc-toggle > summary::before {
#crate-search, .search-input {
background-color: #141920;
/* Without the `!important`, the border-color is ignored for `<select>`... */
border-color: #424c57;
}
#crate-search {
/* Without the `!important`, the border-color is ignored for `<select>`...
It cannot be in the group above because `.search-input` has a different border color on
hover. */
border-color: #424c57 !important;
}

View file

@ -159,7 +159,13 @@ details.rustdoc-toggle > summary::before {
#crate-search, .search-input {
color: #111;
background-color: #f0f0f0;
/* Without the `!important`, the border-color is ignored for `<select>`... */
border-color: #f0f0f0;
}
#crate-search {
/* Without the `!important`, the border-color is ignored for `<select>`...
It cannot be in the group above because `.search-input` has a different border color on
hover. */
border-color: #f0f0f0 !important;
}

View file

@ -146,7 +146,13 @@ details.rustdoc-toggle > summary::before {
#crate-search, .search-input {
background-color: white;
/* Without the `!important`, the border-color is ignored for `<select>`... */
border-color: #e0e0e0;
}
#crate-search {
/* Without the `!important`, the border-color is ignored for `<select>`...
It cannot be in the group above because `.search-input` has a different border color on
hover. */
border-color: #e0e0e0 !important;
}

View file

@ -36,7 +36,8 @@ extern "C" {
}
// CHECK-LABEL: banana:
// x64: movb chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// On the next line LLVM 14 produces a `movb`, whereas LLVM 15+ produces a `movzbl`.
// x64: {{movb|movzbl}} chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// A64: adrp [[REG:[a-z0-9]+]], chaenomeles
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
#[no_mangle]
@ -47,7 +48,7 @@ pub fn banana() -> u8 {
}
// CHECK-LABEL: peach:
// x64: movb banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// x64: {{movb|movzbl}} banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
// A64: adrp [[REG2:[a-z0-9]+]], banana
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
#[no_mangle]
@ -59,7 +60,7 @@ pub fn peach() -> u8 {
// CHECK-LABEL: mango:
// x64: movq EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]]
// x64-NEXT: movb (%[[REG]]), %{{[a-z0-9]+}}
// x64-NEXT: {{movb|movzbl}} (%[[REG]]), %{{[a-z0-9]+}}
// A64: adrp [[REG2:[a-z0-9]+]], EXOCHORDA
// A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA]
#[no_mangle]

View file

@ -1,81 +0,0 @@
// Caveat - gdb doesn't know about UTF-32 character encoding and will print a
// rust char as only its numerical value.
// min-lldb-version: 310
// min-gdb-version: 8.0
// no-prefer-dynamic
// compile-flags:-g -C lto
// gdb-command:run
// gdbg-command:print 'basic_types_globals::B'
// gdbr-command:print B
// gdb-check:$1 = false
// gdbg-command:print 'basic_types_globals::I'
// gdbr-command:print I
// gdb-check:$2 = -1
// gdbg-command:print 'basic_types_globals::C'
// gdbr-command:print/d C
// gdbg-check:$3 = 97
// gdbr-check:$3 = 97
// gdbg-command:print/d 'basic_types_globals::I8'
// gdbr-command:print I8
// gdb-check:$4 = 68
// gdbg-command:print 'basic_types_globals::I16'
// gdbr-command:print I16
// gdb-check:$5 = -16
// gdbg-command:print 'basic_types_globals::I32'
// gdbr-command:print I32
// gdb-check:$6 = -32
// gdbg-command:print 'basic_types_globals::I64'
// gdbr-command:print I64
// gdb-check:$7 = -64
// gdbg-command:print 'basic_types_globals::U'
// gdbr-command:print U
// gdb-check:$8 = 1
// gdbg-command:print/d 'basic_types_globals::U8'
// gdbr-command:print U8
// gdb-check:$9 = 100
// gdbg-command:print 'basic_types_globals::U16'
// gdbr-command:print U16
// gdb-check:$10 = 16
// gdbg-command:print 'basic_types_globals::U32'
// gdbr-command:print U32
// gdb-check:$11 = 32
// gdbg-command:print 'basic_types_globals::U64'
// gdbr-command:print U64
// gdb-check:$12 = 64
// gdbg-command:print 'basic_types_globals::F32'
// gdbr-command:print F32
// gdb-check:$13 = 2.5
// gdbg-command:print 'basic_types_globals::F64'
// gdbr-command:print F64
// gdb-check:$14 = 3.5
// gdb-command:continue
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
// N.B. These are `mut` only so they don't constant fold away.
static mut B: bool = false;
static mut I: isize = -1;
static mut C: char = 'a';
static mut I8: i8 = 68;
static mut I16: i16 = -16;
static mut I32: i32 = -32;
static mut I64: i64 = -64;
static mut U: usize = 1;
static mut U8: u8 = 100;
static mut U16: u16 = 16;
static mut U32: u32 = 32;
static mut U64: u64 = 64;
static mut F32: f32 = 2.5;
static mut F64: f64 = 3.5;
fn main() {
_zzz(); // #break
let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) };
}
fn _zzz() {()}

View file

@ -4,7 +4,13 @@
// min-lldb-version: 310
// min-gdb-version: 8.0
// revisions: lto no-lto
// compile-flags:-g
// [lto] compile-flags:-C lto
// [lto] no-prefer-dynamic
// gdb-command:run
// gdbg-command:print 'basic_types_globals::B'
// gdbr-command:print B

View file

@ -0,0 +1,23 @@
// Ensures that the search input border color changes on focus.
goto: file://|DOC_PATH|/test_docs/index.html
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
reload:
assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
click: ".search-input"
focus: ".search-input"
assert-css: (".search-input", {"border-color": "rgb(0, 141, 253)"})
local-storage: {"rustdoc-theme": "light"}
reload:
assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
click: ".search-input"
assert-css: (".search-input", {"border-color": "rgb(102, 175, 233)"})
local-storage: {"rustdoc-theme": "ayu"}
reload:
assert-css: (".search-input", {"border-color": "rgb(66, 76, 87)"})
click: ".search-input"
assert-css: (".search-input", {"border-color": "rgb(66, 76, 87)"})

View file

@ -18,7 +18,7 @@ assert-css: (".search-results div.desc", {"width": "570px"})
size: (900, 900)
// First we check the current width and position.
assert-css: ("#crate-search", {"width": "222px"})
assert-css: ("#crate-search", {"width": "218px"})
compare-elements-position-near: (
"#crate-search",
"#search-settings .search-results-title",

View file

@ -86,6 +86,9 @@ tenth number: {}",
println!("{:foo}", 1); //~ ERROR unknown format trait `foo`
println!("{5} {:4$} {6:7$}", 1);
//~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
let foo = 1;
println!("{foo:0$}");
//~^ ERROR invalid reference to positional argument 0 (no arguments were given)
// We used to ICE here because we tried to unconditionally access the first argument, which
// doesn't exist.

View file

@ -251,8 +251,19 @@ LL | println!("{5} {:4$} {6:7$}", 1);
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error: invalid reference to positional argument 0 (no arguments were given)
--> $DIR/ifmt-bad-arg.rs:90:15
|
LL | println!("{foo:0$}");
| ^^^^^--^
| |
| this width flag expects an `usize` argument at position 0, but no arguments were given
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error: 2 positional arguments in format string, but no arguments were given
--> $DIR/ifmt-bad-arg.rs:92:15
--> $DIR/ifmt-bad-arg.rs:95:15
|
LL | println!("{:.*}");
| ^^--^
@ -328,7 +339,7 @@ LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
| ^^^^^^^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 36 previous errors
error: aborting due to 37 previous errors
Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`.

View file

@ -91,10 +91,10 @@ LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy`
error[E0277]: the trait bound `Box<dyn Dummy>: Copy` is not satisfied
--> $DIR/kindck-copy.rs:42:5
--> $DIR/kindck-copy.rs:42:19
|
LL | assert_copy::<Box<dyn Dummy>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy>`
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy>`
|
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
@ -103,10 +103,10 @@ LL | fn assert_copy<T:Copy>() { }
| ^^^^ required by this bound in `assert_copy`
error[E0277]: the trait bound `Box<dyn Dummy + Send>: Copy` is not satisfied
--> $DIR/kindck-copy.rs:43:5
--> $DIR/kindck-copy.rs:43:19
|
LL | assert_copy::<Box<dyn Dummy + Send>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy + Send>`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy + Send>`
|
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18

View file

@ -0,0 +1,12 @@
#![feature(macro_metavar_expr)]
macro_rules! metavar {
( $i:expr ) => {
${length(0)}
//~^ ERROR meta-variable expression `length` with depth parameter must be called inside of a macro repetition
};
}
const _: i32 = metavar!(0);
fn main() {}

View file

@ -0,0 +1,8 @@
error: meta-variable expression `length` with depth parameter must be called inside of a macro repetition
--> $DIR/meta-variable-depth-outside-repeat.rs:5:10
|
LL | ${length(0)}
| ^^^^^^^^^^^
error: aborting due to previous error

View file

@ -5,7 +5,7 @@ macro_rules! a {
(
${count(foo, 0)},
${count(foo, 10)},
//~^ ERROR count depth must be less than 4
//~^ ERROR depth parameter on meta-variable expression `count` must be less than 4
)
};
}
@ -17,7 +17,7 @@ macro_rules! b {
${ignore(foo)}
${index(0)},
${index(10)},
//~^ ERROR index depth must be less than 3
//~^ ERROR depth parameter on meta-variable expression `index` must be less than 3
)* )* )*
)
};
@ -30,15 +30,14 @@ macro_rules! c {
${ignore(foo)}
${length(0)}
${length(10)}
//~^ ERROR length depth must be less than 2
//~^ ERROR depth parameter on meta-variable expression `length` must be less than 2
)* )*
)
};
}
fn main() {
a!( { [ (a) ] [ (b c) ] } );
b!( { [ a b ] } );
c!( { a } );
c!({ a });
}

View file

@ -1,16 +1,16 @@
error: count depth must be less than 4
error: depth parameter on meta-variable expression `count` must be less than 4
--> $DIR/out-of-bounds-arguments.rs:7:14
|
LL | ${count(foo, 10)},
| ^^^^^^^^^^^^^^^^
error: index depth must be less than 3
error: depth parameter on meta-variable expression `index` must be less than 3
--> $DIR/out-of-bounds-arguments.rs:19:18
|
LL | ${index(10)},
| ^^^^^^^^^^^
error: length depth must be less than 2
error: depth parameter on meta-variable expression `length` must be less than 2
--> $DIR/out-of-bounds-arguments.rs:32:18
|
LL | ${length(10)}

View file

@ -1,8 +1,11 @@
error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
--> $DIR/not-panic-safe.rs:8:5
--> $DIR/not-panic-safe.rs:8:14
|
LL | assert::<&mut i32>();
| ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
| -^^^^^^^
| |
| `&mut i32` may not be safely transferred across an unwind boundary
| help: consider removing the leading `&`-reference
|
= help: the trait `UnwindSafe` is not implemented for `&mut i32`
= note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`

View file

@ -0,0 +1,8 @@
#![feature(staged_api)]
#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
#[stable(feature = "foo", since = "1.62.0")]
pub fn foo() {}
#[unstable(feature = "foobar", issue = "1", implied_by = "foo")]
pub fn foobar() {}

View file

@ -0,0 +1,10 @@
#![feature(staged_api)]
#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
// Tests that `implied_by = "bar"` results in an error being emitted if `bar` does not exist.
#[unstable(feature = "foobar", issue = "1", implied_by = "bar")]
//~^ ERROR feature `bar` implying `foobar` does not exist
pub fn foobar() {}
fn main() {}

View file

@ -0,0 +1,8 @@
error: feature `bar` implying `foobar` does not exist
--> $DIR/stability-attribute-implies-missing.rs:6:1
|
LL | #[unstable(feature = "foobar", issue = "1", implied_by = "bar")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,13 @@
// aux-build:stability-attribute-implies.rs
// Tests that despite the `foobar` feature being implied by now-stable feature `foo`, if `foobar`
// isn't allowed in this crate then an error will be emitted.
extern crate stability_attribute_implies;
use stability_attribute_implies::{foo, foobar};
//~^ ERROR use of unstable library feature 'foobar'
fn main() {
foo(); // no error - stable
foobar(); //~ ERROR use of unstable library feature 'foobar'
}

View file

@ -0,0 +1,21 @@
error[E0658]: use of unstable library feature 'foobar'
--> $DIR/stability-attribute-implies-no-feature.rs:7:40
|
LL | use stability_attribute_implies::{foo, foobar};
| ^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(foobar)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'foobar'
--> $DIR/stability-attribute-implies-no-feature.rs:12:5
|
LL | foobar();
| ^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(foobar)]` to the crate attributes to enable
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,15 @@
// aux-build:stability-attribute-implies.rs
#![deny(stable_features)]
#![feature(foo)]
//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic
// mentioning partial stabilization, and that given the implied unstable feature is unused (there
// is no `foobar` call), that the compiler suggests removing the flag.
extern crate stability_attribute_implies;
use stability_attribute_implies::foo;
fn main() {
foo();
}

View file

@ -0,0 +1,22 @@
error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
--> $DIR/stability-attribute-implies-using-stable.rs:3:12
|
LL | #![feature(foo)]
| ^^^
|
note: the lint level is defined here
--> $DIR/stability-attribute-implies-using-stable.rs:2:9
|
LL | #![deny(stable_features)]
| ^^^^^^^^^^^^^^^
help: if you are using features which are still unstable, change to using `foobar`
|
LL | #![feature(foobar)]
| ~~~~~~
help: if you are using features which are now stable, remove this line
|
LL - #![feature(foo)]
|
error: aborting due to previous error

View file

@ -0,0 +1,17 @@
// aux-build:stability-attribute-implies.rs
#![deny(stable_features)]
#![feature(foo)]
//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic
// mentioning partial stabilization and that given the implied unstable feature is used (there is a
// `foobar` call), that the compiler suggests changing to that feature and doesn't error about its
// use.
extern crate stability_attribute_implies;
use stability_attribute_implies::{foo, foobar};
fn main() {
foo();
foobar(); // no error!
}

View file

@ -0,0 +1,22 @@
error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
--> $DIR/stability-attribute-implies-using-unstable.rs:3:12
|
LL | #![feature(foo)]
| ^^^
|
note: the lint level is defined here
--> $DIR/stability-attribute-implies-using-unstable.rs:2:9
|
LL | #![deny(stable_features)]
| ^^^^^^^^^^^^^^^
help: if you are using features which are still unstable, change to using `foobar`
|
LL | #![feature(foobar)]
| ~~~~~~
help: if you are using features which are now stable, remove this line
|
LL - #![feature(foo)]
|
error: aborting due to previous error

View file

@ -8,7 +8,7 @@ error[E0541]: unknown meta item 'sinse'
--> $DIR/stability-attribute-sanity-2.rs:10:25
|
LL | #[stable(feature = "a", sinse = "1.0.0")]
| ^^^^^^^^^^^^^^^ expected one of `since`, `note`
| ^^^^^^^^^^^^^^^ expected one of `feature`, `since`
error[E0545]: `issue` must be a non-zero numeric string or "none"
--> $DIR/stability-attribute-sanity-2.rs:13:27

View file

@ -14,7 +14,7 @@ error[E0541]: unknown meta item 'reason'
--> $DIR/stability-attribute-sanity.rs:8:42
|
LL | #[stable(feature = "a", since = "b", reason)]
| ^^^^^^ expected one of `since`, `note`
| ^^^^^^ expected one of `feature`, `since`
error[E0539]: incorrect meta item
--> $DIR/stability-attribute-sanity.rs:11:29

View file

@ -7,6 +7,5 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() {
size_of_copy::<dyn Misc + Copy>();
//~^ ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR the trait bound `dyn Misc: Copy` is not satisfied
}

View file

@ -9,22 +9,11 @@ LL | size_of_copy::<dyn Misc + Copy>();
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/issue-32963.rs:8:31
|
LL | size_of_copy::<dyn Misc + Copy>();
| ---- ^^^^ additional non-auto trait
| |
| first non-auto trait
|
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied
--> $DIR/issue-32963.rs:8:5
--> $DIR/issue-32963.rs:8:20
|
LL | size_of_copy::<dyn Misc + Copy>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc`
| ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc`
|
note: required by a bound in `size_of_copy`
--> $DIR/issue-32963.rs:5:20
@ -32,7 +21,7 @@ note: required by a bound in `size_of_copy`
LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
| ^^^^ required by this bound in `size_of_copy`
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0225, E0277.
For more information about an error, try `rustc --explain E0225`.

View file

@ -85,10 +85,10 @@ LL | pub const fn size_of<T>() -> usize {
| ^ required by this bound in `std::mem::size_of`
error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
--> $DIR/suggest-where-clause.rs:31:5
--> $DIR/suggest-where-clause.rs:31:20
|
LL | mem::size_of::<[&U]>();
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[&U]`
note: required by a bound in `std::mem::size_of`

View file

@ -1,8 +1,8 @@
error[E0277]: `<T as Trait>::AssocType` cannot be sent between threads safely
--> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5
--> $DIR/typeck-default-trait-impl-assoc-type.rs:11:15
|
LL | is_send::<T::AssocType>();
| ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
| ^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `<T as Trait>::AssocType`
note: required by a bound in `is_send`

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
--> $DIR/unboxed-closure-sugar-default.rs:21:5
--> $DIR/unboxed-closure-sugar-default.rs:21:10
|
LL | eq::<dyn Foo<(isize,), isize, Output=()>, dyn Foo(isize)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
|
note: required by a bound in `eq`
--> $DIR/unboxed-closure-sugar-default.rs:14:40

View file

@ -42,7 +42,7 @@ fn test<'a,'b>() {
// Errors expected:
eq::< dyn Foo<(),Output=()>,
dyn Foo(char) >();
//~^^ ERROR E0277
//~^ ERROR E0277
}
fn main() { }

View file

@ -1,9 +1,8 @@
error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
--> $DIR/unboxed-closure-sugar-equiv.rs:43:5
--> $DIR/unboxed-closure-sugar-equiv.rs:44:11
|
LL | / eq::< dyn Foo<(),Output=()>,
LL | | dyn Foo(char) >();
| |_______________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
LL | dyn Foo(char) >();
| ^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
|
note: required by a bound in `eq`
--> $DIR/unboxed-closure-sugar-equiv.rs:16:28

View file

@ -535,6 +535,29 @@ impl TestProps {
}
}
pub fn line_directive<'line>(
comment: &str,
ln: &'line str,
) -> Option<(Option<&'line str>, &'line str)> {
if ln.starts_with(comment) {
let ln = ln[comment.len()..].trim_start();
if ln.starts_with('[') {
// A comment like `//[foo]` is specific to revision `foo`
if let Some(close_brace) = ln.find(']') {
let lncfg = &ln[1..close_brace];
Some((Some(lncfg), ln[(close_brace + 1)..].trim_start()))
} else {
panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln)
}
} else {
Some((None, ln))
}
} else {
None
}
}
fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str)) {
if testfile.is_dir() {
return;
@ -557,17 +580,8 @@ fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>
let ln = ln.trim();
if ln.starts_with("fn") || ln.starts_with("mod") {
return;
} else if ln.starts_with(comment) && ln[comment.len()..].trim_start().starts_with('[') {
// A comment like `//[foo]` is specific to revision `foo`
if let Some(close_brace) = ln.find(']') {
let open_brace = ln.find('[').unwrap();
let lncfg = &ln[open_brace + 1..close_brace];
it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
} else {
panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln)
}
} else if ln.starts_with(comment) {
it(None, ln[comment.len()..].trim_start());
} else if let Some((lncfg, ln)) = line_directive(comment, ln) {
it(lncfg, ln);
}
}
}

View file

@ -648,8 +648,6 @@ impl<'test> TestCx<'test> {
}
fn run_debuginfo_cdb_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
let config = Config {
target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
@ -695,7 +693,12 @@ impl<'test> TestCx<'test> {
// Parse debugger commands etc from test files
let DebuggerCommands { commands, check_lines, breakpoint_lines, .. } =
match DebuggerCommands::parse_from(&self.testpaths.file, self.config, prefixes) {
match DebuggerCommands::parse_from(
&self.testpaths.file,
self.config,
prefixes,
self.revision,
) {
Ok(cmds) => cmds,
Err(e) => self.fatal(&e),
};
@ -756,8 +759,6 @@ impl<'test> TestCx<'test> {
}
fn run_debuginfo_gdb_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
let config = Config {
target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
@ -783,7 +784,12 @@ impl<'test> TestCx<'test> {
};
let DebuggerCommands { commands, check_lines, breakpoint_lines } =
match DebuggerCommands::parse_from(&self.testpaths.file, self.config, prefixes) {
match DebuggerCommands::parse_from(
&self.testpaths.file,
self.config,
prefixes,
self.revision,
) {
Ok(cmds) => cmds,
Err(e) => self.fatal(&e),
};
@ -1005,8 +1011,6 @@ impl<'test> TestCx<'test> {
}
fn run_debuginfo_lldb_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
if self.config.lldb_python_dir.is_none() {
self.fatal("Can't run LLDB test because LLDB's python path is not set.");
}
@ -1059,7 +1063,12 @@ impl<'test> TestCx<'test> {
// Parse debugger commands etc from test files
let DebuggerCommands { commands, check_lines, breakpoint_lines, .. } =
match DebuggerCommands::parse_from(&self.testpaths.file, self.config, prefixes) {
match DebuggerCommands::parse_from(
&self.testpaths.file,
self.config,
prefixes,
self.revision,
) {
Ok(cmds) => cmds,
Err(e) => self.fatal(&e),
};

View file

@ -1,4 +1,5 @@
use crate::common::Config;
use crate::header::line_directive;
use crate::runtest::ProcRes;
use std::fs::File;
@ -16,6 +17,7 @@ impl DebuggerCommands {
file: &Path,
config: &Config,
debugger_prefixes: &[&str],
rev: Option<&str>,
) -> Result<Self, String> {
let directives = debugger_prefixes
.iter()
@ -25,13 +27,19 @@ impl DebuggerCommands {
let mut breakpoint_lines = vec![];
let mut commands = vec![];
let mut check_lines = vec![];
let mut counter = 1;
let mut counter = 0;
let reader = BufReader::new(File::open(file).unwrap());
for line in reader.lines() {
counter += 1;
match line {
Ok(line) => {
let line =
if line.starts_with("//") { line[2..].trim_start() } else { line.as_str() };
let (lnrev, line) = line_directive("//", &line).unwrap_or((None, &line));
// Skip any revision specific directive that doesn't match the current
// revision being tested
if lnrev.is_some() && lnrev != rev {
continue;
}
if line.contains("#break") {
breakpoint_lines.push(counter);
@ -49,7 +57,6 @@ impl DebuggerCommands {
}
Err(e) => return Err(format!("Error while parsing debugger commands: {}", e)),
}
counter += 1;
}
Ok(Self { commands, check_lines, breakpoint_lines })