Skip to content

Commit

Permalink
address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Oct 10, 2020
1 parent fdbe4ce commit 4ae8f6e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 9 deletions.
10 changes: 10 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Expand Up @@ -1884,6 +1884,16 @@ impl Clone for Ty {
}
}

impl Ty {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = &ty;
}
final_ty
}
}

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafe,
Expand Down
24 changes: 16 additions & 8 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Expand Up @@ -442,7 +442,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {

if !self.type_ascription_suggestion(&mut err, base_span) {
let mut fallback = false;
if let PathSource::Trait(AliasPossibility::Maybe) = source {
if let (
PathSource::Trait(AliasPossibility::Maybe),
Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)),
) = (source, res)
{
if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object {
fallback = true;
let spans: Vec<Span> = bounds
Expand Down Expand Up @@ -580,7 +584,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
return false;
};

if let ast::TyKind::Path(None, type_param_path) = &ty.kind {
if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind {
// Confirm that the `SelfTy` is a type parameter.
let partial_res = if let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
bounded_ty.id,
Expand All @@ -603,20 +607,24 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
return false;
}
if let (
[ast::PathSegment { ident, args: None, .. }],
[ast::PathSegment { ident: constrain_ident, args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
) = (&type_param_path.segments[..], &bounds[..])
{
if let [ast::PathSegment { ident: bound_ident, args: None, .. }] =
if let [ast::PathSegment { ident, args: None, .. }] =
&poly_trait_ref.trait_ref.path.segments[..]
{
if bound_ident.span == span {
if ident.span == span {
err.span_suggestion_verbose(
*where_span,
&format!("constrain the associated type to `{}`", bound_ident),
&format!("constrain the associated type to `{}`", ident),
format!(
"{}: {}<{} = {}>",
ident,
self.r
.session
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
path.segments[..*position]
.iter()
.map(|segment| path_segment_to_string(segment))
Expand All @@ -627,7 +635,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
bound_ident,
ident,
),
Applicability::MaybeIncorrect,
);
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/traits/assoc_type_bound_with_struct.rs
Expand Up @@ -6,4 +6,14 @@ struct Foo<T> where T: Bar, <T as Bar>::Baz: String { //~ ERROR expected trait,
t: T,
}

struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found struct
t: &'a T,
}

fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, found struct
}

fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
}

fn main() {}
62 changes: 61 additions & 1 deletion src/test/ui/traits/assoc_type_bound_with_struct.stderr
Expand Up @@ -18,6 +18,66 @@ help: a trait with a similar name exists
LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: ToString {
| ^^^^^^^^

error: aborting due to previous error
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:9:54
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | struct Qux<'a, T> where T: Bar, &'a T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString {
| ^^^^^^^^

error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:13:45
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | fn foo<T: Bar>(_: T) where T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: ToString {
| ^^^^^^^^

error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:16:57
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | fn qux<'a, T: Bar>(_: &'a T) where &'a T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
| ^^^^^^^^

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0404`.

0 comments on commit 4ae8f6e

Please sign in to comment.