mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Auto merge of #100810 - matthiaskrgr:rollup-xep778s, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #97963 (net listen backlog set to negative on Linux.) - #99935 (Reenable disabled early syntax gates as future-incompatibility lints) - #100129 (add miri-test-libstd support to libstd) - #100500 (Ban references to `Self` in trait object substs for projection predicates too.) - #100636 (Revert "Revert "Allow dynamic linking for iOS/tvOS targets."") - #100718 ([rustdoc] Fix item info display) - #100769 (Suggest adding a reference to a trait assoc item) - #100777 (elaborate how revisions work with FileCheck stuff in src/test/codegen) - #100796 (Refactor: remove unnecessary string searchings) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
878aef79dc
@ -2,10 +2,10 @@ use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd, VariantData};
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
use rustc_errors::{struct_span_err, Applicability, StashKey};
|
||||
use rustc_feature::Features;
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_feature::{Features, GateIssue};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue};
|
||||
use rustc_session::parse::{feature_err, feature_warn};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -20,9 +20,7 @@ macro_rules! gate_feature_fn {
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
|
||||
.help(help)
|
||||
.emit();
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
|
||||
}
|
||||
}};
|
||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
@ -31,8 +29,19 @@ macro_rules! gate_feature_fn {
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
|
||||
.emit();
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
|
||||
}
|
||||
}};
|
||||
(future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
let (visitor, has_feature, span, name, explain) =
|
||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!(
|
||||
"gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
|
||||
name, span, has_feature
|
||||
);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_warn(&visitor.sess.parse_sess, name, span, explain);
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -44,6 +53,9 @@ macro_rules! gate_feature_post {
|
||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
(future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
||||
@ -588,11 +600,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
{
|
||||
// When we encounter a statement of the form `foo: Ty = val;`, this will emit a type
|
||||
// ascription error, but the likely intention was to write a `let` statement. (#78907).
|
||||
feature_err_issue(
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::type_ascription,
|
||||
lhs.span,
|
||||
GateIssue::Language,
|
||||
"type ascription is experimental",
|
||||
).span_suggestion_verbose(
|
||||
lhs.span.shrink_to_lo(),
|
||||
@ -615,15 +626,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
);
|
||||
}
|
||||
ast::ExprKind::Type(..) => {
|
||||
// To avoid noise about type ascription in common syntax errors, only emit if it
|
||||
// is the *only* error.
|
||||
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error.
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
type_ascription,
|
||||
e.span,
|
||||
"type ascription is experimental"
|
||||
);
|
||||
} else {
|
||||
// And if it isn't, cancel the early-pass warning.
|
||||
self.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.steal_diagnostic(e.span, StashKey::EarlySyntaxWarning)
|
||||
.map(|err| err.cancel());
|
||||
}
|
||||
}
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
@ -789,14 +807,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
|
||||
// All uses of `gate_all!` below this point were added in #65742,
|
||||
// and subsequently disabled (with the non-early gating readded).
|
||||
// We emit an early future-incompatible warning for these.
|
||||
// New syntax gates should go above here to get a hard error gate.
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal) => {
|
||||
// FIXME(eddyb) do something more useful than always
|
||||
// disabling these uses of early feature-gatings.
|
||||
if false {
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(&visitor, $gate, *span, $msg);
|
||||
}
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -809,11 +825,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all!(label_break_value, "labels on blocks are unstable");
|
||||
gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error. (Also check it last.)
|
||||
if sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
}
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
@ -459,6 +459,7 @@ struct HandlerInner {
|
||||
pub enum StashKey {
|
||||
ItemNoType,
|
||||
UnderscoreForArrayLengths,
|
||||
EarlySyntaxWarning,
|
||||
}
|
||||
|
||||
fn default_track_diagnostic(_: &Diagnostic) {}
|
||||
@ -626,19 +627,13 @@ impl Handler {
|
||||
/// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing.
|
||||
pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
|
||||
// if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
|
||||
// See the PR for a discussion.
|
||||
inner.stashed_diagnostics.insert((span, key), diag);
|
||||
inner.stash((span, key), diag);
|
||||
}
|
||||
|
||||
/// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
|
||||
pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.stashed_diagnostics
|
||||
.remove(&(span, key))
|
||||
.map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
|
||||
}
|
||||
|
||||
/// Emit all stashed diagnostics.
|
||||
@ -1106,13 +1101,31 @@ impl HandlerInner {
|
||||
|
||||
/// Emit all stashed diagnostics.
|
||||
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
|
||||
let has_errors = self.has_errors();
|
||||
let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
|
||||
let mut reported = None;
|
||||
for mut diag in diags {
|
||||
// Decrement the count tracking the stash; emitting will increment it.
|
||||
if diag.is_error() {
|
||||
reported = Some(ErrorGuaranteed(()));
|
||||
if matches!(diag.level, Level::Error { lint: true }) {
|
||||
self.lint_err_count -= 1;
|
||||
} else {
|
||||
self.err_count -= 1;
|
||||
}
|
||||
} else {
|
||||
if diag.is_force_warn() {
|
||||
self.warn_count -= 1;
|
||||
} else {
|
||||
// Unless they're forced, don't flush stashed warnings when
|
||||
// there are errors, to avoid causing warning overload. The
|
||||
// stash would've been stolen already if it were important.
|
||||
if has_errors {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.emit_diagnostic(&mut diag);
|
||||
let reported_this = self.emit_diagnostic(&mut diag);
|
||||
reported = reported.or(reported_this);
|
||||
}
|
||||
reported
|
||||
}
|
||||
@ -1302,9 +1315,47 @@ impl HandlerInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn stash(&mut self, key: (Span, StashKey), diagnostic: Diagnostic) {
|
||||
// Track the diagnostic for counts, but don't panic-if-treat-err-as-bug
|
||||
// yet; that happens when we actually emit the diagnostic.
|
||||
if diagnostic.is_error() {
|
||||
if matches!(diagnostic.level, Level::Error { lint: true }) {
|
||||
self.lint_err_count += 1;
|
||||
} else {
|
||||
self.err_count += 1;
|
||||
}
|
||||
} else {
|
||||
// Warnings are only automatically flushed if they're forced.
|
||||
if diagnostic.is_force_warn() {
|
||||
self.warn_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
|
||||
// if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
|
||||
// See the PR for a discussion.
|
||||
self.stashed_diagnostics.insert(key, diagnostic);
|
||||
}
|
||||
|
||||
fn steal(&mut self, key: (Span, StashKey)) -> Option<Diagnostic> {
|
||||
let diagnostic = self.stashed_diagnostics.remove(&key)?;
|
||||
if diagnostic.is_error() {
|
||||
if matches!(diagnostic.level, Level::Error { lint: true }) {
|
||||
self.lint_err_count -= 1;
|
||||
} else {
|
||||
self.err_count -= 1;
|
||||
}
|
||||
} else {
|
||||
if diagnostic.is_force_warn() {
|
||||
self.warn_count -= 1;
|
||||
}
|
||||
}
|
||||
Some(diagnostic)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn err_count(&self) -> usize {
|
||||
self.err_count + self.stashed_diagnostics.len()
|
||||
self.err_count
|
||||
}
|
||||
|
||||
fn has_errors(&self) -> bool {
|
||||
|
@ -3212,6 +3212,56 @@ declare_lint! {
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unstable_syntax_pre_expansion` lint detects the use of unstable
|
||||
/// syntax that is discarded during attribute expansion.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[cfg(FALSE)]
|
||||
/// macro foo() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The input to active attributes such as `#[cfg]` or procedural macro
|
||||
/// attributes is required to be valid syntax. Previously, the compiler only
|
||||
/// gated the use of unstable syntax features after resolving `#[cfg]` gates
|
||||
/// and expanding procedural macros.
|
||||
///
|
||||
/// To avoid relying on unstable syntax, move the use of unstable syntax
|
||||
/// into a position where the compiler does not parse the syntax, such as a
|
||||
/// functionlike macro.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![deny(unstable_syntax_pre_expansion)]
|
||||
///
|
||||
/// macro_rules! identity {
|
||||
/// ( $($tokens:tt)* ) => { $($tokens)* }
|
||||
/// }
|
||||
///
|
||||
/// #[cfg(FALSE)]
|
||||
/// identity! {
|
||||
/// macro foo() {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this
|
||||
/// to a hard error in the future. See [issue #65860] for more details.
|
||||
///
|
||||
/// [issue #65860]: https://github.com/rust-lang/rust/issues/65860
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub UNSTABLE_SYNTAX_PRE_EXPANSION,
|
||||
Warn,
|
||||
"unstable syntax can change at any point in the future, causing a hard error!",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #65860 <https://github.com/rust-lang/rust/issues/65860>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// that are used by other parts of the compiler.
|
||||
@ -3280,6 +3330,7 @@ declare_lint_pass! {
|
||||
POINTER_STRUCTURAL_MATCH,
|
||||
NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
SOFT_UNSTABLE,
|
||||
UNSTABLE_SYNTAX_PRE_EXPANSION,
|
||||
INLINE_NO_SANITIZE,
|
||||
BAD_ASM_STYLE,
|
||||
ASM_SUB_REGISTER,
|
||||
|
@ -2,15 +2,17 @@
|
||||
//! It also serves as an input to the parser itself.
|
||||
|
||||
use crate::config::CheckCfg;
|
||||
use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
|
||||
use crate::lint::{
|
||||
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
|
||||
};
|
||||
use crate::SessionDiagnostic;
|
||||
use rustc_ast::node_id::NodeId;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
|
||||
use rustc_errors::{
|
||||
error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder,
|
||||
DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
|
||||
DiagnosticMessage, ErrorGuaranteed, MultiSpan, StashKey,
|
||||
};
|
||||
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
|
||||
use rustc_span::edition::Edition;
|
||||
@ -101,11 +103,58 @@ pub fn feature_err_issue<'a>(
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let span = span.into();
|
||||
|
||||
// Cancel an earlier warning for this same error, if it exists.
|
||||
if let Some(span) = span.primary_span() {
|
||||
sess.span_diagnostic
|
||||
.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
|
||||
.map(|err| err.cancel());
|
||||
}
|
||||
|
||||
let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
||||
err
|
||||
}
|
||||
|
||||
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explain: &str) {
|
||||
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
||||
}
|
||||
|
||||
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
///
|
||||
/// This variant allows you to control whether it is a library or language feature.
|
||||
/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
|
||||
pub fn feature_warn_issue<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: Span,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) {
|
||||
let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
||||
|
||||
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
|
||||
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
|
||||
let future_incompatible = lint.future_incompatible.as_ref().unwrap();
|
||||
err.code(DiagnosticId::Lint {
|
||||
name: lint.name_lower(),
|
||||
has_future_breakage: false,
|
||||
is_force_warn: false,
|
||||
});
|
||||
err.warn(lint.desc);
|
||||
err.note(format!("for more information, see {}", future_incompatible.reference));
|
||||
|
||||
// A later feature_err call can steal and cancel this warning.
|
||||
err.stash(span, StashKey::EarlySyntaxWarning);
|
||||
}
|
||||
|
||||
/// Adds the diagnostics for a feature to an existing error.
|
||||
pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, feature: Symbol) {
|
||||
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
|
||||
|
@ -65,7 +65,6 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
|
||||
TargetOptions {
|
||||
abi: target_abi(arch).into(),
|
||||
cpu: target_cpu(arch).into(),
|
||||
dynamic_linking: false,
|
||||
link_env_remove: link_env_remove(arch),
|
||||
has_thread_local: false,
|
||||
..super::apple_base::opts(os, target_arch_name(arch), target_abi(arch))
|
||||
|
@ -671,7 +671,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> bool {
|
||||
// It only make sense when suggesting dereferences for arguments
|
||||
let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else {
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else {
|
||||
return false;
|
||||
};
|
||||
let param_env = obligation.param_env;
|
||||
@ -702,19 +702,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
|
||||
}) {
|
||||
if steps > 0 {
|
||||
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
// Don't care about `&mut` because `DerefMut` is used less
|
||||
// often and user will not expect autoderef happens.
|
||||
if src.starts_with('&') && !src.starts_with("&mut ") {
|
||||
let derefs = "*".repeat(steps);
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider dereferencing here",
|
||||
format!("&{}{}", derefs, &src[1..]),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// Don't care about `&mut` because `DerefMut` is used less
|
||||
// often and user will not expect autoderef happens.
|
||||
if let Some(hir::Node::Expr(hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),
|
||||
..
|
||||
})) = self.tcx.hir().find(*arg_hir_id)
|
||||
{
|
||||
let derefs = "*".repeat(steps);
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_lo(),
|
||||
"consider dereferencing here",
|
||||
derefs,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if real_trait_pred != trait_pred {
|
||||
@ -882,6 +885,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
obligation.cause.code()
|
||||
{
|
||||
&parent_code
|
||||
} else if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code() {
|
||||
obligation.cause.code()
|
||||
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
|
||||
span.ctxt().outer_expn_data().kind
|
||||
{
|
||||
@ -930,10 +935,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
|
||||
self.predicate_must_hold_modulo_regions(&obligation)
|
||||
};
|
||||
let imm_result = mk_result(trait_pred_and_imm_ref);
|
||||
let mut_result = mk_result(trait_pred_and_mut_ref);
|
||||
let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
|
||||
let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
|
||||
|
||||
if imm_result || mut_result {
|
||||
let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
|
||||
if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code()
|
||||
&& let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
|
||||
{
|
||||
(
|
||||
mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
|
||||
matches!(mutability, hir::Mutability::Mut),
|
||||
)
|
||||
} else {
|
||||
(false, false)
|
||||
};
|
||||
|
||||
if imm_ref_self_ty_satisfies_pred
|
||||
|| mut_ref_self_ty_satisfies_pred
|
||||
|| ref_inner_ty_satisfies_pred
|
||||
{
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
// We have a very specific type of error, where just borrowing this argument
|
||||
// might solve the problem. In cases like this, the important part is the
|
||||
@ -973,7 +993,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// }
|
||||
// ```
|
||||
|
||||
if imm_result && mut_result {
|
||||
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
|
||||
err.span_suggestions(
|
||||
span.shrink_to_lo(),
|
||||
"consider borrowing here",
|
||||
@ -981,13 +1001,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
&format!(
|
||||
"consider{} borrowing here",
|
||||
if mut_result { " mutably" } else { "" }
|
||||
if is_mut { " mutably" } else { "" }
|
||||
),
|
||||
format!("&{}", if mut_result { "mut " } else { "" }),
|
||||
format!("&{}", if is_mut { "mut " } else { "" }),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -1001,7 +1022,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
|
||||
try_borrowing(cause.derived.parent_trait_pred, &[])
|
||||
} else if let ObligationCauseCode::BindingObligation(_, _)
|
||||
| ObligationCauseCode::ItemObligation(_) = code
|
||||
| ObligationCauseCode::ItemObligation(..) = code
|
||||
{
|
||||
try_borrowing(poly_trait_pred, &never_suggest_borrow)
|
||||
} else {
|
||||
|
@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::astconv_object_safety_violations;
|
||||
@ -1453,21 +1453,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
.enumerate()
|
||||
.skip(1) // Remove `Self` for `ExistentialPredicate`.
|
||||
.map(|(index, arg)| {
|
||||
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
|
||||
debug!(?ty);
|
||||
if ty == dummy_self {
|
||||
let param = &generics.params[index];
|
||||
missing_type_params.push(param.name);
|
||||
tcx.ty_error().into()
|
||||
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
|
||||
references_self = true;
|
||||
tcx.ty_error().into()
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
} else {
|
||||
arg
|
||||
if arg == dummy_self.into() {
|
||||
let param = &generics.params[index];
|
||||
missing_type_params.push(param.name);
|
||||
return tcx.ty_error().into();
|
||||
} else if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
references_self = true;
|
||||
return tcx.ty_error().into();
|
||||
}
|
||||
arg
|
||||
})
|
||||
.collect();
|
||||
let substs = tcx.intern_substs(&substs[..]);
|
||||
@ -1506,13 +1500,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
});
|
||||
|
||||
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
if b.projection_ty.self_ty() != dummy_self {
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
|
||||
);
|
||||
bound.map_bound(|mut b| {
|
||||
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
||||
|
||||
// Like for trait refs, verify that `dummy_self` did not leak inside default type
|
||||
// parameters.
|
||||
let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
|
||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
});
|
||||
if references_self {
|
||||
tcx.sess
|
||||
.delay_span_bug(span, "trait object projection bounds reference `Self`");
|
||||
let substs: Vec<_> = b
|
||||
.projection_ty
|
||||
.substs
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
return tcx.ty_error().into();
|
||||
}
|
||||
arg
|
||||
})
|
||||
.collect();
|
||||
b.projection_ty.substs = tcx.intern_substs(&substs[..]);
|
||||
}
|
||||
|
||||
ty::ExistentialProjection::erase_self_ty(tcx, b)
|
||||
})
|
||||
});
|
||||
|
@ -56,10 +56,6 @@
|
||||
//! [`Rc`]: rc
|
||||
//! [`RefCell`]: core::cell
|
||||
|
||||
// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
|
||||
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
|
||||
// rustc itself never sets the feature, so this line has no affect there.
|
||||
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
|
||||
#![allow(unused_attributes)]
|
||||
#![stable(feature = "alloc", since = "1.36.0")]
|
||||
#![doc(
|
||||
@ -77,6 +73,10 @@
|
||||
))]
|
||||
#![no_std]
|
||||
#![needs_allocator]
|
||||
// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
|
||||
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
|
||||
// rustc itself never sets the feature, so this line has no affect there.
|
||||
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
|
||||
//
|
||||
// Lints:
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
@ -618,3 +618,22 @@ fn test_arc_cyclic_two_refs() {
|
||||
assert_eq!(Arc::strong_count(&two_refs), 3);
|
||||
assert_eq!(Arc::weak_count(&two_refs), 2);
|
||||
}
|
||||
|
||||
/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005)
|
||||
#[test]
|
||||
#[cfg(miri)] // relies on Stacked Borrows in Miri
|
||||
fn arc_drop_dereferenceable_race() {
|
||||
// The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9).
|
||||
for _ in 0..750 {
|
||||
let arc_1 = Arc::new(());
|
||||
let arc_2 = arc_1.clone();
|
||||
let thread = thread::spawn(|| drop(arc_2));
|
||||
// Spin a bit; makes the race more likely to appear
|
||||
let mut i = 0;
|
||||
while i < 256 {
|
||||
i += 1;
|
||||
}
|
||||
drop(arc_1);
|
||||
thread.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -268,10 +268,13 @@ fn test_lots_of_insertions() {
|
||||
|
||||
// Try this a few times to make sure we never screw up the hashmap's
|
||||
// internal state.
|
||||
for _ in 0..10 {
|
||||
let loops = if cfg!(miri) { 2 } else { 10 };
|
||||
for _ in 0..loops {
|
||||
assert!(m.is_empty());
|
||||
|
||||
for i in 1..1001 {
|
||||
let count = if cfg!(miri) { 101 } else { 1001 };
|
||||
|
||||
for i in 1..count {
|
||||
assert!(m.insert(i, i).is_none());
|
||||
|
||||
for j in 1..=i {
|
||||
@ -279,42 +282,42 @@ fn test_lots_of_insertions() {
|
||||
assert_eq!(r, Some(&j));
|
||||
}
|
||||
|
||||
for j in i + 1..1001 {
|
||||
for j in i + 1..count {
|
||||
let r = m.get(&j);
|
||||
assert_eq!(r, None);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 1001..2001 {
|
||||
for i in count..(2 * count) {
|
||||
assert!(!m.contains_key(&i));
|
||||
}
|
||||
|
||||
// remove forwards
|
||||
for i in 1..1001 {
|
||||
for i in 1..count {
|
||||
assert!(m.remove(&i).is_some());
|
||||
|
||||
for j in 1..=i {
|
||||
assert!(!m.contains_key(&j));
|
||||
}
|
||||
|
||||
for j in i + 1..1001 {
|
||||
for j in i + 1..count {
|
||||
assert!(m.contains_key(&j));
|
||||
}
|
||||
}
|
||||
|
||||
for i in 1..1001 {
|
||||
for i in 1..count {
|
||||
assert!(!m.contains_key(&i));
|
||||
}
|
||||
|
||||
for i in 1..1001 {
|
||||
for i in 1..count {
|
||||
assert!(m.insert(i, i).is_none());
|
||||
}
|
||||
|
||||
// remove backwards
|
||||
for i in (1..1001).rev() {
|
||||
for i in (1..count).rev() {
|
||||
assert!(m.remove(&i).is_some());
|
||||
|
||||
for j in i..1001 {
|
||||
for j in i..count {
|
||||
assert!(!m.contains_key(&j));
|
||||
}
|
||||
|
||||
@ -817,6 +820,7 @@ fn test_retain() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
|
||||
#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
|
||||
fn test_try_reserve() {
|
||||
let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
|
||||
|
@ -94,7 +94,7 @@ fn read_to_end() {
|
||||
assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
|
||||
assert_eq!(v, b"1");
|
||||
|
||||
let cap = 1024 * 1024;
|
||||
let cap = if cfg!(miri) { 1024 } else { 1024 * 1024 };
|
||||
let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
|
||||
let mut v = Vec::new();
|
||||
let (a, b) = data.split_at(data.len() / 2);
|
||||
@ -309,6 +309,7 @@ fn chain_zero_length_read_is_not_eof() {
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_read_to_end(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let mut lr = repeat(1).take(10000000);
|
||||
|
@ -187,6 +187,7 @@
|
||||
//! [rust-discord]: https://discord.gg/rust-lang
|
||||
//! [array]: prim@array
|
||||
//! [slice]: prim@slice
|
||||
|
||||
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
|
||||
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
|
||||
#![doc(
|
||||
@ -201,25 +202,35 @@
|
||||
no_global_oom_handling,
|
||||
not(no_global_oom_handling)
|
||||
))]
|
||||
// To run libstd tests without x.py without ending up with two copies of libstd, Miri needs to be
|
||||
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
|
||||
// rustc itself never sets the feature, so this line has no affect there.
|
||||
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
|
||||
// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
|
||||
#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
|
||||
// Don't link to std. We are std.
|
||||
#![no_std]
|
||||
// Tell the compiler to link to either panic_abort or panic_unwind
|
||||
#![needs_panic_runtime]
|
||||
//
|
||||
// Lints:
|
||||
#![warn(deprecated_in_future)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![allow(unused_lifetimes)]
|
||||
// Tell the compiler to link to either panic_abort or panic_unwind
|
||||
#![needs_panic_runtime]
|
||||
#![deny(rustc::existing_doc_keyword)]
|
||||
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
|
||||
#![deny(ffi_unwind_calls)]
|
||||
// std may use features in a platform-specific way
|
||||
#![allow(unused_features)]
|
||||
//
|
||||
// Features:
|
||||
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
|
||||
#![cfg_attr(
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
||||
)]
|
||||
#![deny(rustc::existing_doc_keyword)]
|
||||
//
|
||||
// Language features:
|
||||
#![feature(alloc_error_handler)]
|
||||
|
@ -73,9 +73,13 @@ impl UnixListener {
|
||||
unsafe {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
#[cfg(target_os = "linux")]
|
||||
const backlog: libc::c_int = -1;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const backlog: libc::c_int = 128;
|
||||
|
||||
cvt(libc::bind(inner.as_inner().as_raw_fd(), &addr as *const _ as *const _, len as _))?;
|
||||
cvt(libc::listen(inner.as_inner().as_raw_fd(), 128))?;
|
||||
cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?;
|
||||
|
||||
Ok(UnixListener(inner))
|
||||
}
|
||||
@ -109,12 +113,16 @@ impl UnixListener {
|
||||
pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
|
||||
unsafe {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
#[cfg(target_os = "linux")]
|
||||
const backlog: libc::c_int = -1;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const backlog: libc::c_int = 128;
|
||||
cvt(libc::bind(
|
||||
inner.as_raw_fd(),
|
||||
&socket_addr.addr as *const _ as *const _,
|
||||
socket_addr.len as _,
|
||||
))?;
|
||||
cvt(libc::listen(inner.as_raw_fd(), 128))?;
|
||||
cvt(libc::listen(inner.as_raw_fd(), backlog))?;
|
||||
Ok(UnixListener(inner))
|
||||
}
|
||||
}
|
||||
|
@ -1768,6 +1768,7 @@ fn test_windows_absolute() {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let mut paths: Vec<_> =
|
||||
@ -1781,6 +1782,7 @@ fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
@ -1799,6 +1801,7 @@ fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let paths: Vec<_> =
|
||||
@ -1817,6 +1820,7 @@ fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
@ -1835,6 +1839,7 @@ fn bench_path_hashset(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset_miss(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
|
@ -13,7 +13,7 @@ fn test_full() {
|
||||
#[test]
|
||||
fn test() {
|
||||
let nthreads = 8;
|
||||
let nmsgs = 1000;
|
||||
let nmsgs = if cfg!(miri) { 100 } else { 1000 };
|
||||
let q = Queue::new();
|
||||
match q.pop() {
|
||||
Empty => {}
|
||||
|
@ -77,12 +77,13 @@ fn stress() {
|
||||
}
|
||||
|
||||
unsafe fn stress_bound(bound: usize) {
|
||||
let count = if cfg!(miri) { 1000 } else { 100000 };
|
||||
let q = Arc::new(Queue::with_additions(bound, (), ()));
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let q2 = q.clone();
|
||||
let _t = thread::spawn(move || {
|
||||
for _ in 0..100000 {
|
||||
for _ in 0..count {
|
||||
loop {
|
||||
match q2.pop() {
|
||||
Some(1) => break,
|
||||
@ -93,7 +94,7 @@ fn stress() {
|
||||
}
|
||||
tx.send(()).unwrap();
|
||||
});
|
||||
for _ in 0..100000 {
|
||||
for _ in 0..count {
|
||||
q.push(1);
|
||||
}
|
||||
rx.recv().unwrap();
|
||||
|
@ -113,23 +113,25 @@ fn chan_gone_concurrent() {
|
||||
|
||||
#[test]
|
||||
fn stress() {
|
||||
let count = if cfg!(miri) { 100 } else { 10000 };
|
||||
let (tx, rx) = sync_channel::<i32>(0);
|
||||
thread::spawn(move || {
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
tx.send(1).unwrap();
|
||||
}
|
||||
});
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
assert_eq!(rx.recv().unwrap(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_recv_timeout_two_threads() {
|
||||
let count = if cfg!(miri) { 100 } else { 10000 };
|
||||
let (tx, rx) = sync_channel::<i32>(0);
|
||||
|
||||
thread::spawn(move || {
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
tx.send(1).unwrap();
|
||||
}
|
||||
});
|
||||
@ -146,12 +148,12 @@ fn stress_recv_timeout_two_threads() {
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(recv_count, 10000);
|
||||
assert_eq!(recv_count, count);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_recv_timeout_shared() {
|
||||
const AMT: u32 = 1000;
|
||||
const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
|
||||
const NTHREADS: u32 = 8;
|
||||
let (tx, rx) = sync_channel::<i32>(0);
|
||||
let (dtx, drx) = sync_channel::<()>(0);
|
||||
@ -191,7 +193,7 @@ fn stress_recv_timeout_shared() {
|
||||
|
||||
#[test]
|
||||
fn stress_shared() {
|
||||
const AMT: u32 = 1000;
|
||||
const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
|
||||
const NTHREADS: u32 = 8;
|
||||
let (tx, rx) = sync_channel::<i32>(0);
|
||||
let (dtx, drx) = sync_channel::<()>(0);
|
||||
@ -438,12 +440,13 @@ fn stream_send_recv_stress() {
|
||||
|
||||
#[test]
|
||||
fn recv_a_lot() {
|
||||
let count = if cfg!(miri) { 1000 } else { 10000 };
|
||||
// Regression test that we don't run out of stack in scheduler context
|
||||
let (tx, rx) = sync_channel(10000);
|
||||
for _ in 0..10000 {
|
||||
let (tx, rx) = sync_channel(count);
|
||||
for _ in 0..count {
|
||||
tx.send(()).unwrap();
|
||||
}
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -120,13 +120,14 @@ fn chan_gone_concurrent() {
|
||||
|
||||
#[test]
|
||||
fn stress() {
|
||||
let count = if cfg!(miri) { 100 } else { 10000 };
|
||||
let (tx, rx) = channel::<i32>();
|
||||
let t = thread::spawn(move || {
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
tx.send(1).unwrap();
|
||||
}
|
||||
});
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
assert_eq!(rx.recv().unwrap(), 1);
|
||||
}
|
||||
t.join().ok().expect("thread panicked");
|
||||
@ -134,7 +135,7 @@ fn stress() {
|
||||
|
||||
#[test]
|
||||
fn stress_shared() {
|
||||
const AMT: u32 = 10000;
|
||||
const AMT: u32 = if cfg!(miri) { 100 } else { 10000 };
|
||||
const NTHREADS: u32 = 8;
|
||||
let (tx, rx) = channel::<i32>();
|
||||
|
||||
@ -504,12 +505,13 @@ fn very_long_recv_timeout_wont_panic() {
|
||||
|
||||
#[test]
|
||||
fn recv_a_lot() {
|
||||
let count = if cfg!(miri) { 1000 } else { 10000 };
|
||||
// Regression test that we don't run out of stack in scheduler context
|
||||
let (tx, rx) = channel();
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
tx.send(()).unwrap();
|
||||
}
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..count {
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ fn smoke() {
|
||||
#[test]
|
||||
fn frob() {
|
||||
const N: u32 = 10;
|
||||
const M: usize = 1000;
|
||||
const M: usize = if cfg!(miri) { 100 } else { 1000 };
|
||||
|
||||
let r = Arc::new(RwLock::new(()));
|
||||
|
||||
|
@ -829,6 +829,7 @@ impl DirEntry {
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
#[cfg_attr(miri, allow(unused))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
|
||||
}
|
||||
@ -840,6 +841,7 @@ impl DirEntry {
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
))]
|
||||
#[cfg_attr(miri, allow(unused))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
&self.name
|
||||
}
|
||||
|
@ -329,3 +329,22 @@ fn test_scoped_threads_nll() {
|
||||
let x = 42_u8;
|
||||
foo(&x);
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/98498.
|
||||
#[test]
|
||||
#[cfg(miri)] // relies on Miri's data race detector
|
||||
fn scope_join_race() {
|
||||
for _ in 0..100 {
|
||||
let a_bool = AtomicBool::new(false);
|
||||
|
||||
thread::scope(|s| {
|
||||
for _ in 0..5 {
|
||||
s.spawn(|| a_bool.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
s.spawn(|| a_bool.load(Ordering::Relaxed));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
|
||||
.map(|_| {
|
||||
crate::thread::spawn(|| {
|
||||
let mut old = Instant::now();
|
||||
for _ in 0..5_000_000 {
|
||||
let count = if cfg!(miri) { 1_000 } else { 5_000_000 };
|
||||
for _ in 0..count {
|
||||
let new = Instant::now();
|
||||
assert!(new >= old);
|
||||
old = new;
|
||||
|
@ -569,7 +569,10 @@ fn short_item_info(
|
||||
message.push_str(&format!(": {}", html.into_string()));
|
||||
}
|
||||
extra_info.push(format!(
|
||||
"<div class=\"stab deprecated\"><span class=\"emoji\">👎</span> {}</div>",
|
||||
"<div class=\"stab deprecated\">\
|
||||
<span class=\"emoji\">👎</span>\
|
||||
<span>{}</span>\
|
||||
</div>",
|
||||
message,
|
||||
));
|
||||
}
|
||||
@ -582,8 +585,9 @@ fn short_item_info(
|
||||
.filter(|stab| stab.feature != sym::rustc_private)
|
||||
.map(|stab| (stab.level, stab.feature))
|
||||
{
|
||||
let mut message =
|
||||
"<span class=\"emoji\">🔬</span> This is a nightly-only experimental API.".to_owned();
|
||||
let mut message = "<span class=\"emoji\">🔬</span>\
|
||||
<span>This is a nightly-only experimental API."
|
||||
.to_owned();
|
||||
|
||||
let mut feature = format!("<code>{}</code>", Escape(feature.as_str()));
|
||||
if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, issue) {
|
||||
@ -594,7 +598,7 @@ fn short_item_info(
|
||||
));
|
||||
}
|
||||
|
||||
message.push_str(&format!(" ({})", feature));
|
||||
message.push_str(&format!(" ({})</span>", feature));
|
||||
|
||||
extra_info.push(format!("<div class=\"stab unstable\">{}</div>", message));
|
||||
}
|
||||
|
@ -1164,6 +1164,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
|
||||
.stab .emoji {
|
||||
font-size: 1.25rem;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
/* Black one-pixel outline around emoji shapes */
|
||||
|
@ -1,2 +1,24 @@
|
||||
The files here use the LLVM FileCheck framework, documented at
|
||||
<https://llvm.org/docs/CommandGuide/FileCheck.html>.
|
||||
|
||||
One extension worth noting is the use of revisions as custom prefixes for
|
||||
FileCheck. If your codegen test has different behavior based on the chosen
|
||||
target or different compiler flags that you want to exercise, you can use a
|
||||
revisions annotation, like so:
|
||||
|
||||
```rust
|
||||
// revisions: aaa bbb
|
||||
// [bbb] compile-flags: --flags-for-bbb
|
||||
```
|
||||
|
||||
After specifying those variations, you can write different expected, or
|
||||
explicitly *unexpected* output by using `<prefix>-SAME:` and `<prefix>-NOT:`,
|
||||
like so:
|
||||
|
||||
```rust
|
||||
// CHECK: expected code
|
||||
// aaa-SAME: emitted-only-for-aaa
|
||||
// aaa-NOT: emitted-only-for-bbb
|
||||
// bbb-NOT: emitted-only-for-aaa
|
||||
// bbb-SAME: emitted-only-for-bbb
|
||||
```
|
||||
|
@ -8,20 +8,24 @@
|
||||
// 'Experimental'
|
||||
// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
|
||||
|
||||
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \
|
||||
// '👎 Deprecated since 1.0.0: text'
|
||||
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' '👎'
|
||||
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' \
|
||||
// 'Deprecated since 1.0.0: text'
|
||||
// @hasraw - '<code>test</code> <a href="https://issue_url/32374">#32374</a>'
|
||||
// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' '🔬'
|
||||
// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
|
||||
// '🔬 This is a nightly-only experimental API. \(test\s#32374\)$'
|
||||
// 'This is a nightly-only experimental API. \(test\s#32374\)$'
|
||||
/// Docs
|
||||
#[deprecated(since = "1.0.0", note = "text")]
|
||||
#[unstable(feature = "test", issue = "32374")]
|
||||
pub struct T;
|
||||
|
||||
// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' '👎'
|
||||
// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \
|
||||
// '👎 Deprecated since 1.0.0: deprecated'
|
||||
// 'Deprecated since 1.0.0: deprecated'
|
||||
// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' '🔬'
|
||||
// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \
|
||||
// '🔬 This is a nightly-only experimental API. (test #32374)'
|
||||
// 'This is a nightly-only experimental API. (test #32374)'
|
||||
#[deprecated(since = "1.0.0", note = "deprecated")]
|
||||
#[unstable(feature = "test", issue = "32374", reason = "unstable")]
|
||||
pub struct U;
|
||||
|
30
src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs
Normal file
30
src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// check-fail
|
||||
// This file is used to test the behavior of the early-pass syntax warnings.
|
||||
// If macro syntax is stabilized, replace with a different unstable syntax.
|
||||
|
||||
macro a() {}
|
||||
//~^ ERROR: `macro` is experimental
|
||||
|
||||
#[cfg(FALSE)]
|
||||
macro b() {}
|
||||
|
||||
macro_rules! identity {
|
||||
($($x:tt)*) => ($($x)*);
|
||||
}
|
||||
|
||||
identity! {
|
||||
macro c() {}
|
||||
//~^ ERROR: `macro` is experimental
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
identity! {
|
||||
macro d() {} // No error
|
||||
}
|
||||
|
||||
identity! {
|
||||
#[cfg(FALSE)]
|
||||
macro e() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,21 @@
|
||||
error[E0658]: `macro` is experimental
|
||||
--> $DIR/soft-syntax-gates-with-errors.rs:5:1
|
||||
|
|
||||
LL | macro a() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `macro` is experimental
|
||||
--> $DIR/soft-syntax-gates-with-errors.rs:16:5
|
||||
|
|
||||
LL | macro c() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,26 @@
|
||||
// check-pass
|
||||
// This file is used to test the behavior of the early-pass syntax warnings.
|
||||
// If macro syntax is stabilized, replace with a different unstable syntax.
|
||||
|
||||
#[cfg(FALSE)]
|
||||
macro b() {}
|
||||
//~^ WARN: `macro` is experimental
|
||||
//~| WARN: unstable syntax
|
||||
|
||||
macro_rules! identity {
|
||||
($($x:tt)*) => ($($x)*);
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
identity! {
|
||||
macro d() {} // No error
|
||||
}
|
||||
|
||||
identity! {
|
||||
#[cfg(FALSE)]
|
||||
macro e() {}
|
||||
//~^ WARN: `macro` is experimental
|
||||
//~| WARN: unstable syntax
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,24 @@
|
||||
warning: `macro` is experimental
|
||||
--> $DIR/soft-syntax-gates-without-errors.rs:6:1
|
||||
|
|
||||
LL | macro b() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: `macro` is experimental
|
||||
--> $DIR/soft-syntax-gates-without-errors.rs:21:5
|
||||
|
|
||||
LL | macro e() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -3,11 +3,18 @@
|
||||
// compile-flags: --test
|
||||
|
||||
#![feature(async_closure)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(generators)]
|
||||
#![feature(half_open_range_patterns)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(more_qualified_paths)]
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(type_ascription)]
|
||||
#![deny(unused_macros)]
|
||||
|
||||
macro_rules! stringify_block {
|
||||
|
@ -7,7 +7,7 @@ fn main() {}
|
||||
|
||||
// Test the `pat` macro fragment parser:
|
||||
macro_rules! accept_pat {
|
||||
($p:pat) => {}
|
||||
($p:pat) => {};
|
||||
}
|
||||
|
||||
accept_pat!((p | q));
|
||||
@ -21,28 +21,28 @@ accept_pat!([p | q]);
|
||||
#[cfg(FALSE)]
|
||||
fn or_patterns() {
|
||||
// Top level of `let`:
|
||||
let (| A | B);
|
||||
let (A | B);
|
||||
let (A | B);
|
||||
let (A | B): u8;
|
||||
let (A | B) = 0;
|
||||
let (A | B): u8 = 0;
|
||||
|
||||
// Top level of `for`:
|
||||
for | A | B in 0 {}
|
||||
for A | B in 0 {}
|
||||
for A | B in 0 {}
|
||||
|
||||
// Top level of `while`:
|
||||
while let | A | B = 0 {}
|
||||
while let A | B = 0 {}
|
||||
while let A | B = 0 {}
|
||||
|
||||
// Top level of `if`:
|
||||
if let | A | B = 0 {}
|
||||
if let A | B = 0 {}
|
||||
if let A | B = 0 {}
|
||||
|
||||
// Top level of `match` arms:
|
||||
match 0 {
|
||||
| A | B => {},
|
||||
A | B => {},
|
||||
A | B => {}
|
||||
A | B => {}
|
||||
}
|
||||
|
||||
// Functions:
|
||||
@ -68,6 +68,8 @@ fn or_patterns() {
|
||||
|
||||
// These bind as `(prefix p) | q` as opposed to `prefix (p | q)`:
|
||||
let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
|
||||
//~^ WARN box pattern syntax is experimental
|
||||
//~| WARN unstable syntax
|
||||
let (&0 | 1);
|
||||
let (&mut 0 | 1);
|
||||
let (x @ 0 | 1);
|
||||
|
13
src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
Normal file
13
src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/or-patterns-syntactic-pass.rs:70:10
|
||||
|
|
||||
LL | let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -3,7 +3,11 @@
|
||||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
foo::<T = u8, T: Ord, String>();
|
||||
//~^ WARN associated type bounds are unstable
|
||||
//~| WARN unstable syntax
|
||||
foo::<T = u8, 'a, T: Ord>();
|
||||
//~^ WARN associated type bounds are unstable
|
||||
//~| WARN unstable syntax
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -0,0 +1,24 @@
|
||||
warning: associated type bounds are unstable
|
||||
--> $DIR/constraints-before-generic-args-syntactic-pass.rs:5:19
|
||||
|
|
||||
LL | foo::<T = u8, T: Ord, String>();
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: associated type bounds are unstable
|
||||
--> $DIR/constraints-before-generic-args-syntactic-pass.rs:8:23
|
||||
|
|
||||
LL | foo::<T = u8, 'a, T: Ord>();
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -19,6 +19,8 @@ fn rest_patterns() {
|
||||
|
||||
// Box patterns:
|
||||
let box ..;
|
||||
//~^ WARN box pattern syntax is experimental
|
||||
//~| WARN unstable syntax
|
||||
|
||||
// In or-patterns:
|
||||
match x {
|
||||
@ -57,7 +59,7 @@ fn rest_patterns() {
|
||||
.. |
|
||||
[
|
||||
(
|
||||
box ..,
|
||||
box .., //~ WARN box pattern syntax is experimental
|
||||
&(..),
|
||||
&mut ..,
|
||||
x @ ..
|
||||
@ -67,4 +69,5 @@ fn rest_patterns() {
|
||||
ref mut x @ ..
|
||||
=> {}
|
||||
}
|
||||
//~| WARN unstable syntax
|
||||
}
|
||||
|
24
src/test/ui/pattern/rest-pat-syntactic.stderr
Normal file
24
src/test/ui/pattern/rest-pat-syntactic.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/rest-pat-syntactic.rs:21:9
|
||||
|
|
||||
LL | let box ..;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/rest-pat-syntactic.rs:62:17
|
||||
|
|
||||
LL | box ..,
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
4
src/test/ui/suggestions/many-type-ascription.rs
Normal file
4
src/test/ui/suggestions/many-type-ascription.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
let _ = 0: i32; //~ ERROR: type ascription is experimental
|
||||
let _ = 0: i32; // (error only emitted once)
|
||||
}
|
12
src/test/ui/suggestions/many-type-ascription.stderr
Normal file
12
src/test/ui/suggestions/many-type-ascription.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0658]: type ascription is experimental
|
||||
--> $DIR/many-type-ascription.rs:2:13
|
||||
|
|
||||
LL | let _ = 0: i32;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
|
||||
= help: add `#![feature(type_ascription)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn foo(foo: &mut usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bar(bar: &usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
|
||||
bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn foo(foo: &mut usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bar(bar: &usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
|
||||
bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
error[E0277]: the trait bound `&mut usize: Default` is not satisfied
|
||||
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
|
||||
|
|
||||
LL | foo(Default::default());
|
||||
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
|
||||
|
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | foo(&mut Default::default());
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `&usize: Default` is not satisfied
|
||||
--> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
|
||||
|
|
||||
LL | bar(Default::default());
|
||||
| ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
|
||||
|
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | bar(&Default::default());
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
not rust; //~ ERROR
|
||||
let _ = 0: i32; // (error hidden by existing error)
|
||||
#[cfg(FALSE)]
|
||||
let _ = 0: i32; // (warning hidden by existing error)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `rust`
|
||||
--> $DIR/type-ascription-and-other-error.rs:2:9
|
||||
|
|
||||
LL | not rust;
|
||||
| ^^^^ expected one of 8 possible tokens
|
||||
|
||||
error: aborting due to previous error
|
||||
|
12
src/test/ui/traits/alias/self-in-const-generics.rs
Normal file
12
src/test/ui/traits/alias/self-in-const-generics.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Bar<const N: usize> {}
|
||||
|
||||
trait BB = Bar<{ 2 + 1 }>;
|
||||
|
||||
fn foo(x: &dyn BB) {}
|
||||
//~^ ERROR the trait alias `BB` cannot be made into an object [E0038]
|
||||
|
||||
fn main() {}
|
11
src/test/ui/traits/alias/self-in-const-generics.stderr
Normal file
11
src/test/ui/traits/alias/self-in-const-generics.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0038]: the trait alias `BB` cannot be made into an object
|
||||
--> $DIR/self-in-const-generics.rs:9:16
|
||||
|
|
||||
LL | fn foo(x: &dyn BB) {}
|
||||
| ^^
|
||||
|
|
||||
= note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,3 +1,10 @@
|
||||
// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
|
||||
// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
|
||||
// Using `save-analysis` triggers type-checking `f` that would be normally skipped
|
||||
// as `type_of` emitted an error.
|
||||
//
|
||||
// compile-flags: -Zsave-analysis
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
pub trait SelfInput = Fn(&mut Self);
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait alias `SelfInput` cannot be made into an object
|
||||
--> $DIR/self-in-generics.rs:5:19
|
||||
--> $DIR/self-in-generics.rs:12:19
|
||||
|
|
||||
LL | pub fn f(_f: &dyn SelfInput) {}
|
||||
| ^^^^^^^^^
|
||||
|
@ -2,10 +2,8 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
|
||||
--> $DIR/issue-39029.rs:16:37
|
||||
|
|
||||
LL | let _errors = TcpListener::bind(&bad);
|
||||
| ----------------- ^^^^
|
||||
| | |
|
||||
| | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
|
||||
| | help: consider dereferencing here: `&*bad`
|
||||
| ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
|
||||
@ -14,6 +12,10 @@ note: required by a bound in `TcpListener::bind`
|
||||
|
|
||||
LL | pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
| ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
|
||||
help: consider dereferencing here
|
||||
|
|
||||
LL | let _errors = TcpListener::bind(&*bad);
|
||||
| +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,10 +2,8 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied
|
||||
--> $DIR/issue-62530.rs:13:26
|
||||
|
|
||||
LL | takes_type_parameter(&string); // Error
|
||||
| -------------------- ^^^^^^^
|
||||
| | |
|
||||
| | the trait `SomeTrait` is not implemented for `&String`
|
||||
| | help: consider dereferencing here: `&*string`
|
||||
| -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_type_parameter`
|
||||
@ -13,6 +11,10 @@ note: required by a bound in `takes_type_parameter`
|
||||
|
|
||||
LL | fn takes_type_parameter<T>(_x: T) where T: SomeTrait {}
|
||||
| ^^^^^^^^^ required by this bound in `takes_type_parameter`
|
||||
help: consider dereferencing here
|
||||
|
|
||||
LL | takes_type_parameter(&*string); // Error
|
||||
| +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,10 +2,8 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied
|
||||
--> $DIR/multiple-0.rs:34:9
|
||||
|
|
||||
LL | foo(&baz);
|
||||
| --- ^^^^
|
||||
| | |
|
||||
| | the trait `Happy` is not implemented for `&Baz`
|
||||
| | help: consider dereferencing here: `&***baz`
|
||||
| --- ^^^^ the trait `Happy` is not implemented for `&Baz`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
@ -13,6 +11,10 @@ note: required by a bound in `foo`
|
||||
|
|
||||
LL | fn foo<T>(_: T) where T: Happy {}
|
||||
| ^^^^^ required by this bound in `foo`
|
||||
help: consider dereferencing here
|
||||
|
|
||||
LL | foo(&***baz);
|
||||
| +++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user