Skip to content

Commit 711760c

Browse files
committed
Point out why a trait is expected on Struct + 'lt
1 parent 5ddef54 commit 711760c

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,8 @@ struct DiagnosticMetadata<'ast> {
384384

385385
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
386386
in_if_condition: Option<&'ast Expr>,
387+
388+
current_trait_object: Option<&'ast [ast::GenericBound]>,
387389
}
388390

389391
struct LateResolutionVisitor<'a, 'b, 'ast> {
@@ -453,6 +455,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
453455
self.diagnostic_metadata.current_let_binding = original;
454456
}
455457
fn visit_ty(&mut self, ty: &'ast Ty) {
458+
let prev = self.diagnostic_metadata.current_trait_object;
456459
match ty.kind {
457460
TyKind::Path(ref qself, ref path) => {
458461
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> {
464467
.map_or(Res::Err, |d| d.res());
465468
self.r.record_partial_res(ty.id, PartialRes::new(res));
466469
}
470+
TyKind::TraitObject(ref bounds, ..) => {
471+
self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
472+
}
467473
_ => (),
468474
}
469475
visit::walk_ty(self, ty);
476+
self.diagnostic_metadata.current_trait_object = prev;
470477
}
471478
fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
472479
self.smart_resolve_path(

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
22
use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
3-
use crate::late::{LateResolutionVisitor, RibKind};
3+
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
44
use crate::path_names_to_string;
55
use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
66
use crate::{PathResult, PathSource, Segment};
@@ -445,6 +445,15 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
445445
// Fallback label.
446446
err.span_label(base_span, fallback_label);
447447

448+
if let PathSource::Trait(AliasPossibility::Maybe) = source {
449+
if let Some([start, .., end]) = self.diagnostic_metadata.current_trait_object {
450+
err.span_help(
451+
start.span().to(end.span()),
452+
"`+` can be used to constrain a \"trait object\" type with lifetimes or \
453+
auto-traits, structs and enums can't be bound in that way",
454+
);
455+
}
456+
}
448457
match self.diagnostic_metadata.current_let_binding {
449458
Some((pat_sp, Some(ty_sp), None)) if ty_sp.contains(base_span) && could_be_expr => {
450459
err.span_suggestion_short(

src/test/ui/traits/trait-bounds-not-on-struct.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ error[E0404]: expected trait, found struct `Foo`
33
|
44
LL | fn foo(_x: Box<Foo + Send>) { }
55
| ^^^ not a trait
6+
|
7+
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
8+
--> $DIR/trait-bounds-not-on-struct.rs:5:16
9+
|
10+
LL | fn foo(_x: Box<Foo + Send>) { }
11+
| ^^^^^^^^^^
612

713
error[E0404]: expected trait, found struct `Vec`
814
--> $DIR/trait-bounds-not-on-struct.rs:7:21

0 commit comments

Comments
 (0)