about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/method/suggest.rs210
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--library/core/src/cell.rs1
-rw-r--r--library/std/src/sync/rwlock.rs1
-rw-r--r--library/std/src/thread/local.rs1
-rw-r--r--src/test/ui/suggestions/inner_type.fixed40
-rw-r--r--src/test/ui/suggestions/inner_type.rs40
-rw-r--r--src/test/ui/suggestions/inner_type.stderr83
-rw-r--r--src/test/ui/suggestions/inner_type2.rs26
-rw-r--r--src/test/ui/suggestions/inner_type2.stderr29
10 files changed, 373 insertions, 61 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs
index 0e77ed0a4fe..0e82e4956c7 100644
--- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs
+++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs
@@ -2,6 +2,7 @@
 //! found or is otherwise invalid.
 
 use crate::check::FnCtxt;
+use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{
 use std::cmp::Ordering;
 use std::iter;
 
-use super::probe::{IsSuggestion, Mode, ProbeScope};
+use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
 
 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_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.dedup();
@@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn check_for_unwrap_self(
+    fn check_for_inner_self(
         &self,
         err: &mut Diagnostic,
         source: SelfSource<'tcx>,
@@ -1408,81 +1409,168 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
 
         let ty::Adt(kind, substs) = actual.kind() else { return; };
-        if !kind.is_enum() {
-            return;
-        }
+        match kind.adt_kind() {
+            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);
+
+                        // Skip `_`, since that'll just lead to ambiguity.
+                        if self.resolve_vars_if_possible(field_ty).is_ty_var() {
+                            return None;
+                        }
 
-        let matching_variants: Vec<_> = kind
-            .variants()
-            .iter()
-            .flat_map(|variant| {
-                let [field] = &variant.fields[..] else { return None; };
-                let field_ty = field.ty(tcx, substs);
+                        self.lookup_probe(
+                            span,
+                            item_name,
+                            field_ty,
+                            call_expr,
+                            ProbeScope::TraitsInScope,
+                        )
+                        .ok()
+                        .map(|pick| (variant, field, pick))
+                    })
+                    .collect();
+
+                let ret_ty_matches = |diagnostic_item| {
+                    if let Some(ret_ty) = self
+                        .ret_coercion
+                        .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
+                    }
+                };
 
-                // Skip `_`, since that'll just lead to ambiguity.
-                if self.resolve_vars_if_possible(field_ty).is_ty_var() {
-                    return None;
+                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
+                    _ => {}
                 }
-
-                self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
-                    .ok()
-                    .map(|pick| (variant, field, pick))
-            })
-            .collect();
-
-        let ret_ty_matches = |diagnostic_item| {
-            if let Some(ret_ty) = self
-                .ret_coercion
-                .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
             }
-        };
+            // 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::TraitsInScope,
+                        )  else { return; };
 
-        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 {
-                        return;
+                let name = self.ty_to_value_string(actual);
+                let inner_id = kind.did();
+                let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
+                    pick.autoref_or_ptr_adjustment
+                {
+                    Some(mutbl)
+                } else {
+                    None
+                };
+
+                if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
+                    err.help("use `with` or `try_with` to access thread local storage");
+                } 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) {
+                    let (suggestion, borrow_kind, panic_if) = match mutable {
+                        Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
+                        Some(Mutability::Mut) => {
+                            (".borrow_mut()", "mutably borrow", "any borrows exist")
+                        }
+                        None => 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"
+                            "use `{suggestion}` to {borrow_kind} the `{ty}`, \
+                            panicking if {panic_if}"
                         ),
-                        "?",
-                        Applicability::MachineApplicable,
+                        suggestion,
+                        Applicability::MaybeIncorrect,
                     );
