Auto merge of #99462 - matthiaskrgr:rollup-ihhwaru, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #98028 (Add E0790 as more specific variant of E0283) - #99384 (use body's param-env when checking if type needs drop) - #99401 (Avoid `Symbol` to `&str` conversions) - #99419 (Stabilize `core::task::ready!`) - #99435 (Revert "Stabilize $$ in Rust 1.63.0") - #99438 (Improve suggestions for `NonZeroT` <- `T` coercion error) - #99441 (Update mdbook) - #99453 (⬆️ rust-analyzer) - #99457 (use `par_for_each_in` in `par_body_owners` and `collect_crate_mono_items`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a289cfcfb3
45
Cargo.lock
45
Cargo.lock
@ -634,7 +634,7 @@ version = "3.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1202,17 +1202,14 @@ checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
|
||||
|
||||
[[package]]
|
||||
name = "elasticlunr-rs"
|
||||
version = "2.3.9"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35622eb004c8f0c5e7e2032815f3314a93df0db30a1ce5c94e62c1ecc81e22b9"
|
||||
checksum = "e6dae5cac90640734ee881bc5f21b6e5123f4e5235e52428db114abffc2391d6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1735,15 +1732,6 @@ dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
@ -2360,9 +2348,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.4.18"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
|
||||
checksum = "13cdad8057b09a519c6c63e6d7c93ea854f5d7fbfe284df864d5e1140d215a2d"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
@ -2370,7 +2358,7 @@ dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"elasticlunr-rs",
|
||||
"env_logger 0.7.1",
|
||||
"env_logger 0.9.0",
|
||||
"handlebars",
|
||||
"lazy_static",
|
||||
"log",
|
||||
@ -2379,7 +2367,6 @@ dependencies = [
|
||||
"pulldown-cmark",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tempfile",
|
||||
@ -3335,7 +3322,7 @@ dependencies = [
|
||||
"difference",
|
||||
"env_logger 0.9.0",
|
||||
"futures 0.3.19",
|
||||
"heck 0.4.0",
|
||||
"heck",
|
||||
"home",
|
||||
"itertools",
|
||||
"jsonrpc-core",
|
||||
@ -5134,24 +5121,6 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
|
||||
dependencies = [
|
||||
"heck 0.3.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.91"
|
||||
|
@ -145,7 +145,7 @@ pub(crate) fn lower_inline_asm(
|
||||
InlineAsmRegOrRegClass::Reg(s) => {
|
||||
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
|
||||
asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| {
|
||||
let msg = format!("invalid register `{}`: {}", s.as_str(), e);
|
||||
let msg = format!("invalid register `{}`: {}", s, e);
|
||||
sess.struct_span_err(*op_sp, &msg).emit();
|
||||
asm::InlineAsmReg::Err
|
||||
})
|
||||
@ -156,7 +156,7 @@ pub(crate) fn lower_inline_asm(
|
||||
InlineAsmRegOrRegClass::RegClass(s) => {
|
||||
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
|
||||
asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| {
|
||||
let msg = format!("invalid register class `{}`: {}", s.as_str(), e);
|
||||
let msg = format!("invalid register class `{}`: {}", s, e);
|
||||
sess.struct_span_err(*op_sp, &msg).emit();
|
||||
asm::InlineAsmRegClass::Err
|
||||
})
|
||||
|
@ -62,9 +62,9 @@ fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||
let ast::StrLit { symbol_unescaped, span, .. } = abi;
|
||||
|
||||
if let ast::Const::Yes(_) = constness {
|
||||
match symbol_unescaped.as_str() {
|
||||
match symbol_unescaped {
|
||||
// Stable
|
||||
"Rust" | "C" => {}
|
||||
sym::Rust | sym::C => {}
|
||||
abi => gate_feature_post!(
|
||||
&self,
|
||||
const_extern_fn,
|
||||
|
@ -55,7 +55,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
|
||||
// The initial byte `4` instructs GDB that the following pretty printer
|
||||
// is defined inline as opposed to in a standalone file.
|
||||
section_contents.extend_from_slice(b"\x04");
|
||||
let vis_name = format!("pretty-printer-{}-{}\n", crate_name.as_str(), index);
|
||||
let vis_name = format!("pretty-printer-{}-{}\n", crate_name, index);
|
||||
section_contents.extend_from_slice(vis_name.as_bytes());
|
||||
section_contents.extend_from_slice(&visualizer.src);
|
||||
|
||||
|
@ -146,7 +146,7 @@ pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
|
||||
t.into_iter()
|
||||
}
|
||||
|
||||
pub fn par_for_each_in<T: IntoIterator>(t: T, for_each: impl Fn(T::Item) + Sync + Send) {
|
||||
pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
|
||||
// We catch panics here ensuring that all the loop iterations execute.
|
||||
// This makes behavior consistent with the parallel compiler.
|
||||
let mut panic = None;
|
||||
|
@ -492,6 +492,7 @@
|
||||
E0786: include_str!("./error_codes/E0786.md"),
|
||||
E0787: include_str!("./error_codes/E0787.md"),
|
||||
E0788: include_str!("./error_codes/E0788.md"),
|
||||
E0790: include_str!("./error_codes/E0790.md"),
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
|
@ -3,48 +3,27 @@ An implementation cannot be chosen unambiguously because of lack of information.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0283
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
struct Foo;
|
||||
|
||||
impl Into<u32> for Foo {
|
||||
fn into(self) -> u32 { 1 }
|
||||
}
|
||||
|
||||
struct Impl;
|
||||
|
||||
impl Generator for Impl {
|
||||
fn create() -> u32 { 1 }
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cont: u32 = Generator::create();
|
||||
// error, impossible to choose one of Generator trait implementation
|
||||
// Should it be Impl or AnotherImpl, maybe something else?
|
||||
}
|
||||
let foo = Foo;
|
||||
let bar: u32 = foo.into() * 1u32;
|
||||
```
|
||||
|
||||
This error can be solved by adding type annotations that provide the missing
|
||||
information to the compiler. In this case, the solution is to use a concrete
|
||||
type:
|
||||
information to the compiler. In this case, the solution is to specify the
|
||||
trait's type parameter:
|
||||
|
||||
```
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
struct Foo;
|
||||
|
||||
impl Into<u32> for Foo {
|
||||
fn into(self) -> u32 { 1 }
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let gen1 = AnotherImpl::create();
|
||||
|
||||
// if there are multiple methods with same name (different traits)
|
||||
let gen2 = <AnotherImpl as Generator>::create();
|
||||
}
|
||||
let foo = Foo;
|
||||
let bar: u32 = Into::<u32>::into(foo) * 1u32;
|
||||
```
|
||||
|
47
compiler/rustc_error_codes/src/error_codes/E0790.md
Normal file
47
compiler/rustc_error_codes/src/error_codes/E0790.md
Normal file
@ -0,0 +1,47 @@
|
||||
You need to specify a specific implementation of the trait in order to call the
|
||||
method.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0790
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
}
|
||||
|
||||
struct Impl;
|
||||
|
||||
impl Generator for Impl {
|
||||
fn create() -> u32 { 1 }
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
let cont: u32 = Generator::create();
|
||||
// error, impossible to choose one of Generator trait implementation
|
||||
// Should it be Impl or AnotherImpl, maybe something else?
|
||||
```
|
||||
|
||||
This error can be solved by adding type annotations that provide the missing
|
||||
information to the compiler. In this case, the solution is to use a concrete
|
||||
type:
|
||||
|
||||
```
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
let gen1 = AnotherImpl::create();
|
||||
|
||||
// if there are multiple methods with same name (different traits)
|
||||
let gen2 = <AnotherImpl as Generator>::create();
|
||||
```
|
@ -234,6 +234,8 @@ fn parse_tree(
|
||||
sess,
|
||||
&Token { kind: token::Dollar, span },
|
||||
);
|
||||
} else {
|
||||
maybe_emit_macro_metavar_expr_feature(features, sess, span);
|
||||
}
|
||||
TokenTree::token(token::Dollar, span)
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ pub fn suggest_adding_lifetime_params<'tcx>(
|
||||
if is_impl {
|
||||
sugg.push_str(" and update trait if needed");
|
||||
}
|
||||
err.multipart_suggestion(sugg.as_str(), suggestions, Applicability::MaybeIncorrect);
|
||||
err.multipart_suggestion(sugg, suggestions, Applicability::MaybeIncorrect);
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -491,9 +491,7 @@ pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
|
||||
}
|
||||
|
||||
pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
|
||||
use rustc_data_structures::sync::{par_iter, ParallelIterator};
|
||||
|
||||
par_iter(&self.tcx.hir_crate_items(()).body_owners[..]).for_each(|&def_id| f(def_id));
|
||||
par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
|
||||
}
|
||||
|
||||
pub fn ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
|
||||
|
@ -74,6 +74,10 @@ impl TraitImpls {
|
||||
pub fn blanket_impls(&self) -> &[DefId] {
|
||||
self.blanket_impls.as_slice()
|
||||
}
|
||||
|
||||
pub fn non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>> {
|
||||
&self.non_blanket_impls
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TraitDef {
|
||||
|
@ -431,9 +431,9 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
||||
let lhs = &self.thir[lhs];
|
||||
if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
|
||||
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
|
||||
if assigned_ty.needs_drop(self.tcx, self.tcx.param_env(adt_def.did())) {
|
||||
if assigned_ty.needs_drop(self.tcx, self.param_env) {
|
||||
// This would be unsafe, but should be outright impossible since we reject such unions.
|
||||
self.tcx.sess.delay_span_bug(assignment_span, "union fields that need dropping should be impossible");
|
||||
self.tcx.sess.delay_span_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}"));
|
||||
}
|
||||
} else {
|
||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||
|
@ -219,14 +219,11 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location:
|
||||
// We have to check the actual type of the assignment, as that determines if the
|
||||
// old value is being dropped.
|
||||
let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||
if assigned_ty.needs_drop(
|
||||
self.tcx,
|
||||
self.tcx.param_env(base_ty.ty_adt_def().unwrap().did()),
|
||||
) {
|
||||
if assigned_ty.needs_drop(self.tcx, self.param_env) {
|
||||
// This would be unsafe, but should be outright impossible since we reject such unions.
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.source_info.span,
|
||||
"union fields that need dropping should be impossible",
|
||||
format!("union fields that need dropping should be impossible: {assigned_ty}")
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -180,7 +180,7 @@
|
||||
//! regardless of whether it is actually needed or not.
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
|
||||
use rustc_data_structures::sync::{par_for_each_in, MTLock, MTRef};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
@ -346,7 +346,7 @@ pub fn collect_crate_mono_items(
|
||||
let inlining_map: MTRef<'_, _> = &mut inlining_map;
|
||||
|
||||
tcx.sess.time("monomorphization_collector_graph_walk", || {
|
||||
par_iter(roots).for_each(|root| {
|
||||
par_for_each_in(roots, |root| {
|
||||
let mut recursion_depths = DefIdMap::default();
|
||||
collect_items_rec(
|
||||
tcx,
|
||||
|
@ -77,7 +77,7 @@ fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol)
|
||||
.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
&format!("`{}` attribute can only be used on functions", sym.as_str()),
|
||||
&format!("`{}` attribute can only be used on functions", sym),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
@ -1627,7 +1627,7 @@ pub(crate) fn add_typo_suggestion(
|
||||
"{}{} `{}` defined here",
|
||||
prefix,
|
||||
suggestion.res.descr(),
|
||||
suggestion.candidate.as_str(),
|
||||
suggestion.candidate,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ pub(crate) fn descr(&self) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn suggestion(&self, sugg: &str) -> String {
|
||||
pub(crate) fn suggestion(&self, sugg: impl std::fmt::Display) -> String {
|
||||
match self {
|
||||
Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
|
||||
Self::ClosureEmpty => format!("for<{}>", sugg),
|
||||
@ -2313,8 +2313,8 @@ pub(crate) fn add_missing_lifetime_specifiers_label(
|
||||
|
||||
let suggest_existing =
|
||||
|err: &mut Diagnostic,
|
||||
name: &str,
|
||||
formatters: Vec<Option<Box<dyn Fn(&str) -> String>>>| {
|
||||
name: Symbol,
|
||||
formatters: Vec<Option<Box<dyn Fn(Symbol) -> String>>>| {
|
||||
if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) =
|
||||
self.missing_named_lifetime_spots.iter().rev().next()
|
||||
{
|
||||
@ -2334,7 +2334,8 @@ pub(crate) fn add_missing_lifetime_specifiers_label(
|
||||
// If all single char lifetime names are present, we wrap around and double the chars.
|
||||
let lt_name = (1..)
|
||||
.flat_map(a_to_z_repeat_n)
|
||||
.find(|lt| !lifetime_names.contains(&Symbol::intern(<)))
|
||||
.map(|lt| Symbol::intern(<))
|
||||
.find(|lt| !lifetime_names.contains(lt))
|
||||
.unwrap();
|
||||
let msg = format!(
|
||||
"consider making the {} lifetime-generic with a new `{}` lifetime",
|
||||
@ -2361,7 +2362,7 @@ pub(crate) fn add_missing_lifetime_specifiers_label(
|
||||
introduce_suggestion.push((*for_span, for_sugg));
|
||||
for ((span, _), formatter) in spans_with_counts.iter().zip(formatters.iter()) {
|
||||
if let Some(formatter) = formatter {
|
||||
introduce_suggestion.push((*span, formatter(<_name)));
|
||||
introduce_suggestion.push((*span, formatter(lt_name)));
|
||||
}
|
||||
}
|
||||
err.multipart_suggestion_verbose(
|
||||
@ -2584,7 +2585,7 @@ fn span_underscore_borrow(&self) -> Span {
|
||||
let lifetime_names: Vec<_> = lifetime_names.iter().collect();
|
||||
match &lifetime_names[..] {
|
||||
[name] => {
|
||||
let mut suggs: Vec<Option<Box<dyn Fn(&str) -> String>>> = Vec::new();
|
||||
let mut suggs: Vec<Option<Box<dyn Fn(Symbol) -> String>>> = Vec::new();
|
||||
for (snippet, (_, count)) in snippets.iter().zip(spans_with_counts.iter().copied())
|
||||
{
|
||||
suggs.push(match snippet.as_deref() {
|
||||
@ -2592,7 +2593,11 @@ fn span_underscore_borrow(&self) -> Span {
|
||||
Some("'_") => Some(Box::new(|n| n.to_string())),
|
||||
Some("") => Some(Box::new(move |n| format!("{}, ", n).repeat(count))),
|
||||
Some("<") => Some(Box::new(move |n| {
|
||||
std::iter::repeat(n).take(count).collect::<Vec<_>>().join(", ")
|
||||
std::iter::repeat(n)
|
||||
.take(count)
|
||||
.map(|n| n.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
})),
|
||||
Some(snippet) if !snippet.ends_with('>') => Some(Box::new(move |name| {
|
||||
format!(
|
||||
@ -2607,7 +2612,7 @@ fn span_underscore_borrow(&self) -> Span {
|
||||
_ => None,
|
||||
});
|
||||
}
|
||||
suggest_existing(err, name.as_str(), suggs);
|
||||
suggest_existing(err, **name, suggs);
|
||||
}
|
||||
[] => {
|
||||
let mut suggs = Vec::new();
|
||||
|
@ -325,7 +325,7 @@ fn check_unused_macros(&mut self) {
|
||||
UNUSED_MACROS,
|
||||
node_id,
|
||||
ident.span,
|
||||
&format!("unused macro definition: `{}`", ident.as_str()),
|
||||
&format!("unused macro definition: `{}`", ident.name),
|
||||
);
|
||||
}
|
||||
for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() {
|
||||
@ -341,7 +341,7 @@ fn check_unused_macros(&mut self) {
|
||||
&format!(
|
||||
"{} rule of macro `{}` is never used",
|
||||
crate::diagnostics::ordinalize(arm_i + 1),
|
||||
ident.as_str()
|
||||
ident.name
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -223,6 +223,16 @@
|
||||
LintPass,
|
||||
Mutex,
|
||||
N,
|
||||
NonZeroI128,
|
||||
NonZeroI16,
|
||||
NonZeroI32,
|
||||
NonZeroI64,
|
||||
NonZeroI8,
|
||||
NonZeroU128,
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
NonZeroU8,
|
||||
None,
|
||||
Ok,
|
||||
Option,
|
||||
@ -257,6 +267,7 @@
|
||||
Result,
|
||||
Return,
|
||||
Right,
|
||||
Rust,
|
||||
RustcDecodable,
|
||||
RustcEncodable,
|
||||
Send,
|
||||
|
@ -474,7 +474,7 @@ fn report_selection_error(
|
||||
if let Some(ref s) = label {
|
||||
// If it has a custom `#[rustc_on_unimplemented]`
|
||||
// error message, let's display it as the label!
|
||||
err.span_label(span, s.as_str());
|
||||
err.span_label(span, s);
|
||||
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
|
||||
// When the self type is a type param We don't need to "the trait
|
||||
// `std::marker::Sized` is not implemented for `T`" as we will point
|
||||
@ -531,7 +531,7 @@ fn report_selection_error(
|
||||
let enclosing_scope_span =
|
||||
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
|
||||
|
||||
err.span_label(enclosing_scope_span, s.as_str());
|
||||
err.span_label(enclosing_scope_span, s);
|
||||
}
|
||||
|
||||
self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
|
||||
@ -2104,6 +2104,98 @@ fn maybe_report_ambiguity(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
|
||||
(body_id, subst.map(|subst| subst.unpack()))
|
||||
{
|
||||
struct FindExprBySpan<'hir> {
|
||||
span: Span,
|
||||
result: Option<&'hir hir::Expr<'hir>>,
|
||||
}
|
||||
|
||||
impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> {
|
||||
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
|
||||
if self.span == ex.span {
|
||||
self.result = Some(ex);
|
||||
} else {
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut expr_finder = FindExprBySpan { span, result: None };
|
||||
|
||||
expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
|
||||
|
||||
if let Some(hir::Expr {
|
||||
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }
|
||||
) = expr_finder.result
|
||||
&& let [
|
||||
..,
|
||||
trait_path_segment @ hir::PathSegment {
|
||||
res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)),
|
||||
..
|
||||
},
|
||||
hir::PathSegment {
|
||||
ident: assoc_item_name,
|
||||
res: Some(rustc_hir::def::Res::Def(_, item_id)),
|
||||
..
|
||||
}
|
||||
] = path.segments
|
||||
&& data.trait_ref.def_id == *trait_id
|
||||
&& self.tcx.trait_of_item(item_id) == Some(*trait_id)
|
||||
&& !self.is_tainted_by_errors()
|
||||
{
|
||||
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
|
||||
ty::AssocKind::Const => ("refer to the", "constant"),
|
||||
ty::AssocKind::Fn => ("call", "function"),
|
||||
ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
|
||||
};
|
||||
|
||||
// Replace the more general E0283 with a more specific error
|
||||
err.cancel();
|
||||
err = self.tcx.sess.struct_span_err_with_code(
|
||||
span,
|
||||
&format!(
|
||||
"cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
|
||||
),
|
||||
rustc_errors::error_code!(E0790),
|
||||
);
|
||||
|
||||
if let Some(local_def_id) = data.trait_ref.def_id.as_local()
|
||||
&& let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
|
||||
&& let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
|
||||
err.span_label(method_ref.span, format!("`{}::{}` defined here", trait_name, assoc_item_name));
|
||||
}
|
||||
|
||||
err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
|
||||
|
||||
let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
|
||||
|
||||
if trait_impls.blanket_impls().is_empty()
|
||||
&& let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
|
||||
&& let Some(impl_def_id) = impl_ty.def() {
|
||||
let message = if trait_impls.non_blanket_impls().len() == 1 {
|
||||
"use the fully-qualified path to the only available implementation".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"use a fully-qualified path to a specific available implementation ({} found)",
|
||||
trait_impls.non_blanket_impls().len()
|
||||
)
|
||||
};
|
||||
|
||||
err.multipart_suggestion(
|
||||
message,
|
||||
vec![
|
||||
(trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
|
||||
(trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
|
||||
],
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ pub(super) fn if_fallback_coercion<T>(
|
||||
&cause,
|
||||
&mut |err| {
|
||||
if let Some((span, msg)) = &ret_reason {
|
||||
err.span_label(*span, msg.as_str());
|
||||
err.span_label(*span, msg);
|
||||
} else if let ExprKind::Block(block, _) = &then_expr.kind
|
||||
&& let Some(expr) = &block.expr
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ pub fn emit_coerce_suggestions(
|
||||
self.annotate_expected_due_to_let_ty(err, expr, error);
|
||||
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
|
||||
self.suggest_compatible_variants(err, expr, expected, expr_ty);
|
||||
self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty);
|
||||
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
|
||||
return;
|
||||
}
|
||||
@ -347,7 +348,7 @@ fn suggest_compatible_variants(
|
||||
}
|
||||
}
|
||||
|
||||
let compatible_variants: Vec<String> = expected_adt
|
||||
let compatible_variants: Vec<(String, Option<String>)> = expected_adt
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|variant| {
|
||||
@ -355,6 +356,18 @@ fn suggest_compatible_variants(
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[0];
|
||||
|
||||
let field_is_local = sole_field.did.is_local();
|
||||
let field_is_accessible =
|
||||
sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx);
|
||||
|
||||
if !field_is_local && !field_is_accessible {
|
||||
return None;
|
||||
}
|
||||
|
||||
let note_about_variant_field_privacy = (field_is_local && !field_is_accessible)
|
||||
.then(|| format!(" (its field is private, but it's local to this crate and its privacy can be changed)"));
|
||||
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
if self.can_coerce(expr_ty, sole_field_ty) {
|
||||
let variant_path =
|
||||
@ -363,9 +376,9 @@ fn suggest_compatible_variants(
|
||||
if let Some(path) = variant_path.strip_prefix("std::prelude::")
|
||||
&& let Some((_, path)) = path.split_once("::")
|
||||
{
|
||||
return Some(path.to_string());
|
||||
return Some((path.to_string(), note_about_variant_field_privacy));
|
||||
}
|
||||
Some(variant_path)
|
||||
Some((variant_path, note_about_variant_field_privacy))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -379,10 +392,13 @@ fn suggest_compatible_variants(
|
||||
|
||||
match &compatible_variants[..] {
|
||||
[] => { /* No variants to format */ }
|
||||
[variant] => {
|
||||
[(variant, note)] => {
|
||||
// Just a single matching variant.
|
||||
err.multipart_suggestion_verbose(
|
||||
&format!("try wrapping the expression in `{variant}`"),
|
||||
&format!(
|
||||
"try wrapping the expression in `{variant}`{note}",
|
||||
note = note.as_deref().unwrap_or("")
|
||||
),
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
|
||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
||||
@ -397,7 +413,7 @@ fn suggest_compatible_variants(
|
||||
"try wrapping the expression in a variant of `{}`",
|
||||
self.tcx.def_path_str(expected_adt.did())
|
||||
),
|
||||
compatible_variants.into_iter().map(|variant| {
|
||||
compatible_variants.into_iter().map(|(variant, _)| {
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
|
||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
||||
@ -410,6 +426,57 @@ fn suggest_compatible_variants(
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_non_zero_new_unwrap(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expected: Ty<'tcx>,
|
||||
expr_ty: Ty<'tcx>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let (adt, unwrap) = match expected.kind() {
|
||||
// In case Option<NonZero*> is wanted, but * is provided, suggest calling new
|
||||
ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
|
||||
// Unwrap option
|
||||
let ty::Adt(adt, _) = substs.type_at(0).kind() else { return };
|
||||
|
||||
(adt, "")
|
||||
}
|
||||
// In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
|
||||
ty::Adt(adt, _) => (adt, ".unwrap()"),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let map = [
|
||||
(sym::NonZeroU8, tcx.types.u8),
|
||||
(sym::NonZeroU16, tcx.types.u16),
|
||||
(sym::NonZeroU32, tcx.types.u32),
|
||||
(sym::NonZeroU64, tcx.types.u64),
|
||||
(sym::NonZeroU128, tcx.types.u128),
|
||||
(sym::NonZeroI8, tcx.types.i8),
|
||||
(sym::NonZeroI16, tcx.types.i16),
|
||||
(sym::NonZeroI32, tcx.types.i32),
|
||||
(sym::NonZeroI64, tcx.types.i64),
|
||||
(sym::NonZeroI128, tcx.types.i128),
|
||||
];
|
||||
|
||||
let Some((s, _)) = map
|
||||
.iter()
|
||||
.find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t))
|
||||
else { return };
|
||||
|
||||
let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
|
||||
|
||||
err.multipart_suggestion(
|
||||
format!("consider calling `{s}::new`"),
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), format!("{path}::new(")),
|
||||
(expr.span.shrink_to_hi(), format!("){unwrap}")),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_conversion_methods(
|
||||
&self,
|
||||
span: Span,
|
||||
|
@ -408,8 +408,7 @@ fn check_overloaded_binop(
|
||||
false,
|
||||
),
|
||||
};
|
||||
let mut err =
|
||||
struct_span_err!(self.tcx.sess, op.span, E0369, "{}", message.as_str());
|
||||
let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}");
|
||||
if !lhs_expr.span.eq(&rhs_expr.span) {
|
||||
self.add_type_neq_err_label(
|
||||
&mut err,
|
||||
|
@ -39,6 +39,7 @@ macro_rules! nonzero_integers {
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(1)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[rustc_diagnostic_item = stringify!($Ty)]
|
||||
pub struct $Ty($Int);
|
||||
|
||||
impl $Ty {
|
||||
|
@ -11,7 +11,7 @@
|
||||
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
|
||||
|
||||
mod ready;
|
||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
||||
#[stable(feature = "ready_macro", since = "1.64.0")]
|
||||
pub use ready::ready;
|
||||
#[unstable(feature = "poll_ready", issue = "89780")]
|
||||
pub use ready::Ready;
|
||||
|
@ -13,8 +13,6 @@
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ready_macro)]
|
||||
///
|
||||
/// use std::task::{ready, Context, Poll};
|
||||
/// use std::future::{self, Future};
|
||||
/// use std::pin::Pin;
|
||||
@ -34,7 +32,6 @@
|
||||
/// The `ready!` call expands to:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(ready_macro)]
|
||||
/// # use std::task::{Context, Poll};
|
||||
/// # use std::future::{self, Future};
|
||||
/// # use std::pin::Pin;
|
||||
@ -53,7 +50,7 @@
|
||||
/// # Poll::Ready(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
||||
#[stable(feature = "ready_macro", since = "1.64.0")]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro ready($e:expr) {
|
||||
match $e {
|
||||
|
@ -2,8 +2,8 @@ trait A {
|
||||
const C: usize;
|
||||
|
||||
fn f() -> ([u8; A::C], [u8; A::C]);
|
||||
//~^ ERROR: type annotations needed
|
||||
//~| ERROR: type annotations needed
|
||||
//~^ ERROR: E0790
|
||||
//~| ERROR: E0790
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,27 +1,21 @@
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/issue-63496.rs:4:21
|
||||
|
|
||||
LL | const C: usize;
|
||||
| --------------- `A::C` defined here
|
||||
LL |
|
||||
LL | fn f() -> ([u8; A::C], [u8; A::C]);
|
||||
| ^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| help: use the fully qualified path to an implementation: `<Type as A>::C`
|
||||
|
|
||||
= note: cannot satisfy `_: A`
|
||||
= note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
| ^^^^ cannot refer to the associated constant of trait
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/issue-63496.rs:4:33
|
||||
|
|
||||
LL | const C: usize;
|
||||
| --------------- `A::C` defined here
|
||||
LL |
|
||||
LL | fn f() -> ([u8; A::C], [u8; A::C]);
|
||||
| ^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| help: use the fully qualified path to an implementation: `<Type as A>::C`
|
||||
|
|
||||
= note: cannot satisfy `_: A`
|
||||
= note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
| ^^^^ cannot refer to the associated constant of trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0790`.
|
||||
|
@ -1,6 +1,6 @@
|
||||
trait Bar {
|
||||
const X: usize;
|
||||
fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed
|
||||
fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790
|
||||
}
|
||||
|
||||
impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object
|
||||
|
@ -13,19 +13,15 @@ LL | const X: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
= help: consider moving `X` to another trait
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/issue-48027.rs:3:32
|
||||
|
|
||||
LL | const X: usize;
|
||||
| --------------- `Bar::X` defined here
|
||||
LL | fn return_n(&self) -> [u8; Bar::X];
|
||||
| ^^^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| help: use the fully qualified path to an implementation: `<Type as Bar>::X`
|
||||
|
|
||||
= note: cannot satisfy `_: Bar`
|
||||
= note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
| ^^^^^^ cannot refer to the associated constant of trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0283.
|
||||
Some errors have detailed explanations: E0038, E0790.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
@ -12,5 +12,5 @@ fn bar() -> isize { 42 }
|
||||
|
||||
pub fn main() {
|
||||
let x: isize = Foo::bar();
|
||||
//~^ ERROR type annotations needed
|
||||
//~^ ERROR E0790
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/associated-types-unconstrained.rs:14:20
|
||||
|
|
||||
LL | fn bar() -> isize;
|
||||
| ------------------ `Foo::bar` defined here
|
||||
...
|
||||
LL | let x: isize = Foo::bar();
|
||||
| ^^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: cannot satisfy `_: Foo`
|
||||
| ^^^^^^^^ cannot call associated function of trait
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0790`.
|
||||
|
@ -27,7 +27,7 @@ fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cont: u32 = Generator::create(); //~ ERROR E0283
|
||||
let cont: u32 = Generator::create(); //~ ERROR E0790
|
||||
}
|
||||
|
||||
fn buzz() {
|
||||
|
@ -1,10 +1,16 @@
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0283.rs:30:21
|
||||
|
|
||||
LL | fn create() -> u32;
|
||||
| ------------------- `Generator::create` defined here
|
||||
...
|
||||
LL | let cont: u32 = Generator::create();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
= note: cannot satisfy `_: Generator`
|
||||
help: use a fully-qualified path to a specific available implementation (2 found)
|
||||
|
|
||||
LL | let cont: u32 = <::Impl as Generator>::create();
|
||||
| ++++++++++ +
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/E0283.rs:35:24
|
||||
@ -27,4 +33,5 @@ LL | let bar = <Impl as Into<T>>::into(foo_impl) * 1u32;
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
Some errors have detailed explanations: E0283, E0790.
|
||||
For more information about an error, try `rustc --explain E0283`.
|
||||
|
53
src/test/ui/error-codes/E0790.rs
Normal file
53
src/test/ui/error-codes/E0790.rs
Normal file
@ -0,0 +1,53 @@
|
||||
mod inner {
|
||||
pub trait MyTrait {
|
||||
const MY_ASSOC_CONST: ();
|
||||
|
||||
fn my_fn();
|
||||
}
|
||||
|
||||
pub struct MyStruct;
|
||||
|
||||
impl MyTrait for MyStruct {
|
||||
const MY_ASSOC_CONST: () = ();
|
||||
|
||||
fn my_fn() {}
|
||||
}
|
||||
|
||||
fn call() {
|
||||
MyTrait::my_fn(); //~ ERROR E0790
|
||||
}
|
||||
|
||||
fn use_const() {
|
||||
let _ = MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
|
||||
}
|
||||
}
|
||||
|
||||
fn call_inner() {
|
||||
inner::MyTrait::my_fn(); //~ ERROR E0790
|
||||
}
|
||||
|
||||
fn use_const_inner() {
|
||||
let _ = inner::MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
|
||||
}
|
||||
|
||||
trait MyTrait2 {
|
||||
fn my_fn();
|
||||
}
|
||||
|
||||
struct Impl1;
|
||||
|
||||
impl MyTrait2 for Impl1 {
|
||||
fn my_fn() {}
|
||||
}
|
||||
|
||||
struct Impl2;
|
||||
|
||||
impl MyTrait2 for Impl2 {
|
||||
fn my_fn() {}
|
||||
}
|
||||
|
||||
fn call_multiple_impls() {
|
||||
MyTrait2::my_fn(); //~ ERROR E0790
|
||||
}
|
||||
|
||||
fn main() {}
|
73
src/test/ui/error-codes/E0790.stderr
Normal file
73
src/test/ui/error-codes/E0790.stderr
Normal file
@ -0,0 +1,73 @@
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0790.rs:17:9
|
||||
|
|
||||
LL | fn my_fn();
|
||||
| ----------- `MyTrait::my_fn` defined here
|
||||
...
|
||||
LL | MyTrait::my_fn();
|
||||
| ^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use the fully-qualified path to the only available implementation
|
||||
|
|
||||
LL | <::inner::MyStruct as MyTrait>::my_fn();
|
||||
| +++++++++++++++++++++ +
|
||||
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0790.rs:21:17
|
||||
|
|
||||
LL | const MY_ASSOC_CONST: ();
|
||||
| ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
|
||||
...
|
||||
LL | let _ = MyTrait::MY_ASSOC_CONST;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
|
||||
|
|
||||
help: use the fully-qualified path to the only available implementation
|
||||
|
|
||||
LL | let _ = <::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
|
||||
| +++++++++++++++++++++ +
|
||||
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0790.rs:26:5
|
||||
|
|
||||
LL | fn my_fn();
|
||||
| ----------- `MyTrait::my_fn` defined here
|
||||
...
|
||||
LL | inner::MyTrait::my_fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use the fully-qualified path to the only available implementation
|
||||
|
|
||||
LL | inner::<::inner::MyStruct as MyTrait>::my_fn();
|
||||
| +++++++++++++++++++++ +
|
||||
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0790.rs:30:13
|
||||
|
|
||||
LL | const MY_ASSOC_CONST: ();
|
||||
| ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
|
||||
...
|
||||
LL | let _ = inner::MyTrait::MY_ASSOC_CONST;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
|
||||
|
|
||||
help: use the fully-qualified path to the only available implementation
|
||||
|
|
||||
LL | let _ = inner::<::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
|
||||
| +++++++++++++++++++++ +
|
||||
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/E0790.rs:50:5
|
||||
|
|
||||
LL | fn my_fn();
|
||||
| ----------- `MyTrait2::my_fn` defined here
|
||||
...
|
||||
LL | MyTrait2::my_fn();
|
||||
| ^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation (2 found)
|
||||
|
|
||||
LL | <::Impl1 as MyTrait2>::my_fn();
|
||||
| +++++++++++ +
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0790`.
|
@ -1,5 +1,5 @@
|
||||
const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
|
||||
//~^ ERROR type annotations needed
|
||||
//~^ ERROR E0790
|
||||
|
||||
trait Tt {
|
||||
const fn const_val<T: Sized>() -> usize {
|
||||
|
@ -4,13 +4,17 @@ error[E0379]: functions in traits cannot be declared const
|
||||
LL | const fn const_val<T: Sized>() -> usize {
|
||||
| ^^^^^ functions in traits cannot be const
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/issue-54954.rs:1:24
|
||||
|
|
||||
LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: cannot satisfy `_: Tt`
|
||||
LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
...
|
||||
LL | / const fn const_val<T: Sized>() -> usize {
|
||||
LL | |
|
||||
LL | | core::mem::size_of::<T>()
|
||||
LL | | }
|
||||
| |_____- `Tt::const_val` defined here
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/issue-54954.rs:11:15
|
||||
@ -26,5 +30,5 @@ LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0080, E0283, E0379.
|
||||
Some errors have detailed explanations: E0080, E0379, E0790.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
|
@ -2,7 +2,7 @@ pub trait Foo: Sized {
|
||||
const SIZE: usize;
|
||||
|
||||
fn new(slice: &[u8; Foo::SIZE]) -> Self;
|
||||
//~^ ERROR: type annotations needed
|
||||
//~^ ERROR: E0790
|
||||
}
|
||||
|
||||
pub struct Bar<T: ?Sized>(T);
|
||||
|
@ -4,19 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo
|
||||
LL | Foo(Box::new(*slice))
|
||||
| ^^^ not a function, tuple struct or tuple variant
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/issue-58022.rs:4:25
|
||||
|
|
||||
LL | const SIZE: usize;
|
||||
| ------------------ `Foo::SIZE` defined here
|
||||
LL |
|
||||
LL | fn new(slice: &[u8; Foo::SIZE]) -> Self;
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| help: use the fully qualified path to an implementation: `<Type as Foo>::SIZE`
|
||||
|
|
||||
= note: cannot satisfy `_: Foo`
|
||||
= note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
| ^^^^^^^^^ cannot refer to the associated constant of trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0283, E0423.
|
||||
For more information about an error, try `rustc --explain E0283`.
|
||||
Some errors have detailed explanations: E0423, E0790.
|
||||
For more information about an error, try `rustc --explain E0423`.
|
||||
|
@ -1,12 +0,0 @@
|
||||
// check-pass
|
||||
|
||||
macro_rules! dollar_dollar {
|
||||
() => {
|
||||
macro_rules! bar {
|
||||
( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -5,6 +5,18 @@ macro_rules! count {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! dollar_dollar {
|
||||
() => {
|
||||
macro_rules! bar {
|
||||
( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
//~^ ERROR meta-variable expressions are unstable
|
||||
//~| ERROR meta-variable expressions are unstable
|
||||
//~| ERROR meta-variable expressions are unstable
|
||||
//~| ERROR meta-variable expressions are unstable
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! index {
|
||||
( $( $e:stmt ),* ) => {
|
||||
$( ${ignore(e)} ${index()} )*
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:3:10
|
||||
--> $DIR/required-feature.rs:3:10
|
||||
|
|
||||
LL | ${ count(e) }
|
||||
| ^^^^^^^^^^^^
|
||||
@ -8,7 +8,43 @@ LL | ${ count(e) }
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:10:13
|
||||
--> $DIR/required-feature.rs:11:16
|
||||
|
|
||||
LL | ( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
| ^
|
||||
|
|
||||
= note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-feature.rs:11:20
|
||||
|
|
||||
LL | ( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
| ^
|
||||
|
|
||||
= note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-feature.rs:11:39
|
||||
|
|
||||
LL | ( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
| ^
|
||||
|
|
||||
= note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-feature.rs:11:43
|
||||
|
|
||||
LL | ( $$( $$any:tt )* ) => { $$( $$any )* };
|
||||
| ^
|
||||
|
|
||||
= note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-feature.rs:22:13
|
||||
|
|
||||
LL | $( ${ignore(e)} ${index()} )*
|
||||
| ^^^^^^^^^^^
|
||||
@ -17,7 +53,7 @@ LL | $( ${ignore(e)} ${index()} )*
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:10:26
|
||||
--> $DIR/required-feature.rs:22:26
|
||||
|
|
||||
LL | $( ${ignore(e)} ${index()} )*
|
||||
| ^^^^^^^^^
|
||||
@ -26,7 +62,7 @@ LL | $( ${ignore(e)} ${index()} )*
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:18:19
|
||||
--> $DIR/required-feature.rs:30:19
|
||||
|
|
||||
LL | 0 $( + 1 ${ignore(i)} )*
|
||||
| ^^^^^^^^^^^
|
||||
@ -35,7 +71,7 @@ LL | 0 $( + 1 ${ignore(i)} )*
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:25:13
|
||||
--> $DIR/required-feature.rs:37:13
|
||||
|
|
||||
LL | $( ${ignore(e)} ${length()} )*
|
||||
| ^^^^^^^^^^^
|
||||
@ -44,7 +80,7 @@ LL | $( ${ignore(e)} ${length()} )*
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: meta-variable expressions are unstable
|
||||
--> $DIR/required-features.rs:25:26
|
||||
--> $DIR/required-feature.rs:37:26
|
||||
|
|
||||
LL | $( ${ignore(e)} ${length()} )*
|
||||
| ^^^^^^^^^^
|
||||
@ -52,6 +88,6 @@ LL | $( ${ignore(e)} ${length()} )*
|
||||
= note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
|
||||
= help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,9 @@
|
||||
fn main() {
|
||||
let _: std::num::NonZeroU64 = 1;
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP consider calling `NonZeroU64::new`
|
||||
|
||||
let _: Option<std::num::NonZeroU64> = 1;
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP consider calling `NonZeroU64::new`
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/non_zero_assigned_something.rs:2:35
|
||||
|
|
||||
LL | let _: std::num::NonZeroU64 = 1;
|
||||
| -------------------- ^ expected struct `NonZeroU64`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: consider calling `NonZeroU64::new`
|
||||
|
|
||||
LL | let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap();
|
||||
| ++++++++++++++++ ++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/non_zero_assigned_something.rs:6:43
|
||||
|
|
||||
LL | let _: Option<std::num::NonZeroU64> = 1;
|
||||
| ---------------------------- ^ expected enum `Option`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected enum `Option<NonZeroU64>`
|
||||
found type `{integer}`
|
||||
help: consider calling `NonZeroU64::new`
|
||||
|
|
||||
LL | let _: Option<std::num::NonZeroU64> = NonZeroU64::new(1);
|
||||
| ++++++++++++++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
24
src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
Normal file
24
src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
Normal file
@ -0,0 +1,24 @@
|
||||
mod inner {
|
||||
pub struct Wrapper<T>(T);
|
||||
}
|
||||
|
||||
fn needs_wrapper(t: inner::Wrapper<i32>) {}
|
||||
fn needs_wrapping(t: std::num::Wrapping<i32>) {}
|
||||
fn needs_ready(t: std::future::Ready<i32>) {}
|
||||
|
||||
fn main() {
|
||||
// Suggest wrapping expression because type is local
|
||||
// and its privacy can be easily changed
|
||||
needs_wrapper(0);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping the expression in `inner::Wrapper`
|
||||
|
||||
// Suggest wrapping expression because field is accessible
|
||||
needs_wrapping(0);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP try wrapping the expression in `std::num::Wrapping`
|
||||
|
||||
// Do not suggest wrapping expression
|
||||
needs_ready(Some(0));
|
||||
//~^ ERROR mismatched types
|
||||
}
|
59
src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
Normal file
59
src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
Normal file
@ -0,0 +1,59 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/wrap-suggestion-privacy.rs:12:19
|
||||
|
|
||||
LL | needs_wrapper(0);
|
||||
| ------------- ^ expected struct `Wrapper`, found integer
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `Wrapper<i32>`
|
||||
found type `{integer}`
|
||||
note: function defined here
|
||||
--> $DIR/wrap-suggestion-privacy.rs:5:4
|
||||
|
|
||||
LL | fn needs_wrapper(t: inner::Wrapper<i32>) {}
|
||||
| ^^^^^^^^^^^^^ ----------------------
|
||||
help: try wrapping the expression in `inner::Wrapper` (its field is private, but it's local to this crate and its privacy can be changed)
|
||||
|
|
||||
LL | needs_wrapper(inner::Wrapper(0));
|
||||
| +++++++++++++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/wrap-suggestion-privacy.rs:17:20
|
||||
|
|
||||
LL | needs_wrapping(0);
|
||||
| -------------- ^ expected struct `Wrapping`, found integer
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `Wrapping<i32>`
|
||||
found type `{integer}`
|
||||
note: function defined here
|
||||
--> $DIR/wrap-suggestion-privacy.rs:6:4
|
||||
|
|
||||
LL | fn needs_wrapping(t: std::num::Wrapping<i32>) {}
|
||||
| ^^^^^^^^^^^^^^ --------------------------
|
||||
help: try wrapping the expression in `std::num::Wrapping`
|
||||
|
|
||||
LL | needs_wrapping(std::num::Wrapping(0));
|
||||
| +++++++++++++++++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/wrap-suggestion-privacy.rs:22:17
|
||||
|
|
||||
LL | needs_ready(Some(0));
|
||||
| ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `std::future::Ready<i32>`
|
||||
found enum `Option<{integer}>`
|
||||
note: function defined here
|
||||
--> $DIR/wrap-suggestion-privacy.rs:7:4
|
||||
|
|
||||
LL | fn needs_ready(t: std::future::Ready<i32>) {}
|
||||
| ^^^^^^^^^^^ --------------------------
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -23,7 +23,13 @@ LL | pub fn foo() {}
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0432, E0603.
|
||||
For more information about an error, try `rustc --explain E0432`.
|
||||
|
@ -6,6 +6,12 @@ LL | use bar::gpriv;
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: requires `sized` lang_item
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0432`.
|
||||
|
@ -22,7 +22,7 @@ fn new() -> Foo {
|
||||
|
||||
pub fn foo() {
|
||||
let _f: base::Foo = base::HasNew::new();
|
||||
//~^ ERROR type annotations needed
|
||||
//~^ ERROR E0790
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,11 +1,17 @@
|
||||
error[E0283]: type annotations needed
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/static-method-generic-inference.rs:24:25
|
||||
|
|
||||
LL | fn new() -> T;
|
||||
| -------------- `HasNew::new` defined here
|
||||
...
|
||||
LL | let _f: base::Foo = base::HasNew::new();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
= note: cannot satisfy `_: HasNew<Foo>`
|
||||
help: use the fully-qualified path to the only available implementation
|
||||
|
|
||||
LL | let _f: base::Foo = base::<::base::Foo as HasNew>::new();
|
||||
| +++++++++++++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0790`.
|
||||
|
@ -7,5 +7,14 @@ LL | pub fn drop<T>(_x: T) {}
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
||||
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
||||
|
||||
error: aborting due to previous error
|
||||
error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
||||
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
21
src/test/ui/union/issue-99375.rs
Normal file
21
src/test/ui/union/issue-99375.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// check-pass
|
||||
|
||||
union URes<R: Copy> {
|
||||
uninit: (),
|
||||
init: R,
|
||||
}
|
||||
|
||||
struct Params<F, R: Copy> {
|
||||
function: F,
|
||||
result: URes<R>,
|
||||
}
|
||||
|
||||
unsafe extern "C" fn do_call<F, R>(params: *mut Params<F, R>)
|
||||
where
|
||||
R: Copy,
|
||||
F: Fn() -> R,
|
||||
{
|
||||
(*params).result.init = ((*params).function)();
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1 +1 @@
|
||||
Subproject commit 5342f47f4276641ddb5f0a5e08fb307742d6cdc4
|
||||
Subproject commit 897a7ec4b826f85ec1626870e734490701138097
|
Loading…
Reference in New Issue
Block a user