diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-09-22 17:35:03 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-10-09 14:44:24 -0700 |
| commit | 711760c8ec9dc431de43a0a72593abcdd74e0b3e (patch) | |
| tree | e4a24a34202f8be633420344d75ca63eb5707016 | |
| parent | 5ddef544fa26c5535376fa424baf30cb985f7cb1 (diff) | |
Point out why a trait is expected on `Struct + 'lt`
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-bounds-not-on-struct.stderr | 6 |
3 files changed, 23 insertions, 1 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2c01934b490..cfaf59e8feb 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -384,6 +384,8 @@ struct DiagnosticMetadata<'ast> { /// Used to detect possible `if let` written without `let` and to provide structured suggestion. in_if_condition: Option<&'ast Expr>, + + current_trait_object: Option<&'ast [ast::GenericBound]>, } struct LateResolutionVisitor<'a, 'b, 'ast> { @@ -453,6 +455,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { self.diagnostic_metadata.current_let_binding = original; } fn visit_ty(&mut self, ty: &'ast Ty) { + let prev = self.diagnostic_metadata.current_trait_object; match ty.kind { TyKind::Path(ref qself, ref path) => { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); @@ -464,9 +467,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); } + TyKind::TraitObject(ref bounds, ..) => { + self.diagnostic_metadata.current_trait_object = Some(&bounds[..]); + } _ => (), } visit::walk_ty(self, ty); + self.diagnostic_metadata.current_trait_object = prev; } fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { self.smart_resolve_path( diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 15e72228870..a3948cc00d6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1,6 +1,6 @@ use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion}; use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; -use crate::late::{LateResolutionVisitor, RibKind}; +use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind}; use crate::path_names_to_string; use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; @@ -445,6 +445,15 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Fallback label. err.span_label(base_span, fallback_label); + if let PathSource::Trait(AliasPossibility::Maybe) = source { + if let Some([start, .., end]) = self.diagnostic_metadata.current_trait_object { + err.span_help( + start.span().to(end.span()), + "`+` can be used to constrain a \"trait object\" type with lifetimes or \ + auto-traits, structs and enums can't be bound in that way", + ); + } + } match self.diagnostic_metadata.current_let_binding { Some((pat_sp, Some(ty_sp), None)) if ty_sp.contains(base_span) && could_be_expr => { err.span_suggestion_short( diff --git a/src/test/ui/traits/trait-bounds-not-on-struct.stderr b/src/test/ui/traits/trait-bounds-not-on-struct.stderr index a649a4eee55..3d338ef3736 100644 --- a/src/test/ui/traits/trait-bounds-not-on-struct.stderr +++ b/src/test/ui/traits/trait-bounds-not-on-struct.stderr @@ -3,6 +3,12 @@ error[E0404]: expected trait, found struct `Foo` | LL | fn foo(_x: Box<Foo + Send>) { } | ^^^ not a trait + | +help: `+` can be used to constrain a "trait object" type with lifetimes or auto-traits, structs and enums can't be bound in that way + --> $DIR/trait-bounds-not-on-struct.rs:5:16 + | +LL | fn foo(_x: Box<Foo + Send>) { } + | ^^^^^^^^^^ error[E0404]: expected trait, found struct `Vec` --> $DIR/trait-bounds-not-on-struct.rs:7:21 |