-                } else {
+                } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
                     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}`"
+                            "use `.lock().unwrap()` to borrow the `{ty}`, \
+                            blocking the current thread until it can be acquired"
                         ),
-                        ".expect(\"REASON\")",
-                        Applicability::HasPlaceholders,
+                        ".lock().unwrap()",
+                        Applicability::MaybeIncorrect,
                     );
-                }
+                } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
+                    let (suggestion, borrow_kind) = match mutable {
+                        Some(Mutability::Not) => (".read().unwrap()", "borrow"),
+                        Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
+                        None => return,
+                    };
+                    err.span_suggestion_verbose(
+                        expr.span.shrink_to_hi(),
+                        format!(
+                            "use `{suggestion}` to {borrow_kind} the `{ty}`, \
+                            blocking the current thread until it can be acquired"
+                        ),
+                        suggestion,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    return;
+                };
+
+                err.span_note(
+                    tcx.def_span(pick.item.def_id),
+                    &format!("the method `{item_name}` exists on the type `{ty}`"),
+                );
             }
-            // FIXME(compiler-errors): Support suggestions for other matching enum variants
-            _ => {}
         }
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 502ef67fc67..67ffc573b99 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -224,6 +224,7 @@ symbols! {
         Left,
         LinkedList,
         LintPass,
+        LocalKey,
         Mutex,
         MutexGuard,
         N,
@@ -266,6 +267,7 @@ symbols! {
         Rc,
         Ready,
         Receiver,
+        RefCell,
         Relaxed,
         Release,
         Result,
@@ -274,6 +276,7 @@ symbols! {
         Rust,
         RustcDecodable,
         RustcEncodable,
+        RwLock,
         RwLockReadGuard,
         RwLockWriteGuard,
         Send,
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 1abbb39497a..288cab1ef39 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -614,6 +614,7 @@ impl<T, const N: usize> Cell<[T; N]> {
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](self) for more.
+#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RefCell<T: ?Sized> {
     borrow: Cell<BorrowFlag>,
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 9ab781561e9..ee2c79b6669 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -76,6 +76,7 @@ use crate::sys_common::rwlock as sys;
 ///
 /// [`Mutex`]: super::Mutex
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")]
 pub struct RwLock<T: ?Sized> {
     inner: sys::MovableRwLock,
     poison: poison::Flag,
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 8aedfc4a6b8..ffd17dc9909 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -95,6 +95,7 @@ use crate::fmt;
 /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
 /// [`JoinHandle::join`]: crate::thread::JoinHandle::join
 /// [`with`]: LocalKey::with
+#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LocalKey<T: 'static> {
     // This outer `LocalKey<T>` type is what's going to be stored in statics,
diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed
new file mode 100644
index 00000000000..7af7391ca85
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.fixed
@@ -0,0 +1,40 @@
+// 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 a mutable borrow exists
+
+    other_item.borrow_mut().some_mutable_method();
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any 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().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+    let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+    another_item.read().unwrap().method();
+    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+    another_item.write().unwrap().some_mutable_method();
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs
new file mode 100644
index 00000000000..4aca5071625
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.rs
@@ -0,0 +1,40 @@
+// 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 a mutable borrow exists
+
+    other_item.some_mutable_method();
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any 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().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+    let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+    another_item.method();
+    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+    another_item.some_mutable_method();
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr
new file mode 100644
index 00000000000..5ac3d04f104
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.stderr
@@ -0,0 +1,83 @@
+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 a mutable borrow exists
+   |
+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 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().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+   |
+LL |     another_item.lock().unwrap().method();
+   |                 ++++++++++++++++
+
+error[E0599]: no method named `method` found for struct `RwLock` in the current scope
+  --> $DIR/inner_type.rs:33:18
+   |
+LL |     another_item.method();
+   |                  ^^^^^^ method not found in `RwLock<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 `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+   |
+LL |     another_item.read().unwrap().method();
+   |                 ++++++++++++++++
+
+error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope
+  --> $DIR/inner_type.rs:37:18
+   |
+LL |     another_item.some_mutable_method();
+   |                  ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock<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 `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+   |
+LL |     another_item.write().unwrap().some_mutable_method();
+   |                 +++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs
new file mode 100644
index 00000000000..c56ea7c030d
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type2.rs
@@ -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 thread local storage
+
+    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
+}
diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr
new file mode 100644
index 00000000000..eddfd9d6340
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type2.stderr
@@ -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 thread local storage
+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`.