Auto merge of #80708 - JohnTitor:rollup-6esk027, r=JohnTitor
Rollup of 12 pull requests Successful merges: - #80442 (Mention Arc::make_mut and Rc::make_mut in the documentation of Cow) - #80533 (bootstrap: clippy fixes) - #80538 (Add check for `[T;N]`/`usize` mismatch in astconv) - #80612 (Remove reverted change from relnotes) - #80627 (Builder: Warn if test file does not exist) - #80637 (Use Option::filter instead of open-coding it) - #80643 (Move variable into the only branch where it is relevant) - #80656 (Fixed documentation error for `std::hint::spin_loop`) - #80666 (Fix missing link for "fully qualified syntax") - #80672 (./x.py clippy: allow the most noisy lints) - #80677 (doc -- list edit for consistency) - #80696 (make sure that promoteds which fail to evaluate in dead const code behave correctly) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f412fb56b8
@ -3745,6 +3745,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_feature",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
|
@ -45,7 +45,6 @@ Libraries
|
||||
|
||||
- [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
|
||||
- [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
|
||||
- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
@ -110,7 +109,6 @@ related tools.
|
||||
[76199]: https://github.com/rust-lang/rust/pull/76199
|
||||
[76119]: https://github.com/rust-lang/rust/pull/76119
|
||||
[75914]: https://github.com/rust-lang/rust/pull/75914
|
||||
[74989]: https://github.com/rust-lang/rust/pull/74989
|
||||
[79004]: https://github.com/rust-lang/rust/pull/79004
|
||||
[78676]: https://github.com/rust-lang/rust/pull/78676
|
||||
[79904]: https://github.com/rust-lang/rust/issues/79904
|
||||
|
@ -9,6 +9,7 @@ doctest = false
|
||||
|
||||
[dependencies]
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
|
@ -290,6 +290,14 @@ impl GenericArg<'_> {
|
||||
GenericArg::Const(_) => "const",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd {
|
||||
match self {
|
||||
GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
|
||||
GenericArg::Type(_) => ast::ParamKindOrd::Type,
|
||||
GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
|
@ -43,22 +43,18 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
|
||||
let ty_opt = self
|
||||
.infcx
|
||||
self.infcx
|
||||
.in_progress_typeck_results
|
||||
.and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id));
|
||||
match ty_opt {
|
||||
Some(ty) => {
|
||||
let ty = self.infcx.resolve_vars_if_possible(ty);
|
||||
if ty.walk().any(|inner| {
|
||||
.and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id))
|
||||
.map(|ty| self.infcx.resolve_vars_if_possible(ty))
|
||||
.filter(|ty| {
|
||||
ty.walk().any(|inner| {
|
||||
inner == self.target
|
||||
|| match (inner.unpack(), self.target.unpack()) {
|
||||
(GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
|
||||
use ty::{Infer, TyVar};
|
||||
match (inner_ty.kind(), target_ty.kind()) {
|
||||
(
|
||||
&ty::Infer(ty::TyVar(a_vid)),
|
||||
&ty::Infer(ty::TyVar(b_vid)),
|
||||
) => self
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
@ -69,14 +65,8 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}) {
|
||||
Some(ty)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1341,15 +1341,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
return &[];
|
||||
}
|
||||
|
||||
// Do a reverse lookup beforehand to avoid touching the crate_num
|
||||
// hash map in the loop below.
|
||||
let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
|
||||
Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
|
||||
Some(None) => return &[],
|
||||
None => None,
|
||||
};
|
||||
if let Some(def_id) = filter {
|
||||
// Do a reverse lookup beforehand to avoid touching the crate_num
|
||||
// hash map in the loop below.
|
||||
let filter = match self.reverse_translate_def_id(def_id) {
|
||||
Some(def_id) => (def_id.krate.as_u32(), def_id.index),
|
||||
None => return &[],
|
||||
};
|
||||
|
||||
if let Some(filter) = filter {
|
||||
if let Some(impls) = self.trait_impls.get(&filter) {
|
||||
tcx.arena.alloc_from_iter(
|
||||
impls.decode(self).map(|(idx, simplified_self_ty)| {
|
||||
|
@ -801,6 +801,15 @@ impl GenericParamDefKind {
|
||||
GenericParamDefKind::Const => "constant",
|
||||
}
|
||||
}
|
||||
pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
|
||||
match self {
|
||||
GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
|
||||
GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
|
||||
GenericParamDefKind::Const => {
|
||||
ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
|
@ -11,7 +11,7 @@ use rustc_hir::GenericArg;
|
||||
use rustc_middle::ty::{
|
||||
self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session};
|
||||
use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
|
||||
use rustc_span::{symbol::kw, MultiSpan, Span};
|
||||
|
||||
use smallvec::SmallVec;
|
||||
@ -20,62 +20,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
/// Report an error that a generic argument did not match the generic parameter that was
|
||||
/// expected.
|
||||
fn generic_arg_mismatch_err(
|
||||
sess: &Session,
|
||||
tcx: TyCtxt<'_>,
|
||||
arg: &GenericArg<'_>,
|
||||
kind: &'static str,
|
||||
param: &GenericParamDef,
|
||||
possible_ordering_error: bool,
|
||||
help: Option<&str>,
|
||||
) {
|
||||
let sess = tcx.sess;
|
||||
let mut err = struct_span_err!(
|
||||
sess,
|
||||
arg.span(),
|
||||
E0747,
|
||||
"{} provided when a {} was expected",
|
||||
arg.descr(),
|
||||
kind,
|
||||
param.kind.descr(),
|
||||
);
|
||||
|
||||
let unordered = sess.features_untracked().const_generics;
|
||||
let kind_ord = match kind {
|
||||
"lifetime" => ParamKindOrd::Lifetime,
|
||||
"type" => ParamKindOrd::Type,
|
||||
"constant" => ParamKindOrd::Const { unordered },
|
||||
// It's more concise to match on the string representation, though it means
|
||||
// the match is non-exhaustive.
|
||||
_ => bug!("invalid generic parameter kind {}", kind),
|
||||
};
|
||||
|
||||
if let ParamKindOrd::Const { .. } = kind_ord {
|
||||
if let GenericParamDefKind::Const { .. } = param.kind {
|
||||
if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg {
|
||||
err.help("const arguments cannot yet be inferred with `_`");
|
||||
}
|
||||
}
|
||||
|
||||
let arg_ord = match arg {
|
||||
GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
|
||||
GenericArg::Type(_) => ParamKindOrd::Type,
|
||||
GenericArg::Const(_) => ParamKindOrd::Const { unordered },
|
||||
};
|
||||
|
||||
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }))
|
||||
&& matches!(kind_ord, ParamKindOrd::Const { .. })
|
||||
{
|
||||
let suggestions = vec![
|
||||
(arg.span().shrink_to_lo(), String::from("{ ")),
|
||||
(arg.span().shrink_to_hi(), String::from(" }")),
|
||||
];
|
||||
err.multipart_suggestion(
|
||||
"if this generic argument was intended as a const parameter, \
|
||||
// Specific suggestion set for diagnostics
|
||||
match (arg, ¶m.kind) {
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => {
|
||||
let suggestions = vec![
|
||||
(arg.span().shrink_to_lo(), String::from("{ ")),
|
||||
(arg.span().shrink_to_hi(), String::from(" }")),
|
||||
];
|
||||
err.multipart_suggestion(
|
||||
"if this generic argument was intended as a const parameter, \
|
||||
try surrounding it with braces:",
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
||||
GenericParamDefKind::Const { .. },
|
||||
) if tcx.type_of(param.def_id) == tcx.types.usize => {
|
||||
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
|
||||
if let Ok(snippet) = snippet {
|
||||
err.span_suggestion(
|
||||
arg.span(),
|
||||
"array type provided where a `usize` was expected, try",
|
||||
format!("{{ {} }}", snippet),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let kind_ord = param.kind.to_ord(tcx);
|
||||
let arg_ord = arg.to_ord(&tcx.features());
|
||||
|
||||
// This note is only true when generic parameters are strictly ordered by their kind.
|
||||
if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
|
||||
let (first, last) =
|
||||
if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
|
||||
let (first, last) = if kind_ord < arg_ord {
|
||||
(param.kind.descr(), arg.descr())
|
||||
} else {
|
||||
(arg.descr(), param.kind.descr())
|
||||
};
|
||||
err.note(&format!("{} arguments must be provided before {} arguments", first, last));
|
||||
if let Some(help) = help {
|
||||
err.help(help);
|
||||
@ -203,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// We expected a lifetime argument, but got a type or const
|
||||
// argument. That means we're inferring the lifetimes.
|
||||
substs.push(ctx.inferred_kind(None, param, infer_args));
|
||||
force_infer_lt = Some(arg);
|
||||
force_infer_lt = Some((arg, param));
|
||||
params.next();
|
||||
}
|
||||
(GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
|
||||
@ -213,7 +223,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// ignore it.
|
||||
args.next();
|
||||
}
|
||||
(_, kind, _) => {
|
||||
(_, _, _) => {
|
||||
// We expected one kind of parameter, but the user provided
|
||||
// another. This is an error. However, if we already know that
|
||||
// the arguments don't match up with the parameters, we won't issue
|
||||
@ -256,9 +266,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
param_types_present.dedup();
|
||||
|
||||
Self::generic_arg_mismatch_err(
|
||||
tcx.sess,
|
||||
tcx,
|
||||
arg,
|
||||
kind.descr(),
|
||||
param,
|
||||
!args_iter.clone().is_sorted_by_key(|arg| match arg {
|
||||
GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
|
||||
GenericArg::Type(_) => ParamKindOrd::Type,
|
||||
@ -315,9 +325,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
{
|
||||
let kind = arg.descr();
|
||||
assert_eq!(kind, "lifetime");
|
||||
let provided =
|
||||
let (provided_arg, param) =
|
||||
force_infer_lt.expect("lifetimes ought to have been inferred");
|
||||
Self::generic_arg_mismatch_err(tcx.sess, provided, kind, false, None);
|
||||
Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -103,6 +103,11 @@ where
|
||||
/// is desired, `to_mut` will obtain a mutable reference to an owned
|
||||
/// value, cloning if necessary.
|
||||
///
|
||||
/// If you need reference-counting pointers, note that
|
||||
/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and
|
||||
/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write
|
||||
/// functionality as well.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -238,6 +238,7 @@
|
||||
//! [downgrade]: Rc::downgrade
|
||||
//! [upgrade]: Weak::upgrade
|
||||
//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
|
||||
//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
|
@ -91,7 +91,7 @@ pub const unsafe fn unreachable_unchecked() -> ! {
|
||||
/// };
|
||||
///
|
||||
/// // Back on our current thread, we wait for the value to be set
|
||||
/// while live.load(Ordering::Acquire) {
|
||||
/// while !live.load(Ordering::Acquire) {
|
||||
/// // The spin loop is a hint to the CPU that we're waiting, but probably
|
||||
/// // not for very long
|
||||
/// hint::spin_loop();
|
||||
|
@ -397,7 +397,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
|
||||
/// only be called at most `self.size() - idx - 1` times.
|
||||
/// 4. After `get_unchecked` is called, then only the following methods will be
|
||||
/// called on `self`:
|
||||
/// * `std::clone::Clone::clone`
|
||||
/// * `std::clone::Clone::clone()`
|
||||
/// * `std::iter::Iterator::size_hint()`
|
||||
/// * `std::iter::Iterator::next_back()`
|
||||
/// * `std::iter::Iterator::__iterator_get_unchecked()`
|
||||
|
@ -1534,7 +1534,7 @@ impl Rustflags {
|
||||
fn arg(&mut self, arg: &str) -> &mut Self {
|
||||
assert_eq!(arg.split(' ').count(), 1);
|
||||
if !self.0.is_empty() {
|
||||
self.0.push_str(" ");
|
||||
self.0.push(' ');
|
||||
}
|
||||
self.0.push_str(arg);
|
||||
self
|
||||
|
@ -74,9 +74,9 @@ impl GitInfo {
|
||||
if let Some(ref inner) = self.inner {
|
||||
version.push_str(" (");
|
||||
version.push_str(&inner.short_sha);
|
||||
version.push_str(" ");
|
||||
version.push(' ');
|
||||
version.push_str(&inner.commit_date);
|
||||
version.push_str(")");
|
||||
version.push(')');
|
||||
}
|
||||
version
|
||||
}
|
||||
|
@ -21,6 +21,16 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
|
||||
}
|
||||
|
||||
if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
|
||||
// disable the most spammy clippy lints
|
||||
let ignored_lints = vec![
|
||||
"many_single_char_names", // there are a lot in stdarch
|
||||
"collapsible_if",
|
||||
"type_complexity",
|
||||
"missing_safety_doc", // almost 3K warnings
|
||||
"too_many_arguments",
|
||||
"needless_lifetimes", // people want to keep the lifetimes
|
||||
"wrong_self_convention",
|
||||
];
|
||||
let mut args = vec![];
|
||||
if fix {
|
||||
#[rustfmt::skip]
|
||||
@ -33,6 +43,7 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
|
||||
]));
|
||||
}
|
||||
args.extend(strings(&["--", "--cap-lints", "warn"]));
|
||||
args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
|
||||
args
|
||||
} else {
|
||||
vec![]
|
||||
|
@ -1326,17 +1326,17 @@ impl Step for Extended {
|
||||
license += &builder.read(&builder.src.join("COPYRIGHT"));
|
||||
license += &builder.read(&builder.src.join("LICENSE-APACHE"));
|
||||
license += &builder.read(&builder.src.join("LICENSE-MIT"));
|
||||
license.push_str("\n");
|
||||
license.push_str("\n");
|
||||
license.push('\n');
|
||||
license.push('\n');
|
||||
|
||||
let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
|
||||
let mut rtf = rtf.to_string();
|
||||
rtf.push_str("\n");
|
||||
rtf.push('\n');
|
||||
for line in license.lines() {
|
||||
rtf.push_str(line);
|
||||
rtf.push_str("\\line ");
|
||||
}
|
||||
rtf.push_str("}");
|
||||
rtf.push('}');
|
||||
|
||||
fn filter(contents: &str, marker: &str) -> String {
|
||||
let start = format!("tool-{}-start", marker);
|
||||
|
@ -1083,7 +1083,7 @@ impl Build {
|
||||
if let Some(ref s) = self.config.description {
|
||||
version.push_str(" (");
|
||||
version.push_str(s);
|
||||
version.push_str(")");
|
||||
version.push(')');
|
||||
}
|
||||
version
|
||||
}
|
||||
@ -1144,7 +1144,7 @@ impl Build {
|
||||
&& (dep != "profiler_builtins"
|
||||
|| target
|
||||
.map(|t| self.config.profiler_enabled(t))
|
||||
.unwrap_or(self.config.any_profiler_enabled()))
|
||||
.unwrap_or_else(|| self.config.any_profiler_enabled()))
|
||||
&& (dep != "rustc_codegen_llvm" || self.config.llvm_enabled())
|
||||
{
|
||||
list.push(*dep);
|
||||
|
@ -163,7 +163,11 @@ pub fn check(build: &mut Build) {
|
||||
panic!("the iOS target is only supported on macOS");
|
||||
}
|
||||
|
||||
build.config.target_config.entry(*target).or_insert(Target::from_triple(&target.triple));
|
||||
build
|
||||
.config
|
||||
.target_config
|
||||
.entry(*target)
|
||||
.or_insert_with(|| Target::from_triple(&target.triple));
|
||||
|
||||
if target.contains("-none-") || target.contains("nvptx") {
|
||||
if build.no_std(*target) == Some(false) {
|
||||
|
@ -89,7 +89,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let path = cfg_file.unwrap_or("config.toml".into());
|
||||
let path = cfg_file.unwrap_or_else(|| "config.toml".into());
|
||||
let settings = format!(
|
||||
"# Includes one of the default files in src/bootstrap/defaults\n\
|
||||
profile = \"{}\"\n\
|
||||
@ -156,7 +156,7 @@ pub fn interactive_path() -> io::Result<Profile> {
|
||||
io::stdout().flush()?;
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input)?;
|
||||
if input == "" {
|
||||
if input.is_empty() {
|
||||
eprintln!("EOF on stdin, when expecting answer to question. Giving up.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
@ -1126,7 +1126,19 @@ note: if you're sure you want to do this, please open an issue as to why. In the
|
||||
Ok(path) => path,
|
||||
Err(_) => p,
|
||||
})
|
||||
.filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
|
||||
.filter(|p| p.starts_with(suite_path))
|
||||
.filter(|p| {
|
||||
let exists = p.is_dir() || p.is_file();
|
||||
if !exists {
|
||||
if let Some(p) = p.to_str() {
|
||||
builder.info(&format!(
|
||||
"Warning: Skipping \"{}\": not a regular file or directory",
|
||||
p
|
||||
));
|
||||
}
|
||||
}
|
||||
exists
|
||||
})
|
||||
.filter_map(|p| {
|
||||
// Since test suite paths are themselves directories, if we don't
|
||||
// specify a directory or file, we'll get an empty string here
|
||||
@ -1135,7 +1147,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
|
||||
// flag is respected, so providing an empty --test-args conflicts with
|
||||
// any following it.
|
||||
match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
|
||||
Some(s) if s != "" => Some(s),
|
||||
Some(s) if !s.is_empty() => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
|
10
src/test/ui/const-generics/suggest_const_for_array.rs
Normal file
10
src/test/ui/const-generics/suggest_const_for_array.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![crate_type = "lib"]
|
||||
|
||||
fn example<const N: usize>() {}
|
||||
|
||||
fn other() {
|
||||
example::<[usize; 3]>();
|
||||
//~^ ERROR type provided when a const
|
||||
example::<[usize; 4+5]>();
|
||||
//~^ ERROR type provided when a const
|
||||
}
|
15
src/test/ui/const-generics/suggest_const_for_array.stderr
Normal file
15
src/test/ui/const-generics/suggest_const_for_array.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/suggest_const_for_array.rs:6:13
|
||||
|
|
||||
LL | example::<[usize; 3]>();
|
||||
| ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }`
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/suggest_const_for_array.rs:8:13
|
||||
|
|
||||
LL | example::<[usize; 4+5]>();
|
||||
| ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0747`.
|
@ -4,12 +4,23 @@
|
||||
|
||||
fn foo(_: &'static [&'static str]) {}
|
||||
fn bar(_: &'static [&'static str; 3]) {}
|
||||
fn baz_i32(_: &'static i32) {}
|
||||
fn baz_u32(_: &'static u32) {}
|
||||
const fn baz_i32(_: &'static i32) {}
|
||||
const fn baz_u32(_: &'static u32) {}
|
||||
|
||||
const fn fail() -> i32 { 1/0 }
|
||||
const C: i32 = {
|
||||
// Promoted that fails to evaluate in dead code -- this must work
|
||||
// (for backwards compatibility reasons).
|
||||
if false {
|
||||
baz_i32(&fail());
|
||||
}
|
||||
42
|
||||
};
|
||||
|
||||
fn main() {
|
||||
foo(&["a", "b", "c"]);
|
||||
bar(&["d", "e", "f"]);
|
||||
assert_eq!(C, 42);
|
||||
|
||||
// make sure that these do not cause trouble despite overflowing
|
||||
baz_u32(&(0-1));
|
||||
|
Loading…
Reference in New Issue
Block a user