When suggesting writing a fully qualified path probe for appropriate types

Fix #46585.
This commit is contained in:
Esteban Küber 2023-01-08 06:54:52 +00:00
parent b22c152958
commit 12ddf77811
18 changed files with 295 additions and 55 deletions

View File

@ -24,6 +24,7 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
@ -1633,8 +1634,8 @@ trait here instead: `trait NewTrait: {} {{}}`",
fn report_ambiguous_associated_type(
&self,
span: Span,
type_str: &str,
trait_str: &str,
types: &[String],
traits: &[String],
name: Symbol,
) -> ErrorGuaranteed {
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
@ -1645,19 +1646,92 @@ fn report_ambiguous_associated_type(
.keys()
.any(|full_span| full_span.contains(span))
{
err.span_suggestion(
err.span_suggestion_verbose(
span.shrink_to_lo(),
"you are looking for the module in `std`, not the primitive type",
"std::",
Applicability::MachineApplicable,
);
} else {
err.span_suggestion(
span,
"use fully-qualified syntax",
format!("<{} as {}>::{}", type_str, trait_str, name),
Applicability::HasPlaceholders,
);
match (types, traits) {
([], []) => {
err.span_suggestion_verbose(
span,
&format!(
"if there were a type named `Type` that implements a trait named \
`Trait` with associated type `{name}`, you could use the \
fully-qualified path",
),
format!("<Type as Trait>::{name}"),
Applicability::HasPlaceholders,
);
}
([], [trait_str]) => {
err.span_suggestion_verbose(
span,
&format!(
"if there were a type named `Example` that implemented `{trait_str}`, \
you could use the fully-qualified path",
),
format!("<Example as {trait_str}>::{name}"),
Applicability::HasPlaceholders,
);
}
([], traits) => {
err.span_suggestions(
span,
&format!(
"if there were a type named `Example` that implemented one of the \
traits with associated type `{name}`, you could use the \
fully-qualified path",
),
traits
.iter()
.map(|trait_str| format!("<Example as {trait_str}>::{name}"))
.collect::<Vec<_>>(),
Applicability::HasPlaceholders,
);
}
([type_str], []) => {
err.span_suggestion_verbose(
span,
&format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for `{type_str}`, you could use the fully-qualified path",
),
format!("<{type_str} as Example>::{name}"),
Applicability::HasPlaceholders,
);
}
(types, []) => {
err.span_suggestions(
span,
&format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for one of the types, you could use the fully-qualified \
path",
),
types
.into_iter()
.map(|type_str| format!("<{type_str} as Example>::{name}")),
Applicability::HasPlaceholders,
);
}
(types, traits) => {
let mut suggestions = vec![];
for type_str in types {
for trait_str in traits {
suggestions.push(format!("<{type_str} as {trait_str}>::{name}"));
}
}
err.span_suggestions(
span,
"use the fully-qualified path",
suggestions,
Applicability::MachineApplicable,
);
}
}
}
err.emit()
}
@ -2040,12 +2114,67 @@ pub fn associated_path_to_ty(
err.emit()
} else if let Err(reported) = qself_ty.error_reported() {
reported
} else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() {
// `<impl Trait as OtherTrait>::Assoc` makes no sense.
struct_span_err!(
tcx.sess,
tcx.def_span(alias_ty.def_id),
E0667,
"`impl Trait` is not allowed in path parameters"
)
.emit() // Already reported in an earlier stage.
} else {
// Find all the `impl`s that `qself_ty` has for any trait that has the
// associated type, so that we suggest the right one.
let infcx = tcx.infer_ctxt().build();
// We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()`
// to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`.
let param_env = ty::ParamEnv::new(
ty::List::empty(),
traits::Reveal::All,
hir::Constness::NotConst,
);
let traits: Vec<_> = self
.tcx()
.all_traits()
.filter(|trait_def_id| {
// Consider only traits with the associated type
tcx.associated_items(*trait_def_id)
.in_definition_order()
.find(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
&& matches!(i.kind, ty::AssocKind::Type)
})
.is_some()
// Consider only accessible traits
&& tcx.visibility(*trait_def_id)
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.filter(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
trait_ref.map_or(false, |impl_| {
infcx
.can_eq(
param_env,
tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty),
)
.is_ok()
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
.next()
.is_some()
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
.collect();
// Don't print `TyErr` to the user.
self.report_ambiguous_associated_type(
span,
&qself_ty.to_string(),
"Trait",
&[qself_ty.to_string()],
&traits,
assoc_ident.name,
)
};
@ -2163,16 +2292,30 @@ fn qpath_to_ty(
let is_part_of_self_trait_constraints = def_id == trait_def_id;
let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
"Self"
let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
vec!["Self".to_string()]
} else {
"Type"
// Find all the types that have an `impl` for the trait.
tcx.all_impls(trait_def_id)
.filter(|impl_def_id| {
// Consider only accessible traits
tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx)
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
.map(|impl_| impl_.self_ty())
// We don't care about blanket impls.
.filter(|self_ty| !self_ty.has_non_region_infer())
.map(|self_ty| tcx.erase_regions(self_ty).to_string())
.collect()
};
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
// references the trait. Relevant for the first case in
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
let reported = self.report_ambiguous_associated_type(
span,
type_name,
&path_str,
&type_names,
&[path_str],
item_segment.ident.name,
);
return tcx.ty_error_with_guaranteed(reported)

View File

@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type
--> $DIR/associated-item-duplicate-names-3.rs:18:12
|
LL | let x: Baz::Bar = 5;
| ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar`
| ^^^^^^^^ help: use the fully-qualified path: `<Baz as Foo>::Bar`
error: aborting due to 2 previous errors

View File

@ -2,31 +2,46 @@ error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:6:36
|
LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
| ^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
|
LL | fn get<T:Get,U:Get>(x: T, y: U) -> <Example as Get>::Value {}
| ~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:20:17
|
LL | trait Foo where Foo::Assoc: Bar {
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc`
| ^^^^^^^^^^ help: use the fully-qualified path: `<Self as Foo>::Assoc`
error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:25:10
|
LL | type X = std::ops::Deref::Target;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Deref>::Target`
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path
|
LL | type X = <Example as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:11:23
|
LL | fn grab(&self) -> Grab::Value;
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
| ^^^^^^^^^^^ help: use the fully-qualified path: `<Self as Grab>::Value`
error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:14:22
|
LL | fn get(&self) -> Get::Value;
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
| ^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
|
LL | fn get(&self) -> <Example as Get>::Value;
| ~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors

View File

@ -61,25 +61,45 @@ error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:1:10
|
LL | type A = [u8; 4]::AssocTy;
| ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; 4] as Trait>::AssocTy`
| ^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path
|
LL | type A = <[u8; 4] as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:5:10
|
LL | type B = [u8]::AssocTy;
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8] as Trait>::AssocTy`
| ^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path
|
LL | type B = <[u8] as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:9:10
|
LL | type C = (u8)::AssocTy;
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
| ^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
LL | type C = <u8 as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:13:10
|
LL | type D = (u8, u8)::AssocTy;
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy`
| ^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path
|
LL | type D = <(u8, u8) as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
--> $DIR/bad-assoc-ty.rs:17:10
@ -91,13 +111,23 @@ error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:21:19
|
LL | type F = &'static (u8)::AssocTy;
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
| ^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
LL | type F = &'static <u8 as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:27:10
|
LL | type G = dyn 'static + (Send)::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Send + 'static) as Trait>::AssocTy`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path
|
LL | type G = <(dyn Send + 'static) as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bad-assoc-ty.rs:33:10
@ -117,24 +147,38 @@ error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:33:10
|
LL | type H = Fn(u8) -> (u8)::Output;
| ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as Trait>::Output`
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Output` implemented for `(dyn Fn(u8) -> u8 + 'static)`, you could use the fully-qualified path
|
LL | type H = <(dyn Fn(u8) -> u8 + 'static) as Example>::Output;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:39:19
|
LL | ($ty: ty) => ($ty::AssocTy);
| ^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
| ^^^^^^^^^^^^
...
LL | type J = ty!(u8);
| ------- in this macro invocation
|
= note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
LL | ($ty: ty) => (<u8 as Example>::AssocTy);
| ~~~~~~~~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:46:10
|
LL | type I = ty!()::AssocTy;
| ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
| ^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
LL | type I = <u8 as Example>::AssocTy;
| ~~~~~~~~~~~~~~~~~~~~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/bad-assoc-ty.rs:51:13

View File

@ -1,4 +1,8 @@
trait MyTrait { type X; }
struct MyStruct;
impl MyTrait for MyStruct {
type X = ();
}
fn main() {
let foo: MyTrait::X;

View File

@ -1,8 +1,8 @@
error[E0223]: ambiguous associated type
--> $DIR/E0223.rs:4:14
--> $DIR/E0223.rs:8:14
|
LL | let foo: MyTrait::X;
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as MyTrait>::X`
| ^^^^^^^^^^ help: use the fully-qualified path: `<MyStruct as MyTrait>::X`
error: aborting due to previous error

View File

@ -11,7 +11,7 @@ fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
//~^ ERROR `impl Trait` is not allowed in path parameters
//~^^ ERROR ambiguous associated type
//~| ERROR `impl Trait` is not allowed in path parameters
x.next().unwrap()
}

View File

@ -22,13 +22,12 @@ error[E0667]: `impl Trait` is not allowed in path parameters
LL | -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
| ^^^^^^^^^^
error[E0223]: ambiguous associated type
--> $DIR/impl_trait_projections.rs:12:50
error[E0667]: `impl Trait` is not allowed in path parameters
--> $DIR/impl_trait_projections.rs:12:51
|
LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
| ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<impl Iterator as Trait>::Item`
| ^^^^^^^^^^^^^
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0223, E0667.
For more information about an error, try `rustc --explain E0223`.
For more information about this error, try `rustc --explain E0667`.

View File

@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
--> $DIR/issue-23073.rs:6:17
|
LL | type FooT = <<Self as Bar>::Foo>::T;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<Self as Bar>::Foo as Trait>::T`
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `T` implemented for `<Self as Bar>::Foo`, you could use the fully-qualified path
|
LL | type FooT = <<Self as Bar>::Foo as Example>::T;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
--> $DIR/issue-78622.rs:5:5
|
LL | S::A::<f> {}
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
| ^^^^
|
help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path
|
LL | <S as Example>::A::<f> {}
| ~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type
--> $DIR/bare-trait-objects-path.rs:23:12
|
LL | let _: Dyn::Ty;
| ^^^^^^^ help: use fully-qualified syntax: `<dyn Dyn as Trait>::Ty`
| ^^^^^^^ help: use the fully-qualified path: `<dyn Dyn as Assoc>::Ty`
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:14:5

View File

@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
--> $DIR/qualified-path-params-2.rs:18:10
|
LL | type A = <S as Tr>::A::f<u8>;
| ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<S as Tr>::A as Trait>::f`
| ^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `f` implemented for `<S as Tr>::A`, you could use the fully-qualified path
|
LL | type A = <<S as Tr>::A as Example>::f;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
--> $DIR/issue-103202.rs:4:17
|
LL | fn f(self: &S::x) {}
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::x`
| ^^^^
|
help: if there were a trait named `Example` with associated type `x` implemented for `S`, you could use the fully-qualified path
|
LL | fn f(self: &<S as Example>::x) {}
| ~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type
--> $DIR/self-impl.rs:23:16
|
LL | let _: <Self>::Baz = true;
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
| ^^^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
error[E0223]: ambiguous associated type
--> $DIR/self-impl.rs:25:16
|
LL | let _: Self::Baz = true;
| ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
| ^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
error: aborting due to 2 previous errors

View File

@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type
--> $DIR/struct-path-associated-type.rs:32:13
|
LL | let s = S::A {};
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
| ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
error[E0223]: ambiguous associated type
--> $DIR/struct-path-associated-type.rs:33:13
|
LL | let z = S::A::<u8> {};
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
| ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
error[E0223]: ambiguous associated type
--> $DIR/struct-path-associated-type.rs:35:9
|
LL | S::A {} => {}
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
| ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
error: aborting due to 8 previous errors

View File

@ -21,7 +21,12 @@ error[E0223]: ambiguous associated type
--> $DIR/let-binding-init-expr-as-ty.rs:2:14
|
LL | let foo: i32::from_be(num);
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<i32 as Trait>::from_be`
| ^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path
|
LL | let foo: <i32 as Example>::from_be;
| ~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 3 previous errors

View File

@ -148,19 +148,24 @@ error[E0223]: ambiguous associated type
--> $DIR/item-privacy.rs:115:12
|
LL | let _: S::A;
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
| ^^^^
|
help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path
|
LL | let _: <S as Example>::A;
| ~~~~~~~~~~~~~~~~~
error[E0223]: ambiguous associated type
--> $DIR/item-privacy.rs:116:12
|
LL | let _: S::B;
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::B`
| ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B`
error[E0223]: ambiguous associated type
--> $DIR/item-privacy.rs:117:12
|
LL | let _: S::C;
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
| ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C`
error[E0624]: associated type `A` is private
--> $DIR/item-privacy.rs:119:12

View File

@ -205,7 +205,12 @@ error[E0223]: ambiguous associated type
--> $DIR/ufcs-partially-resolved.rs:36:12
|
LL | let _: <u8 as Tr>::Y::NN;
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
| ^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `NN` implemented for `<u8 as Tr>::Y`, you could use the fully-qualified path
|
LL | let _: <<u8 as Tr>::Y as Example>::NN;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0599]: no associated item named `NN` found for type `u16` in the current scope
--> $DIR/ufcs-partially-resolved.rs:38:20