Erroneous code example:
-```compile_fail,E0744
+```compile_fail,edition2018,E0744
const _: i32 = {
- let mut x = 0;
-
- for i in 0..4 { // error!
- x += i;
- }
+ async { 0 }.await
};
```
-At the moment, `for` loops, `.await`, and the `Try` operator (`?`) are forbidden
-inside a `const`, `static`, or `const fn`.
+At the moment, `.await` is forbidden inside a `const`, `static`, or `const fn`.
This may be allowed at some point in the future, but the implementation is not
-yet complete. See the tracking issues for [`async`] and [`?`] in `const fn`, and
-(to support `for` loops in `const fn`) the tracking issues for [`impl const
-Trait for Ty`] and [`&mut T`] in `const fn`.
+yet complete. See the tracking issue for [`async`] in `const fn`.
[`async`]: https://github.com/rust-lang/rust/issues/69431
-[`?`]: https://github.com/rust-lang/rust/issues/74935
-[`impl const Trait for Ty`]: https://github.com/rust-lang/rust/issues/67792
-[`&mut T`]: https://github.com/rust-lang/rust/issues/57349
lint_node_id: NodeId,
is_trailing_mac: bool,
arm_span: Span,
+ /// Whether or not this macro is defined in the current crate
+ is_local: bool,
}
crate fn annotate_err_with_kind(
lint_node_id,
arm_span,
is_trailing_mac,
+ is_local,
} = *self;
let snapshot = &mut parser.clone();
let fragment = match parse_ast_fragment(parser, kind) {
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
// but `m!()` is allowed in expression positions (cf. issue #34706).
if kind == AstFragmentKind::Expr && parser.token == token::Semi {
- parser.sess.buffer_lint_with_diagnostic(
- SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
- parser.token.span,
- lint_node_id,
- "trailing semicolon in macro used in expression position",
- BuiltinLintDiagnostics::TrailingMacro(is_trailing_mac, macro_ident),
- );
+ if is_local {
+ parser.sess.buffer_lint_with_diagnostic(
+ SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
+ parser.token.span,
+ lint_node_id,
+ "trailing semicolon in macro used in expression position",
+ BuiltinLintDiagnostics::TrailingMacro(is_trailing_mac, macro_ident),
+ );
+ }
parser.bump();
}
lhses: Vec<mbe::TokenTree>,
rhses: Vec<mbe::TokenTree>,
valid: bool,
+ is_local: bool,
}
impl TTMacroExpander for MacroRulesMacroExpander {
input,
&self.lhses,
&self.rhses,
+ self.is_local,
)
}
}
arg: TokenStream,
lhses: &[mbe::TokenTree],
rhses: &[mbe::TokenTree],
+ is_local: bool,
) -> Box<dyn MacResult + 'cx> {
let sess = &cx.sess.parse_sess;
lint_node_id: cx.current_expansion.lint_node_id,
is_trailing_mac: cx.current_expansion.is_trailing_mac,
arm_span,
+ is_local,
});
}
Failure(token, msg) => match best_failure {
lhses,
rhses,
valid,
+ // Macros defined in the current crate have a real node id,
+ // whereas macros from an external crate have a dummy id.
+ is_local: def.id != DUMMY_NODE_ID,
}))
}
/// Allows `#[derive(Default)]` and `#[default]` on enums.
(active, derive_default_enum, "1.56.0", Some(86985), None),
+ /// Allows `for _ in _` loops in const contexts.
+ (active, const_for, "1.56.0", Some(87575), None),
+
+ /// Allows the `?` operator in const contexts.
+ (active, const_try, "1.56.0", Some(74935), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
/// [issue #79813]: https://github.com/rust-lang/rust/issues/79813
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
- Allow,
+ Warn,
"trailing semicolon in macro body used as expression",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #79813 <https://github.com/rust-lang/rust/issues/79813>",
} else if target.contains("windows-gnu") {
println!("cargo:rustc-link-lib=shell32");
println!("cargo:rustc-link-lib=uuid");
- } else if target.contains("netbsd") || target.contains("haiku") {
+ } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
println!("cargo:rustc-link-lib=z");
}
cmd.args(&components);
use rustc_middle::mir::*;
use rustc_middle::ty;
use rustc_span::source_map::DesugaringKind;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use crate::borrow_check::diagnostics::UseSpans;
use crate::borrow_check::prefixes::PrefixSet;
}
}
};
- if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
- let def_id = match *move_place.ty(self.body, self.infcx.tcx).ty.kind() {
- ty::Adt(self_def, _) => self_def.did,
- ty::Foreign(def_id)
- | ty::FnDef(def_id, _)
- | ty::Closure(def_id, _)
- | ty::Generator(def_id, ..)
- | ty::Opaque(def_id, _) => def_id,
- _ => return err,
+ let ty = move_place.ty(self.body, self.infcx.tcx).ty;
+ let def_id = match *ty.kind() {
+ ty::Adt(self_def, _) => self_def.did,
+ ty::Foreign(def_id)
+ | ty::FnDef(def_id, _)
+ | ty::Closure(def_id, _)
+ | ty::Generator(def_id, ..)
+ | ty::Opaque(def_id, _) => def_id,
+ _ => return err,
+ };
+ let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id);
+ let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id);
+ if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
+ err.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ &format!(
+ "consider borrowing the `{}`'s content",
+ if is_option { "Option" } else { "Result" }
+ ),
+ ".as_ref()".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
+ let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
+ Some(def_id) => type_known_to_meet_bound_modulo_regions(
+ &self.infcx,
+ self.param_env,
+ self.infcx.tcx.mk_imm_ref(self.infcx.tcx.lifetimes.re_erased, ty),
+ def_id,
+ DUMMY_SP,
+ ),
+ _ => false,
};
- let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id);
- let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id);
- if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
- err.span_suggestion(
- span,
- &format!(
- "consider borrowing the `{}`'s content",
- if is_option { "Option" } else { "Result" }
- ),
- format!("{}.as_ref()", snippet),
- Applicability::MaybeIncorrect,
- );
- } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_)))
- && self.infcx.tcx.is_diagnostic_item(sym::vec_type, def_id)
- {
- // FIXME: suggest for anything that implements `IntoIterator`.
- err.span_suggestion(
- span,
- "consider iterating over a slice of the `Vec<_>`'s content",
- format!("&{}", snippet),
+ if suggest {
+ err.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ &format!("consider iterating over a slice of the `{}`'s content", ty),
+ "&".to_string(),
Applicability::MaybeIncorrect,
);
}
use hir::MatchSource::*;
let gates: &[_] = match self {
- // A `for` loop's desugaring contains a call to `IntoIterator::into_iter`,
- // so they are not yet allowed.
- // Likewise, `?` desugars to a call to `Try::into_result`.
- Self::Loop(ForLoop) | Self::Match(ForLoopDesugar | TryDesugar | AwaitDesugar) => {
+ Self::Match(AwaitDesugar) => {
return None;
}
+ Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for],
+
+ Self::Match(TryDesugar) => &[sym::const_try],
+
Self::Match(IfLetGuardDesugar) => bug!("`if let` guard outside a `match` expression"),
// All other expressions are allowed.
const_fn_transmute,
const_fn_union,
const_fn_unsize,
+ const_for,
const_format_args,
const_generic_defaults,
const_generics,
const_trait_bound_opt_out,
const_trait_impl,
const_transmute,
+ const_try,
constant,
constructor,
contents,
}
pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
- self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty);
- self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty);
+ self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
+ self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{Ref, Ty};
+use rustc_middle::ty::{Adt, Ref, Ty};
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_span::symbol::kw::Underscore;
use rustc_span::symbol::{sym, Ident};
method_name.name
));
- let self_ty = self
+ let self_ty_name = self
.sess()
.source_map()
.span_to_snippet(self_ty_span)
.unwrap_or_else(|_| self_ty.to_string());
+ let self_ty_generics_count = match self_ty.kind() {
+ // Get the number of generics the self type has (if an Adt) unless we can determine that
+ // the user has written the self type with generics already which we (naively) do by looking
+ // for a "<" in `self_ty_name`.
+ Adt(def, _) if !self_ty_name.contains("<") => self.tcx.generics_of(def.did).count(),
+ _ => 0,
+ };
+ let self_ty_generics = if self_ty_generics_count > 0 {
+ format!("<{}>", vec!["_"; self_ty_generics_count].join(", "))
+ } else {
+ String::new()
+ };
lint.span_suggestion(
span,
"disambiguate the associated function",
- format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
+ format!(
+ "<{}{} as {}>::{}",
+ self_ty_name, self_ty_generics, trait_name, method_name.name,
+ ),
Applicability::MachineApplicable,
);
/// a `T`, which means this must not be used as a "not yet initialized"
/// sentinel value. Types that lazily allocate must track initialization by
/// some other means.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let ptr = NonNull::<u32>::dangling();
+ /// // Important: don't try to access the value of `ptr` without
+ /// // initializing it first! The pointer is not null but isn't valid either!
+ /// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")]
#[inline]
/// # Safety
///
/// `ptr` must be non-null.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let ptr = unsafe { NonNull::new_unchecked(&mut x as *mut _) };
+ ///
+ /// // NEVER DO THAT!!!
+ /// let ptr = unsafe { NonNull::<u32>::new_unchecked(std::ptr::null_mut()) };
+ /// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")]
#[inline]
}
/// Creates a new `NonNull` if `ptr` is non-null.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let ptr = NonNull::<u32>::new(&mut x as *mut _).expect("ptr is null!");
+ ///
+ /// if let Some(ptr) = NonNull::<u32>::new(std::ptr::null_mut()) {
+ /// unreachable!();
+ /// }
+ /// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
pub fn new(ptr: *mut T) -> Option<Self> {
}
/// Acquires the underlying `*mut` pointer.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let ptr = NonNull::new(&mut x).expect("ptr is null!");
+ ///
+ /// let x_value = unsafe { *ptr.as_ptr() };
+ /// assert_eq!(x_value, 0);
+ ///
+ /// unsafe { *ptr.as_ptr() += 2; }
+ /// let x_value = unsafe { *ptr.as_ptr() };
+ /// assert_eq!(x_value, 2);
+ /// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
#[inline]
/// (The part about being initialized is not yet fully decided, but until
/// it is, the only safe approach is to ensure that they are indeed initialized.)
///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let ptr = NonNull::new(&mut x as *mut _).expect("ptr is null!");
+ ///
+ /// let ref_x = unsafe { ptr.as_ref() };
+ /// println!("{}", ref_x);
+ /// ```
+ ///
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
/// This applies even if the result of this method is unused!
/// (The part about being initialized is not yet fully decided, but until
/// it is, the only safe approach is to ensure that they are indeed initialized.)
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let mut ptr = NonNull::new(&mut x).expect("null pointer");
+ ///
+ /// let x_ref = unsafe { ptr.as_mut() };
+ /// assert_eq!(*x_ref, 0);
+ /// *x_ref += 2;
+ /// assert_eq!(*x_ref, 2);
+ /// ```
///
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
}
/// Casts to a pointer of another type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ptr::NonNull;
+ ///
+ /// let mut x = 0u32;
+ /// let ptr = NonNull::new(&mut x as *mut _).expect("null pointer");
+ ///
+ /// let casted_ptr = ptr.cast::<i8>();
+ /// let raw_ptr: *mut i8 = casted_ptr.as_ptr();
+ /// ```
#[stable(feature = "nonnull_cast", since = "1.27.0")]
#[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")]
#[inline]
// `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
// will be malformed.
() => {
- $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
+ $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!())
};
($val:expr $(,)?) => {
// Use of `match` here is intentional because it affects the lifetimes
--- /dev/null
+// Check that errors for unresolved types in cast expressions are reported
+// for the offending subexpression, not the whole cast expression.
+
+#![allow(unused_variables)]
+
+fn main() {
+ let a = [1, 2, 3].iter().sum();
+ let b = (a + 1) as usize;
+ //~^ ERROR: type annotations needed [E0282]
+}
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/issue-85586.rs:8:13
+ |
+LL | let b = (a + 1) as usize;
+ | ^^^^^^^ cannot infer type
+ |
+ = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
//~| ERROR calls in constant functions
//~| ERROR calls in constant functions
//~| ERROR E0080
- //~| ERROR E0744
+ //~| ERROR `for` is not allowed in a `const fn`
sum += i;
}
sum
-error[E0744]: `for` is not allowed in a `const fn`
+error[E0658]: `for` is not allowed in a `const fn`
--> $DIR/const-fn-error.rs:5:5
|
LL | / for i in 0..x {
LL | | sum += i;
LL | | }
| |_____^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-fn-error.rs:5:14
error: aborting due to 5 previous errors
-Some errors have detailed explanations: E0015, E0080, E0658, E0744.
+Some errors have detailed explanations: E0015, E0080, E0658.
For more information about an error, try `rustc --explain E0015`.
--- /dev/null
+// gate-test-const_for
+
+const _: () = {
+ for _ in 0..5 {}
+ //~^ error: `for` is not allowed in a `const`
+};
+
+fn main() {}
--- /dev/null
+error[E0658]: `for` is not allowed in a `const`
+ --> $DIR/const-for-feature-gate.rs:4:5
+ |
+LL | for _ in 0..5 {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+#![feature(const_for)]
+#![feature(const_mut_refs)]
+
+const _: () = {
+ for _ in 0..5 {}
+ //~^ error: calls in constants are limited to
+ //~| error: calls in constants are limited to
+};
+
+fn main() {}
--- /dev/null
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+ --> $DIR/const-for.rs:5:14
+ |
+LL | for _ in 0..5 {}
+ | ^^^^
+
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+ --> $DIR/const-for.rs:5:14
+ |
+LL | for _ in 0..5 {}
+ | ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
--- /dev/null
+// gate-test-const_try
+
+const fn t() -> Option<()> {
+ Some(())?;
+ //~^ error: `?` is not allowed in a `const fn`
+ None
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: `?` is not allowed in a `const fn`
+ --> $DIR/const-try-feature-gate.rs:4:5
+ |
+LL | Some(())?;
+ | ^^^^^^^^^
+ |
+ = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+ = help: add `#![feature(const_try)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// check-pass
+
+// Demonstrates what's needed to make use of `?` in const contexts.
+
+#![crate_type = "lib"]
+#![feature(try_trait_v2)]
+#![feature(const_trait_impl)]
+#![feature(const_try)]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+struct TryMe;
+struct Error;
+
+impl const FromResidual<Error> for TryMe {
+ fn from_residual(residual: Error) -> Self {
+ TryMe
+ }
+}
+
+impl const Try for TryMe {
+ type Output = ();
+ type Residual = Error;
+ fn from_output(output: Self::Output) -> Self {
+ TryMe
+ }
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ ControlFlow::Break(Error)
+ }
+}
+
+const fn t() -> TryMe {
+ TryMe?;
+ TryMe
+}
+
+const _: () = {
+ t();
+};
-error[E0744]: `for` is not allowed in a `const`
+error[E0658]: `for` is not allowed in a `const`
--> $DIR/loop.rs:53:5
|
LL | / for i in 0..4 {
LL | | x += i;
LL | | }
| |_____^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
-error[E0744]: `for` is not allowed in a `const`
+error[E0658]: `for` is not allowed in a `const`
--> $DIR/loop.rs:57:5
|
LL | / for i in 0..4 {
LL | | x += i;
LL | | }
| |_____^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0744`.
+For more information about this error, try `rustc --explain E0658`.
-error[E0744]: `?` is not allowed in a `const fn`
+error[E0658]: `?` is not allowed in a `const fn`
--> $DIR/try.rs:6:5
|
LL | x?;
| ^^
+ |
+ = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+ = help: add `#![feature(const_try)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0744`.
+For more information about this error, try `rustc --explain E0658`.
mod bar {
fn f() -> u32 { 1 }
pub macro m() {
- f();
+ f()
}
}
}
}
pub fn main() {
- 'x: loop { foo!() }
+ 'x: loop { foo!(); }
}
LL | () => { break 'x; }
| ^^ undeclared label `'x`
...
-LL | 'x: loop { foo!() }
- | ------ in this macro invocation
+LL | 'x: loop { foo!(); }
+ | ------- in this macro invocation
|
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
pub fn main() {
'x: for _ in 0..1 {
- foo!()
+ foo!();
};
}
LL | () => { break 'x; }
| ^^ undeclared label `'x`
...
-LL | foo!()
- | ------ in this macro invocation
+LL | foo!();
+ | ------- in this macro invocation
|
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0744]: `for` is not allowed in a `const`
+error[E0658]: `for` is not allowed in a `const`
--> $DIR/issue-50582.rs:2:20
|
LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
| ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
error[E0277]: cannot add `()` to `{integer}`
--> $DIR/issue-50582.rs:2:18
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0277, E0744.
+Some errors have detailed explanations: E0277, E0658.
For more information about an error, try `rustc --explain E0277`.
-error[E0744]: `for` is not allowed in a `const`
+error[E0658]: `for` is not allowed in a `const`
--> $DIR/issue-50585.rs:2:18
|
LL | |y: Vec<[(); for x in 0..2 {}]>| {};
| ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
error[E0308]: mismatched types
--> $DIR/issue-50585.rs:2:18
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0308, E0744.
+Some errors have detailed explanations: E0308, E0658.
For more information about an error, try `rustc --explain E0308`.
+++ /dev/null
-// check-pass
-// Ensure that trailing semicolons are allowed by default
-
-macro_rules! foo {
- () => {
- true;
- }
-}
-
-fn main() {
- let val = match true {
- true => false,
- _ => foo!()
- };
-}
--- /dev/null
+#[macro_export]
+macro_rules! my_macro {
+ () => { true; }
+}
--- /dev/null
+// aux-build:foreign-crate.rs
+// check-pass
+
+extern crate foreign_crate;
+
+// Test that we do not lint for a macro in a foreign crate
+fn main() {
+ let _ = foreign_crate::my_macro!();
+}
--- /dev/null
+// check-pass
+// Ensure that trailing semicolons cause warnings by default
+
+macro_rules! foo {
+ () => {
+ true; //~ WARN trailing semicolon in macro
+ //~| WARN this was previously
+ }
+}
+
+fn main() {
+ let _val = match true {
+ true => false,
+ _ => foo!()
+ };
+}
--- /dev/null
+warning: trailing semicolon in macro used in expression position
+ --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13
+ |
+LL | true;
+ | ^
+...
+LL | _ => foo!()
+ | ------ in this macro invocation
+ |
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
//~| ERROR macro expansion ignores token `;`
//~| ERROR cannot find type `i` in this scope
//~| ERROR cannot find value `i` in this scope
+ //~| WARN trailing semicolon in macro
+ //~| WARN this was previously
}
fn main() {
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 6 previous errors
+warning: trailing semicolon in macro used in expression position
+ --> $DIR/macro-context.rs:3:15
+ |
+LL | () => ( i ; typeof );
+ | ^
+...
+LL | let i = m!();
+ | ---- in this macro invocation
+ |
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors; 1 warning emitted
Some errors have detailed explanations: E0412, E0425.
For more information about an error, try `rustc --explain E0412`.
macro_rules! foo {
() => {
assert_eq!("A", "A");
+ //~^ WARN trailing semicolon in macro
+ //~| WARN this was previously
+ //~| NOTE macro invocations at the end of a block
+ //~| NOTE to ignore the value produced by the macro
+ //~| NOTE for more information
+ //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default
assert_eq!("B", "B");
}
//~^^ ERROR macro expansion ignores token `assert_eq` and any following
fn main() {
foo!();
//~^ NOTE caused by the macro expansion here
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
}
macro_rules! foo {
() => {
assert_eq!("A", "A");
+ //~^ WARN trailing semicolon in macro
+ //~| WARN this was previously
+ //~| NOTE macro invocations at the end of a block
+ //~| NOTE to ignore the value produced by the macro
+ //~| NOTE for more information
+ //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default
assert_eq!("B", "B");
}
//~^^ ERROR macro expansion ignores token `assert_eq` and any following
fn main() {
foo!()
//~^ NOTE caused by the macro expansion here
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
+ //~| NOTE in this expansion
}
error: macro expansion ignores token `assert_eq` and any following
- --> $DIR/macro-in-expression-context.rs:6:9
+ --> $DIR/macro-in-expression-context.rs:12:9
|
LL | assert_eq!("B", "B");
| ^^^^^^^^^
|
= note: the usage of `foo!` is likely invalid in expression context
-error: aborting due to previous error
+warning: trailing semicolon in macro used in expression position
+ --> $DIR/macro-in-expression-context.rs:5:29
+ |
+LL | assert_eq!("A", "A");
+ | ^
+...
+LL | foo!()
+ | ------ in this macro invocation
+ |
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: macro invocations at the end of a block are treated as expressions
+ = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo`
+ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error; 1 warning emitted
|
= note: `#[warn(while_true)]` on by default
-error[E0744]: `for` is not allowed in a `const`
+error[E0658]: `for` is not allowed in a `const`
--> $DIR/issue-52443.rs:9:12
|
LL | [(); { for _ in 0usize.. {}; 0}];
| ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
error[E0308]: mismatched types
--> $DIR/issue-52443.rs:2:10
error: aborting due to 6 previous errors; 1 warning emitted
-Some errors have detailed explanations: E0015, E0308, E0658, E0744.
+Some errors have detailed explanations: E0015, E0308, E0658.
For more information about an error, try `rustc --explain E0015`.
+++ /dev/null
-// check-pass
-// edition:2021
-// compile-flags: -Zunstable-options
-
-fn main() {
- let _: u16 = 123i32.try_into().unwrap();
-}
(first, $e:expr) => { wrap!(second, $e + 1) };
(second, $e:expr) => { wrap!(third, $e + 2) };
(third, $e:expr) => {
- print_bang!($e + 3);
+ print_bang!($e + 3)
};
}
-error[E0744]: `?` is not allowed in a `const fn`
+error[E0658]: `?` is not allowed in a `const fn`
--> $DIR/hir-const-check.rs:11:9
|
LL | Some(())?;
| ^^^^^^^^^
+ |
+ = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+ = help: add `#![feature(const_try)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0744`.
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// test for https://github.com/rust-lang/rust/issues/86940
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+struct Generic<T, U>(T, U);
+
+trait MyFromIter {
+ fn from_iter(_: i32) -> Self;
+}
+
+impl MyFromIter for Generic<i32, i32> {
+ fn from_iter(x: i32) -> Self {
+ Self(x, x)
+ }
+}
+
+impl std::iter::FromIterator<i32> for Generic<i32, i32> {
+ fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
+ todo!()
+ }
+}
+
+fn main() {
+ <Generic<_, _> as MyFromIter>::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+ <Generic::<i32, i32> as MyFromIter>::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+ <Generic::<_, _> as MyFromIter>::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+}
--- /dev/null
+// test for https://github.com/rust-lang/rust/issues/86940
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+struct Generic<T, U>(T, U);
+
+trait MyFromIter {
+ fn from_iter(_: i32) -> Self;
+}
+
+impl MyFromIter for Generic<i32, i32> {
+ fn from_iter(x: i32) -> Self {
+ Self(x, x)
+ }
+}
+
+impl std::iter::FromIterator<i32> for Generic<i32, i32> {
+ fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
+ todo!()
+ }
+}
+
+fn main() {
+ Generic::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+ Generic::<i32, i32>::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+ Generic::<_, _>::from_iter(1);
+ //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
+ //~| this is accepted in the current edition (Rust 2018)
+}
--- /dev/null
+warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
+ --> $DIR/future-prelude-collision-generic.rs:28:5
+ |
+LL | Generic::from_iter(1);
+ | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<_, _> as MyFromIter>::from_iter`
+ |
+note: the lint level is defined here
+ --> $DIR/future-prelude-collision-generic.rs:5:9
+ |
+LL | #![warn(rust_2021_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+
+warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
+ --> $DIR/future-prelude-collision-generic.rs:31:5
+ |
+LL | Generic::<i32, i32>::from_iter(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
+ |
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+
+warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
+ --> $DIR/future-prelude-collision-generic.rs:34:5
+ |
+LL | Generic::<_, _>::from_iter(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
+ |
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+
+warning: 3 warnings emitted
+
--- /dev/null
+// check-pass
+// edition:2021
+// compile-flags: -Zunstable-options
+
+fn main() {
+ let _: u16 = 123i32.try_into().unwrap();
+}
struct Foo {
v: Vec<u32>,
+ h: std::collections::HashMap<i32, i32>,
}
impl Foo {
fn bar(&self) {
for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
}
+ for _ in &self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference
+ }
}
}
struct Foo {
v: Vec<u32>,
+ h: std::collections::HashMap<i32, i32>,
}
impl Foo {
fn bar(&self) {
for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
}
+ for _ in self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference
+ }
}
}
error[E0507]: cannot move out of `self.v` which is behind a shared reference
- --> $DIR/for-i-in-vec.rs:10:18
+ --> $DIR/for-i-in-vec.rs:11:18
|
LL | for _ in self.v {
- | ^^^^^^
- | |
- | move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
- | help: consider iterating over a slice of the `Vec<_>`'s content: `&self.v`
+ | ^^^^^^ move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
+ |
+help: consider iterating over a slice of the `Vec<u32>`'s content
+ |
+LL | for _ in &self.v {
+ | ^
+
+error[E0507]: cannot move out of `self.h` which is behind a shared reference
+ --> $DIR/for-i-in-vec.rs:13:18
+ |
+LL | for _ in self.h {
+ | ^^^^^^ move occurs because `self.h` has type `HashMap<i32, i32>`, which does not implement the `Copy` trait
+ |
+help: consider iterating over a slice of the `HashMap<i32, i32>`'s content
+ |
+LL | for _ in &self.h {
+ | ^
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0507`.
--> $DIR/option-content-move.rs:11:20
|
LL | if selection.1.unwrap().contains(selection.0) {
- | ^^^^^^^^^^^
- | |
- | move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
- | help: consider borrowing the `Option`'s content: `selection.1.as_ref()`
+ | ^^^^^^^^^^^ move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the `Option`'s content
+ |
+LL | if selection.1.as_ref().unwrap().contains(selection.0) {
+ | ^^^^^^^^^
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
--> $DIR/option-content-move.rs:29:20
|
LL | if selection.1.unwrap().contains(selection.0) {
- | ^^^^^^^^^^^
- | |
- | move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
- | help: consider borrowing the `Result`'s content: `selection.1.as_ref()`
+ | ^^^^^^^^^^^ move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the `Result`'s content
+ |
+LL | if selection.1.as_ref().unwrap().contains(selection.0) {
+ | ^^^^^^^^^
error: aborting due to 2 previous errors
fn f1(_: &str) {}
macro_rules! m1 {
($e:expr) => {
- f1($e);
+ f1($e)
};
}
macro_rules! m3 {
fn f1(_: &str) {}
macro_rules! m2 {
($e:expr) => {
- f1(*$e);
+ f1(*$e)
};
}
macro_rules! m3 {