diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2025-06-01 19:35:41 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-01 19:35:41 +0200 |
| commit | cd0adc9d7b2a2c7a41df53d6a384a42fbe2fce21 (patch) | |
| tree | f8e92415689f450bc2c424f4762d92fac102c267 | |
| parent | 9b0268a43b0a5b58f50c96ded25364037c019a61 (diff) | |
| parent | 8f765fc7a15b6a2f1de93251b9f65c6156fbfe33 (diff) | |
| download | rust-cd0adc9d7b2a2c7a41df53d6a384a42fbe2fce21.tar.gz rust-cd0adc9d7b2a2c7a41df53d6a384a42fbe2fce21.zip | |
Rollup merge of #140370 - WaffleLapkin:unqualified, r=jdonszelmann
Improve diagnostics for usage of qualified paths within tuple struct exprs/pats For patterns the old diagnostic was just incorrect, but I also added machine applicable suggestions. For context, this special cases errors for `<T as Trait>::Assoc(..)` patterns and expressions (latter is just a call). Tuple struct patterns and expressions both live in the value namespace, so they are not forwarded through associated *types*. r? ``@jdonszelmann`` cc ``@petrochenkov`` in https://github.com/rust-lang/rust/pull/80080#issuecomment-800630582 you were wondering why it doesn't work for types, that's why — tuple patterns are resolved in the value namespace.
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 124 | ||||
| -rw-r--r-- | tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr | 4 | ||||
| -rw-r--r-- | tests/ui/associated-types/associated-type-tuple-struct-construction.rs | 24 | ||||
| -rw-r--r-- | tests/ui/associated-types/associated-type-tuple-struct-construction.stderr | 19 | ||||
| -rw-r--r-- | tests/ui/associated-types/tuple-struct-expr-pat.fixed | 48 | ||||
| -rw-r--r-- | tests/ui/associated-types/tuple-struct-expr-pat.rs | 48 | ||||
| -rw-r--r-- | tests/ui/associated-types/tuple-struct-expr-pat.stderr | 97 | ||||
| -rw-r--r-- | tests/ui/delegation/bad-resolve.stderr | 4 | ||||
| -rw-r--r-- | tests/ui/delegation/glob-non-fn.stderr | 4 | ||||
| -rw-r--r-- | tests/ui/namespace/namespace-mix.stderr | 4 | ||||
| -rw-r--r-- | tests/ui/resolve/tuple-struct-alias.stderr | 15 | ||||
| -rw-r--r-- | tests/ui/ufcs/ufcs-partially-resolved.stderr | 2 |
13 files changed, 327 insertions, 97 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fb1534d0b27..744e99c86e1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -415,7 +415,7 @@ pub(crate) enum AliasPossibility { } #[derive(Copy, Clone, Debug)] -pub(crate) enum PathSource<'a> { +pub(crate) enum PathSource<'a, 'c> { /// Type paths `Path`. Type, /// Trait paths in bounds or impls. @@ -429,7 +429,10 @@ pub(crate) enum PathSource<'a> { /// Paths in tuple struct patterns `Path(..)`. TupleStruct(Span, &'a [Span]), /// `m::A::B` in `<T as m::A>::B::C`. - TraitItem(Namespace), + /// + /// Second field holds the "cause" of this one, i.e. the context within + /// which the trait item is resolved. Used for diagnostics. + TraitItem(Namespace, &'c PathSource<'a, 'c>), /// Paths in delegation item Delegation, /// An arg in a `use<'a, N>` precise-capturing bound. @@ -440,7 +443,7 @@ pub(crate) enum PathSource<'a> { DefineOpaques, } -impl<'a> PathSource<'a> { +impl<'a> PathSource<'a, '_> { fn namespace(self) -> Namespace { match self { PathSource::Type @@ -452,7 +455,7 @@ impl<'a> PathSource<'a> { | PathSource::TupleStruct(..) | PathSource::Delegation | PathSource::ReturnTypeNotation => ValueNS, - PathSource::TraitItem(ns) => ns, + PathSource::TraitItem(ns, _) => ns, PathSource::PreciseCapturingArg(ns) => ns, } } @@ -480,8 +483,9 @@ impl<'a> PathSource<'a> { PathSource::Trait(_) => "trait", PathSource::Pat => "unit struct, unit variant or constant", PathSource::Struct => "struct, variant or union type", - PathSource::TupleStruct(..) => "tuple struct or tuple variant", - PathSource::TraitItem(ns) => match ns { + PathSource::TraitItem(ValueNS, PathSource::TupleStruct(..)) + | PathSource::TupleStruct(..) => "tuple struct or tuple variant", + PathSource::TraitItem(ns, _) => match ns { TypeNS => "associated type", ValueNS => "method or associated constant", MacroNS => bug!("associated macro"), @@ -585,7 +589,7 @@ impl<'a> PathSource<'a> { ) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } ), - PathSource::TraitItem(ns) => match res { + PathSource::TraitItem(ns, _) => match res { Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true, Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, _ => false, @@ -2007,7 +2011,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, partial_res: PartialRes, path: &[Segment], - source: PathSource<'_>, + source: PathSource<'_, '_>, path_span: Span, ) { let proj_start = path.len() - partial_res.unresolved_segments(); @@ -4206,7 +4210,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { id: NodeId, qself: &Option<P<QSelf>>, path: &Path, - source: PathSource<'ast>, + source: PathSource<'ast, '_>, ) { self.smart_resolve_path_fragment( qself, @@ -4223,7 +4227,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, qself: &Option<P<QSelf>>, path: &[Segment], - source: PathSource<'ast>, + source: PathSource<'ast, '_>, finalize: Finalize, record_partial_res: RecordPartialRes, parent_qself: Option<&QSelf>, @@ -4404,6 +4408,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { path_span, source.defer_to_typeck(), finalize, + source, ) { Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { // if we also have an associated type that matches the ident, stash a suggestion @@ -4526,12 +4531,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { span: Span, defer_to_typeck: bool, finalize: Finalize, + source: PathSource<'ast, '_>, ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> { let mut fin_res = None; for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() { if i == 0 || ns != primary_ns { - match self.resolve_qpath(qself, path, ns, finalize)? { + match self.resolve_qpath(qself, path, ns, finalize, source)? { Some(partial_res) if partial_res.unresolved_segments() == 0 || defer_to_typeck => { @@ -4568,6 +4574,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { path: &[Segment], ns: Namespace, finalize: Finalize, + source: PathSource<'ast, '_>, ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> { debug!( "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", @@ -4615,7 +4622,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let partial_res = self.smart_resolve_path_fragment( &None, &path[..=qself.position], - PathSource::TraitItem(ns), + PathSource::TraitItem(ns, &source), Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), RecordPartialRes::No, Some(&qself), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ca25cdc9563..97a45fcf233 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -175,7 +175,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, path: &[Segment], span: Span, - source: PathSource<'_>, + source: PathSource<'_, '_>, res: Option<Res>, ) -> BaseError { // Make the base error. @@ -421,7 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, span: Span, - source: PathSource<'_>, + source: PathSource<'_, '_>, res: Option<Res>, qself: Option<&QSelf>, ) -> (Diag<'tcx>, Vec<ImportSuggestion>) { @@ -539,12 +539,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, span: Span, - source: PathSource<'_>, + source: PathSource<'_, '_>, res: Option<Res>, qself: Option<&QSelf>, ) { if let Some(Res::Def(DefKind::AssocFn, _)) = res - && let PathSource::TraitItem(TypeNS) = source + && let PathSource::TraitItem(TypeNS, _) = source && let None = following_seg && let Some(qself) = qself && let TyKind::Path(None, ty_path) = &qself.ty.kind @@ -650,7 +650,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn try_lookup_name_relaxed( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -940,7 +940,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_trait_and_bounds( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, res: Option<Res>, span: Span, base_error: &BaseError, @@ -1017,7 +1017,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_typo( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -1063,7 +1063,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_shadowed( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -1096,7 +1096,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn err_code_special_cases( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], span: Span, ) { @@ -1141,7 +1141,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_self_ty( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], span: Span, ) -> bool { @@ -1164,7 +1164,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_self_value( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], span: Span, ) -> bool { @@ -1332,7 +1332,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_swapping_misplaced_self_ty_and_trait( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, res: Option<Res>, span: Span, ) { @@ -1361,7 +1361,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, res: Option<Res>, - source: PathSource<'_>, + source: PathSource<'_, '_>, ) { let PathSource::TupleStruct(_, _) = source else { return }; let Some(Res::Def(DefKind::Fn, _)) = res else { return }; @@ -1373,7 +1373,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, res: Option<Res>, - source: PathSource<'_>, + source: PathSource<'_, '_>, span: Span, ) { let PathSource::Trait(_) = source else { return }; @@ -1422,7 +1422,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_pattern_match_with_let( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, span: Span, ) -> bool { if let PathSource::Expr(_) = source @@ -1448,10 +1448,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn get_single_associated_item( &mut self, path: &[Segment], - source: &PathSource<'_>, + source: &PathSource<'_, '_>, filter_fn: &impl Fn(Res) -> bool, ) -> Option<TypoSuggestion> { - if let crate::PathSource::TraitItem(_) = source { + if let crate::PathSource::TraitItem(_, _) = source { let mod_path = &path[..path.len() - 1]; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(mod_path, None, None) @@ -1556,7 +1556,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { /// Check if the source is call expression and the first argument is `self`. If true, /// return the span of whole call and the span for all arguments expect the first one (`self`). - fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option<Span>)> { + fn call_has_self_arg(&self, source: PathSource<'_, '_>) -> Option<(Span, Option<Span>)> { let mut has_self_arg = None; if let PathSource::Expr(Some(parent)) = source && let ExprKind::Call(_, args) = &parent.kind @@ -1614,7 +1614,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, span: Span, - source: PathSource<'_>, + source: PathSource<'_, '_>, path: &[Segment], res: Res, path_str: &str, @@ -1666,7 +1666,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let find_span = |source: &PathSource<'_>, err: &mut Diag<'_>| { + let find_span = |source: &PathSource<'_, '_>, err: &mut Diag<'_>| { match source { PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. })) | PathSource::TupleStruct(span, _) => { @@ -2050,8 +2050,86 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(span, fallback_label.to_string()); err.note("can't use `Self` as a constructor, you must use the implemented struct"); } - (Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => { + ( + Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), + PathSource::TraitItem(ValueNS, PathSource::TupleStruct(whole, args)), + ) => { + err.note("can't use a type alias as tuple pattern"); + + let mut suggestion = Vec::new(); + + if let &&[first, ..] = args + && let &&[.., last] = args + { + suggestion.extend([ + // "0: " has to be included here so that the fix is machine applicable. + // + // If this would only add " { " and then the code below add "0: ", + // rustfix would crash, because end of this suggestion is the same as start + // of the suggestion below. Thus, we have to merge these... + (span.between(first), " { 0: ".to_owned()), + (last.between(whole.shrink_to_hi()), " }".to_owned()), + ]); + + suggestion.extend( + args.iter() + .enumerate() + .skip(1) // See above + .map(|(index, &arg)| (arg.shrink_to_lo(), format!("{index}: "))), + ) + } else { + suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned())); + } + + err.multipart_suggestion( + "use struct pattern instead", + suggestion, + Applicability::MachineApplicable, + ); + } + ( + Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), + PathSource::TraitItem( + ValueNS, + PathSource::Expr(Some(ast::Expr { + span: whole, + kind: ast::ExprKind::Call(_, args), + .. + })), + ), + ) => { err.note("can't use a type alias as a constructor"); + + let mut suggestion = Vec::new(); + + if let [first, ..] = &**args + && let [.., last] = &**args + { + suggestion.extend([ + // "0: " has to be included here so that the fix is machine applicable. + // + // If this would only add " { " and then the code below add "0: ", + // rustfix would crash, because end of this suggestion is the same as start + // of the suggestion below. Thus, we have to merge these... + (span.between(first.span), " { 0: ".to_owned()), + (last.span.between(whole.shrink_to_hi()), " }".to_owned()), + ]); + + suggestion.extend( + args.iter() + .enumerate() + .skip(1) // See above + .map(|(index, arg)| (arg.span.shrink_to_lo(), format!("{index}: "))), + ) + } else { + suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned())); + } + + err.multipart_suggestion( + "use struct expression instead", + suggestion, + Applicability::MachineApplicable, + ); } _ => return false, } @@ -2621,7 +2699,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_using_enum_variant( &mut self, err: &mut Diag<'_>, - source: PathSource<'_>, + source: PathSource<'_, '_>, def_id: DefId, span: Span, ) { @@ -2799,7 +2877,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { pub(crate) fn suggest_adding_generic_parameter( &self, path: &[Segment], - source: PathSource<'_>, + source: PathSource<'_, '_>, ) -> Option<(Span, &'static str, String, Applicability)> { let (ident, span) = match path { [segment] diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr index edac09db89d..677fc0e10bb 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr @@ -8,9 +8,7 @@ error[E0575]: expected method or associated constant, found associated type `A:: --> $DIR/path-missing.rs:12:5 | LL | <T as A>::bad(..): Send, - | ^^^^^^^^^^^^^^^^^ - | - = note: can't use a type alias as a constructor + | ^^^^^^^^^^^^^^^^^ not a method or associated constant error[E0220]: associated function `method` not found for `T` --> $DIR/path-missing.rs:19:8 diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.rs b/tests/ui/associated-types/associated-type-tuple-struct-construction.rs deleted file mode 100644 index d5809ecd55d..00000000000 --- a/tests/ui/associated-types/associated-type-tuple-struct-construction.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Users cannot yet construct structs through associated types -// in both expressions and patterns - -#![feature(more_qualified_paths)] - -fn main() { - let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2); - //~^ ERROR expected method or associated constant, found associated type - //~| ERROR expected method or associated constant, found associated type - assert!(n == 2); -} - -struct TupleStruct(i8); - -struct Foo; - - -trait A { - type Assoc; -} - -impl A for Foo { - type Assoc = TupleStruct; -} diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr b/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr deleted file mode 100644 index bca7deeb512..00000000000 --- a/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0575]: expected method or associated constant, found associated type `A::Assoc` - --> $DIR/associated-type-tuple-struct-construction.rs:7:32 - | -LL | let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2); - | ^^^^^^^^^^^^^^^^^ - | - = note: can't use a type alias as a constructor - -error[E0575]: expected method or associated constant, found associated type `A::Assoc` - --> $DIR/associated-type-tuple-struct-construction.rs:7:9 - | -LL | let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2); - | ^^^^^^^^^^^^^^^^^ - | - = note: can't use a type alias as a constructor - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0575`. diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.fixed b/tests/ui/associated-types/tuple-struct-expr-pat.fixed new file mode 100644 index 00000000000..d6e2385f821 --- /dev/null +++ b/tests/ui/associated-types/tuple-struct-expr-pat.fixed @@ -0,0 +1,48 @@ +// Check that fully qualified syntax can **not** be used in tuple struct expressions (calls) and +// patterns. Both tuple struct expressions and patterns are resolved in value namespace and thus +// can't be resolved through associated *types*. +// +//@ run-rustfix + +#![feature(more_qualified_paths)] + +fn main() { + let <T<0> as Trait>::Assoc {} = <T<0> as Trait>::Assoc {}; + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<1> as Trait>::Assoc { 0: _a } = <T<1> as Trait>::Assoc { 0: 0 }; + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<2> as Trait>::Assoc { 0: _a, 1: _b } = <T<2> as Trait>::Assoc { 0: 0, 1: 1 }; + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<3> as Trait>::Assoc { 0: ref _a, 1: ref mut _b, 2: mut _c } = <T<3> as Trait>::Assoc { 0: 0, 1: 1, 2: 2 }; + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type +} + + +struct T<const N: usize>; + +struct T0(); +struct T1(u8); +struct T2(u8, u8); +struct T3(u8, u8, u8); + +trait Trait { + type Assoc; +} + +impl Trait for T<0> { + type Assoc = T0; +} + +impl Trait for T<1> { + type Assoc = T1; +} +impl Trait for T<2> { + type Assoc = T2; +} +impl Trait for T<3> { + type Assoc = T3; +} diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.rs b/tests/ui/associated-types/tuple-struct-expr-pat.rs new file mode 100644 index 00000000000..f27a5fe1753 --- /dev/null +++ b/tests/ui/associated-types/tuple-struct-expr-pat.rs @@ -0,0 +1,48 @@ +// Check that fully qualified syntax can **not** be used in tuple struct expressions (calls) and +// patterns. Both tuple struct expressions and patterns are resolved in value namespace and thus +// can't be resolved through associated *types*. +// +//@ run-rustfix + +#![feature(more_qualified_paths)] + +fn main() { + let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc(); + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0); + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1); + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type + let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2); + //~^ error: expected method or associated constant, found associated type + //~| error: expected tuple struct or tuple variant, found associated type +} + + +struct T<const N: usize>; + +struct T0(); +struct T1(u8); +struct T2(u8, u8); +struct T3(u8, u8, u8); + +trait Trait { + type Assoc; +} + +impl Trait for T<0> { + type Assoc = T0; +} + +impl Trait for T<1> { + type Assoc = T1; +} +impl Trait for T<2> { + type Assoc = T2; +} +impl Trait for T<3> { + type Assoc = T3; +} diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.stderr b/tests/ui/associated-types/tuple-struct-expr-pat.stderr new file mode 100644 index 00000000000..135dfcb3447 --- /dev/null +++ b/tests/ui/associated-types/tuple-struct-expr-pat.stderr @@ -0,0 +1,97 @@ +error[E0575]: expected method or associated constant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:10:36 + | +LL | let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc(); + | ^^^^^^^^^^^^^^^^^^^^^^-- help: use struct expression instead: `{}` + | + = note: can't use a type alias as a constructor + +error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:10:9 + | +LL | let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc(); + | ^^^^^^^^^^^^^^^^^^^^^^-- help: use struct pattern instead: `{}` + | + = note: can't use a type alias as tuple pattern + +error[E0575]: expected method or associated constant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:13:38 + | +LL | let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor +help: use struct expression instead + | +LL - let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0); +LL + let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc { 0: 0 }; + | + +error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:13:9 + | +LL | let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as tuple pattern +help: use struct pattern instead + | +LL - let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0); +LL + let <T<1> as Trait>::Assoc { 0: _a } = <T<1> as Trait>::Assoc(0); + | + +error[E0575]: expected method or associated constant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:16:42 + | +LL | let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor +help: use struct expression instead + | +LL - let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1); +LL + let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc { 0: 0, 1: 1 }; + | + +error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:16:9 + | +LL | let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as tuple pattern +help: use struct pattern instead + | +LL - let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1); +LL + let <T<2> as Trait>::Assoc { 0: _a, 1: _b } = <T<2> as Trait>::Assoc(0, 1); + | + +error[E0575]: expected method or associated constant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:19:62 + | +LL | let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor +help: use struct expression instead + | +LL - let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2); +LL + let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc { 0: 0, 1: 1, 2: 2 }; + | + +error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc` + --> $DIR/tuple-struct-expr-pat.rs:19:9 + | +LL | let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as tuple pattern +help: use struct pattern instead + | +LL - let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2); +LL + let <T<3> as Trait>::Assoc { 0: ref _a, 1: ref mut _b, 2: mut _c } = <T<3> as Trait>::Assoc(0, 1, 2); + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0575`. diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 966387e1d61..fc6811292a6 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -44,9 +44,7 @@ error[E0575]: expected method or associated constant, found associated type `Tra --> $DIR/bad-resolve.rs:27:11 | LL | reuse <F as Trait>::Type; - | ^^^^^^^^^^^^^^^^^^ - | - = note: can't use a type alias as a constructor + | ^^^^^^^^^^^^^^^^^^ not a method or associated constant error[E0576]: cannot find method or associated constant `baz` in trait `Trait` --> $DIR/bad-resolve.rs:30:25 diff --git a/tests/ui/delegation/glob-non-fn.stderr b/tests/ui/delegation/glob-non-fn.stderr index 4b918c53b84..f63c8e88c6f 100644 --- a/tests/ui/delegation/glob-non-fn.stderr +++ b/tests/ui/delegation/glob-non-fn.stderr @@ -38,9 +38,7 @@ error[E0423]: expected function, found associated type `Trait::Type` --> $DIR/glob-non-fn.rs:30:11 | LL | reuse Trait::* { &self.0 } - | ^^^^^ - | - = note: can't use a type alias as a constructor + | ^^^^^ not a function error[E0046]: not all trait items implemented, missing: `CONST`, `Type`, `method` --> $DIR/glob-non-fn.rs:29:1 diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr index 412ea4aba30..200d31cc710 100644 --- a/tests/ui/namespace/namespace-mix.stderr +++ b/tests/ui/namespace/namespace-mix.stderr @@ -7,7 +7,6 @@ LL | pub struct TS(); LL | check(m1::S); | ^^^^^ | - = note: can't use a type alias as a constructor help: a tuple struct with a similar name exists | LL | check(m1::TS); @@ -35,7 +34,6 @@ LL | check(xm1::S); LL | pub struct TS(); | ------------- similarly named tuple struct `TS` defined here | - = note: can't use a type alias as a constructor help: a tuple struct with a similar name exists | LL | check(xm1::TS); @@ -61,7 +59,6 @@ LL | TV(), LL | check(m7::V); | ^^^^^ | - = note: can't use a type alias as a constructor help: a tuple variant with a similar name exists | LL | check(m7::TV); @@ -89,7 +86,6 @@ LL | check(xm7::V); LL | TV(), | -- similarly named tuple variant `TV` defined here | - = note: can't use a type alias as a constructor help: a tuple variant with a similar name exists | LL | check(xm7::TV); diff --git a/tests/ui/resolve/tuple-struct-alias.stderr b/tests/ui/resolve/tuple-struct-alias.stderr index a739ea43eed..bf026a499b8 100644 --- a/tests/ui/resolve/tuple-struct-alias.stderr +++ b/tests/ui/resolve/tuple-struct-alias.stderr @@ -6,8 +6,6 @@ LL | struct S(u8, u16); ... LL | A(..) => {} | ^ help: a tuple struct with a similar name exists: `S` - | - = note: can't use a type alias as a constructor error[E0423]: expected function, tuple struct or tuple variant, found type alias `A` --> $DIR/tuple-struct-alias.rs:5:13 @@ -16,9 +14,18 @@ LL | struct S(u8, u16); | ------------------ similarly named tuple struct `S` defined here ... LL | let s = A(0, 1); - | ^ help: a tuple struct with a similar name exists: `S` + | ^ + | +help: a tuple struct with a similar name exists + | +LL - let s = A(0, 1); +LL + let s = S(0, 1); + | +help: you might have meant to use `:` for type annotation + | +LL - let s = A(0, 1); +LL + let s: A(0, 1); | - = note: can't use a type alias as a constructor error: aborting due to 2 previous errors diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr index 0a9c190cb35..69d6bd74a73 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.stderr +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -235,8 +235,6 @@ LL | <u8 as Dr>::X; | ^^^^^^^^^^^^- | | | help: an associated function with a similar name exists: `Z` - | - = note: can't use a type alias as a constructor error[E0575]: expected associated type, found associated function `Dr::Z` --> $DIR/ufcs-partially-resolved.rs:54:12 |
