Wrapper suggestions
This commit is contained in:
parent
57ee5cf5a9
commit
c4c9415132
9 changed files with 316 additions and 67 deletions
|
@ -2,6 +2,7 @@
|
||||||
//! found or is otherwise invalid.
|
//! found or is otherwise invalid.
|
||||||
|
|
||||||
use crate::check::FnCtxt;
|
use crate::check::FnCtxt;
|
||||||
|
use rustc_ast::ast::Mutability;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||||
|
@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use super::probe::{IsSuggestion, Mode, ProbeScope};
|
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
|
||||||
use super::{CandidateSource, MethodError, NoMatchData};
|
use super::{CandidateSource, MethodError, NoMatchData};
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
@ -983,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.check_for_field_method(&mut err, source, span, actual, item_name);
|
self.check_for_field_method(&mut err, source, span, actual, item_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
|
self.check_for_inner_self(&mut err, source, span, actual, item_name);
|
||||||
|
|
||||||
bound_spans.sort();
|
bound_spans.sort();
|
||||||
bound_spans.dedup();
|
bound_spans.dedup();
|
||||||
|
@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_unwrap_self(
|
fn check_for_inner_self(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
source: SelfSource<'tcx>,
|
source: SelfSource<'tcx>,
|
||||||
|
@ -1408,81 +1409,159 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
|
let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
|
||||||
|
|
||||||
let ty::Adt(kind, substs) = actual.kind() else { return; };
|
let ty::Adt(kind, substs) = actual.kind() else { return; };
|
||||||
if !kind.is_enum() {
|
match kind.adt_kind() {
|
||||||
return;
|
ty::AdtKind::Enum => {
|
||||||
}
|
let matching_variants: Vec<_> = kind
|
||||||
|
.variants()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|variant| {
|
||||||
|
let [field] = &variant.fields[..] else { return None; };
|
||||||
|
let field_ty = field.ty(tcx, substs);
|
||||||
|
|
||||||
let matching_variants: Vec<_> = kind
|
// Skip `_`, since that'll just lead to ambiguity.
|
||||||
.variants()
|
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
|
||||||
.iter()
|
return None;
|
||||||
.flat_map(|variant| {
|
}
|
||||||
let [field] = &variant.fields[..] else { return None; };
|
|
||||||
let field_ty = field.ty(tcx, substs);
|
|
||||||
|
|
||||||
// Skip `_`, since that'll just lead to ambiguity.
|
self.lookup_probe(
|
||||||
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
|
span,
|
||||||
return None;
|
item_name,
|
||||||
}
|
field_ty,
|
||||||
|
call_expr,
|
||||||
|
ProbeScope::AllTraits,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.map(|pick| (variant, field, pick))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
|
let ret_ty_matches = |diagnostic_item| {
|
||||||
.ok()
|
if let Some(ret_ty) = self
|
||||||
.map(|pick| (variant, field, pick))
|
.ret_coercion
|
||||||
})
|
.as_ref()
|
||||||
.collect();
|
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
|
||||||
|
&& let ty::Adt(kind, _) = ret_ty.kind()
|
||||||
let ret_ty_matches = |diagnostic_item| {
|
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
|
||||||
if let Some(ret_ty) = self
|
{
|
||||||
.ret_coercion
|
true
|
||||||
.as_ref()
|
|
||||||
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
|
|
||||||
&& let ty::Adt(kind, _) = ret_ty.kind()
|
|
||||||
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
|
|
||||||
{
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match &matching_variants[..] {
|
|
||||||
[(_, field, pick)] => {
|
|
||||||
let self_ty = field.ty(tcx, substs);
|
|
||||||
err.span_note(
|
|
||||||
tcx.def_span(pick.item.def_id),
|
|
||||||
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
|
|
||||||
);
|
|
||||||
let (article, kind, variant, question) =
|
|
||||||
if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
|
|
||||||
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
|
||||||
} else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
|
|
||||||
("an", "Option", "None", ret_ty_matches(sym::Option))
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
false
|
||||||
};
|
}
|
||||||
if question {
|
};
|
||||||
|
|
||||||
|
match &matching_variants[..] {
|
||||||
|
[(_, field, pick)] => {
|
||||||
|
let self_ty = field.ty(tcx, substs);
|
||||||
|
err.span_note(
|
||||||
|
tcx.def_span(pick.item.def_id),
|
||||||
|
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
|
||||||
|
);
|
||||||
|
let (article, kind, variant, question) =
|
||||||
|
if tcx.is_diagnostic_item(sym::Result, kind.did()) {
|
||||||
|
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
||||||
|
} else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
|
||||||
|
("an", "Option", "None", ret_ty_matches(sym::Option))
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if question {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
expr.span.shrink_to_hi(),
|
||||||
|
format!(
|
||||||
|
"use the `?` operator to extract the `{self_ty}` value, propagating \
|
||||||
|
{article} `{kind}::{variant}` value to the caller"
|
||||||
|
),
|
||||||
|
"?",
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
expr.span.shrink_to_hi(),
|
||||||
|
format!(
|
||||||
|
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
|
||||||
|
panicking if the value is {article} `{kind}::{variant}`"
|
||||||
|
),
|
||||||
|
".expect(\"REASON\")",
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME(compiler-errors): Support suggestions for other matching enum variants
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Target wrapper types - types that wrap or pretend to wrap another type,
|
||||||
|
// perhaps this inner type is meant to be called?
|
||||||
|
ty::AdtKind::Struct | ty::AdtKind::Union => {
|
||||||
|
let [first] = ***substs else { return; };
|
||||||
|
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
|
||||||
|
let Ok(pick) = self.lookup_probe(
|
||||||
|
span,
|
||||||
|
item_name,
|
||||||
|
ty,
|
||||||
|
call_expr,
|
||||||
|
ProbeScope::AllTraits,
|
||||||
|
) else { return; };
|
||||||
|
|
||||||
|
let name = self.ty_to_value_string(actual);
|
||||||
|
let inner_id = kind.did();
|
||||||
|
|
||||||
|
if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
|
||||||
|
err.help("use `with` or `try_with` to access the contents of threadlocals");
|
||||||
|
} else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
|
||||||
|
err.help(format!(
|
||||||
|
"if this `{name}` has been initialized, \
|
||||||
|
use one of the `assume_init` methods to access the inner value"
|
||||||
|
));
|
||||||
|
} else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
|
||||||
|
match pick.autoref_or_ptr_adjustment {
|
||||||
|
Some(AutorefOrPtrAdjustment::Autoref {
|
||||||
|
mutbl: Mutability::Not, ..
|
||||||
|
}) => {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
expr.span.shrink_to_hi(),
|
||||||
|
format!(
|
||||||
|
"use `.borrow()` to borrow the {ty}, \
|
||||||
|
panicking if any outstanding mutable borrows exist."
|
||||||
|
),
|
||||||
|
".borrow()",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Some(AutorefOrPtrAdjustment::Autoref {
|
||||||
|
mutbl: Mutability::Mut, ..
|
||||||
|
}) => {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
expr.span.shrink_to_hi(),
|
||||||
|
format!(
|
||||||
|
"use `.borrow_mut()` to mutably borrow the {ty}, \
|
||||||
|
panicking if any outstanding borrows exist."
|
||||||
|
),
|
||||||
|
".borrow_mut()",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
} else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_hi(),
|
expr.span.shrink_to_hi(),
|
||||||
format!(
|
format!(
|
||||||
"use the `?` operator to extract the `{self_ty}` value, propagating \
|
"use `.lock()` to borrow the {ty}, \
|
||||||
{article} `{kind}::{variant}` value to the caller"
|
blocking the current thread until it can be acquired"
|
||||||
),
|
),
|
||||||
"?",
|
".lock().unwrap()",
|
||||||
Applicability::MachineApplicable,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
err.span_suggestion_verbose(
|
return;
|
||||||
expr.span.shrink_to_hi(),
|
};
|
||||||
format!(
|
|
||||||
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
|
err.span_note(
|
||||||
panicking if the value is {article} `{kind}::{variant}`"
|
tcx.def_span(pick.item.def_id),
|
||||||
),
|
&format!("the method `{item_name}` exists on the type `{ty}`"),
|
||||||
".expect(\"REASON\")",
|
);
|
||||||
Applicability::HasPlaceholders,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// FIXME(compiler-errors): Support suggestions for other matching enum variants
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,7 @@ symbols! {
|
||||||
Left,
|
Left,
|
||||||
LinkedList,
|
LinkedList,
|
||||||
LintPass,
|
LintPass,
|
||||||
|
LocalKey,
|
||||||
Mutex,
|
Mutex,
|
||||||
MutexGuard,
|
MutexGuard,
|
||||||
N,
|
N,
|
||||||
|
@ -266,6 +267,7 @@ symbols! {
|
||||||
Rc,
|
Rc,
|
||||||
Ready,
|
Ready,
|
||||||
Receiver,
|
Receiver,
|
||||||
|
RefCell,
|
||||||
Relaxed,
|
Relaxed,
|
||||||
Release,
|
Release,
|
||||||
Result,
|
Result,
|
||||||
|
|
|
@ -614,6 +614,7 @@ impl<T, const N: usize> Cell<[T; N]> {
|
||||||
/// A mutable memory location with dynamically checked borrow rules
|
/// A mutable memory location with dynamically checked borrow rules
|
||||||
///
|
///
|
||||||
/// See the [module-level documentation](self) for more.
|
/// See the [module-level documentation](self) for more.
|
||||||
|
#[rustc_diagnostic_item = "RefCell"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct RefCell<T: ?Sized> {
|
pub struct RefCell<T: ?Sized> {
|
||||||
borrow: Cell<BorrowFlag>,
|
borrow: Cell<BorrowFlag>,
|
||||||
|
|
|
@ -95,6 +95,7 @@ use crate::fmt;
|
||||||
/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
|
/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
|
||||||
/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
|
/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
|
||||||
/// [`with`]: LocalKey::with
|
/// [`with`]: LocalKey::with
|
||||||
|
#[rustc_diagnostic_item = "LocalKey"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct LocalKey<T: 'static> {
|
pub struct LocalKey<T: 'static> {
|
||||||
// This outer `LocalKey<T>` type is what's going to be stored in statics,
|
// This outer `LocalKey<T>` type is what's going to be stored in statics,
|
||||||
|
|
30
src/test/ui/suggestions/inner_type.fixed
Normal file
30
src/test/ui/suggestions/inner_type.fixed
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// compile-flags: --edition=2021
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
pub struct Struct<T> {
|
||||||
|
pub p: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Struct<T> {
|
||||||
|
pub fn method(&self) {}
|
||||||
|
|
||||||
|
pub fn some_mutable_method(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
|
||||||
|
|
||||||
|
other_item.borrow().method();
|
||||||
|
//~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
|
||||||
|
//~| HELP use `.borrow()` to borrow the Struct<u32>, panicking if any outstanding mutable borrows exist.
|
||||||
|
|
||||||
|
other_item.borrow_mut().some_mutable_method();
|
||||||
|
//~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
|
||||||
|
//~| HELP use `.borrow_mut()` to mutably borrow the Struct<u32>, panicking if any outstanding borrows exist.
|
||||||
|
|
||||||
|
let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
|
||||||
|
|
||||||
|
another_item.lock().unwrap().method();
|
||||||
|
//~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
|
||||||
|
//~| HELP use `.lock()` to borrow the Struct<u32>, blocking the current thread until it can be acquired
|
||||||
|
}
|
30
src/test/ui/suggestions/inner_type.rs
Normal file
30
src/test/ui/suggestions/inner_type.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// compile-flags: --edition=2021
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
pub struct Struct<T> {
|
||||||
|
pub p: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Struct<T> {
|
||||||
|
pub fn method(&self) {}
|
||||||
|
|
||||||
|
pub fn some_mutable_method(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
|
||||||
|
|
||||||
|
other_item.method();
|
||||||
|
//~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
|
||||||
|
//~| HELP use `.borrow()` to borrow the Struct<u32>, panicking if any outstanding mutable borrows exist.
|
||||||
|
|
||||||
|
other_item.some_mutable_method();
|
||||||
|
//~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
|
||||||
|
//~| HELP use `.borrow_mut()` to mutably borrow the Struct<u32>, panicking if any outstanding borrows exist.
|
||||||
|
|
||||||
|
let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
|
||||||
|
|
||||||
|
another_item.method();
|
||||||
|
//~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
|
||||||
|
//~| HELP use `.lock()` to borrow the Struct<u32>, blocking the current thread until it can be acquired
|
||||||
|
}
|
51
src/test/ui/suggestions/inner_type.stderr
Normal file
51
src/test/ui/suggestions/inner_type.stderr
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
error[E0599]: no method named `method` found for struct `RefCell` in the current scope
|
||||||
|
--> $DIR/inner_type.rs:17:16
|
||||||
|
|
|
||||||
|
LL | other_item.method();
|
||||||
|
| ^^^^^^ method not found in `RefCell<Struct<u32>>`
|
||||||
|
|
|
||||||
|
note: the method `method` exists on the type `Struct<u32>`
|
||||||
|
--> $DIR/inner_type.rs:9:5
|
||||||
|
|
|
||||||
|
LL | pub fn method(&self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: use `.borrow()` to borrow the Struct<u32>, panicking if any outstanding mutable borrows exist.
|
||||||
|
|
|
||||||
|
LL | other_item.borrow().method();
|
||||||
|
| +++++++++
|
||||||
|
|
||||||
|
error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope
|
||||||
|
--> $DIR/inner_type.rs:21:16
|
||||||
|
|
|
||||||
|
LL | other_item.some_mutable_method();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell<Struct<u32>>`
|
||||||
|
|
|
||||||
|
note: the method `some_mutable_method` exists on the type `Struct<u32>`
|
||||||
|
--> $DIR/inner_type.rs:11:5
|
||||||
|
|
|
||||||
|
LL | pub fn some_mutable_method(&mut self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: use `.borrow_mut()` to mutably borrow the Struct<u32>, panicking if any outstanding borrows exist.
|
||||||
|
|
|
||||||
|
LL | other_item.borrow_mut().some_mutable_method();
|
||||||
|
| +++++++++++++
|
||||||
|
|
||||||
|
error[E0599]: no method named `method` found for struct `Mutex` in the current scope
|
||||||
|
--> $DIR/inner_type.rs:27:18
|
||||||
|
|
|
||||||
|
LL | another_item.method();
|
||||||
|
| ^^^^^^ method not found in `Mutex<Struct<u32>>`
|
||||||
|
|
|
||||||
|
note: the method `method` exists on the type `Struct<u32>`
|
||||||
|
--> $DIR/inner_type.rs:9:5
|
||||||
|
|
|
||||||
|
LL | pub fn method(&self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: use `.lock()` to borrow the Struct<u32>, blocking the current thread until it can be acquired
|
||||||
|
|
|
||||||
|
LL | another_item.lock().unwrap().method();
|
||||||
|
| ++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
26
src/test/ui/suggestions/inner_type2.rs
Normal file
26
src/test/ui/suggestions/inner_type2.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
pub struct Struct<T> {
|
||||||
|
pub p: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Struct<T> {
|
||||||
|
pub fn method(&self) {}
|
||||||
|
|
||||||
|
pub fn some_mutable_method(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static STRUCT: Struct<u32> = Struct {
|
||||||
|
p: 42_u32
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
STRUCT.method();
|
||||||
|
//~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599]
|
||||||
|
//~| HELP use `with` or `try_with` to access the contents of threadlocals
|
||||||
|
|
||||||
|
let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
|
||||||
|
item.method();
|
||||||
|
//~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
|
||||||
|
//~| HELP if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
|
||||||
|
}
|
29
src/test/ui/suggestions/inner_type2.stderr
Normal file
29
src/test/ui/suggestions/inner_type2.stderr
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
error[E0599]: no method named `method` found for struct `LocalKey` in the current scope
|
||||||
|
--> $DIR/inner_type2.rs:18:12
|
||||||
|
|
|
||||||
|
LL | STRUCT.method();
|
||||||
|
| ^^^^^^ method not found in `LocalKey<Struct<u32>>`
|
||||||
|
|
|
||||||
|
= help: use `with` or `try_with` to access the contents of threadlocals
|
||||||
|
note: the method `method` exists on the type `Struct<u32>`
|
||||||
|
--> $DIR/inner_type2.rs:6:5
|
||||||
|
|
|
||||||
|
LL | pub fn method(&self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope
|
||||||
|
--> $DIR/inner_type2.rs:23:10
|
||||||
|
|
|
||||||
|
LL | item.method();
|
||||||
|
| ^^^^^^ method not found in `MaybeUninit<Struct<u32>>`
|
||||||
|
|
|
||||||
|
= help: if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
|
||||||
|
note: the method `method` exists on the type `Struct<u32>`
|
||||||
|
--> $DIR/inner_type2.rs:6:5
|
||||||
|
|
|
||||||
|
LL | pub fn method(&self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
Loading…
Add table
Add a link
Reference in a new issue