Skip to content

Commit 767ffce

Browse files
author
Alexander Regueiro
committed
Made suggestion diagnostics more consistent for enum variant names, relative to method names.
1 parent ecacad0 commit 767ffce

File tree

5 files changed

+84
-69
lines changed

5 files changed

+84
-69
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12771277
ref_id: ast::NodeId,
12781278
span: Span,
12791279
ty: Ty<'tcx>,
1280-
ty_hir: &hir::Ty,
1280+
qself: &hir::Ty,
12811281
ty_path_def: Def,
12821282
item_segment: &hir::PathSegment)
12831283
-> (Ty<'tcx>, Def)
@@ -1292,11 +1292,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12921292
// Check if we have an enum variant here.
12931293
if let ty::Adt(adt_def, _) = ty.sty {
12941294
if adt_def.is_enum() {
1295-
if allow_type_alias_enum_variants(tcx, ty_hir, span) {
1296-
let variant_def = adt_def.variants.iter().find(|vd| {
1297-
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1298-
});
1299-
if let Some(variant_def) = variant_def {
1295+
let variant_def = adt_def.variants.iter().find(|vd| {
1296+
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1297+
});
1298+
if let Some(variant_def) = variant_def {
1299+
if allow_type_alias_enum_variants(tcx, qself, span) {
13001300
let def = Def::Variant(variant_def.did);
13011301
return (ty, def);
13021302
}

src/librustc_typeck/check/method/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod suggest;
88

99
pub use self::MethodError::*;
1010
pub use self::CandidateSource::*;
11-
pub use self::suggest::TraitInfo;
11+
pub use self::suggest::{SelfSource, TraitInfo};
1212

1313
use check::FnCtxt;
1414
use namespace::Namespace;
@@ -361,7 +361,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
361361
span: Span,
362362
method_name: ast::Ident,
363363
self_ty: Ty<'tcx>,
364-
self_ty_hir: &hir::Ty,
364+
qself: &hir::Ty,
365365
expr_id: ast::NodeId)
366366
-> Result<Def, MethodError<'tcx>> {
367367
debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
@@ -375,11 +375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
375375
// Check if we have an enum variant here.
376376
if let ty::Adt(adt_def, _) = self_ty.sty {
377377
if adt_def.is_enum() {
378-
if allow_type_alias_enum_variants(tcx, self_ty_hir, span) {
379-
let variant_def = adt_def.variants.iter().find(|vd| {
380-
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
381-
});
382-
if let Some(variant_def) = variant_def {
378+
let variant_def = adt_def.variants.iter().find(|vd| {
379+
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
380+
});
381+
if let Some(variant_def) = variant_def {
382+
if allow_type_alias_enum_variants(tcx, qself, span) {
383383
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
384384
return Ok(def);
385385
}

src/librustc_typeck/check/method/suggest.rs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use errors::{Applicability, DiagnosticBuilder};
66
use middle::lang_items::FnOnceTraitLangItem;
77
use namespace::Namespace;
88
use rustc_data_structures::sync::Lrc;
9-
use rustc::hir::{self, Node};
9+
use rustc::hir::{self, ExprKind, Node, QPath};
1010
use rustc::hir::def::Def;
1111
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
1212
use rustc::hir::map as hir_map;
@@ -60,13 +60,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
6060
}
6161
}
6262

63-
pub fn report_method_error(&self,
64-
span: Span,
65-
rcvr_ty: Ty<'tcx>,
66-
item_name: ast::Ident,
67-
rcvr_expr: Option<&hir::Expr>,
68-
error: MethodError<'tcx>,
69-
args: Option<&'gcx [hir::Expr]>) {
63+
pub fn report_method_error<'b>(&self,
64+
span: Span,
65+
rcvr_ty: Ty<'tcx>,
66+
item_name: ast::Ident,
67+
source: SelfSource<'b>,
68+
error: MethodError<'tcx>,
69+
args: Option<&'gcx [hir::Expr]>) {
7070
// Avoid suggestions when we don't know what's going on.
7171
if rcvr_ty.references_error() {
7272
return;
@@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212212
.filter_map(|info|
213213
self.associated_item(info.def_id, item_name, Namespace::Value)
214214
);
215-
if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(),
216-
actual.has_concrete_skeleton(),
217-
rcvr_expr,
218-
candidates.next()) {
215+
if let (true, false, SelfSource::MethodCall(expr), Some(_)) =
216+
(actual.is_numeric(),
217+
actual.has_concrete_skeleton(),
218+
source,
219+
candidates.next()) {
219220
let mut err = struct_span_err!(
220221
tcx.sess,
221222
span,
@@ -231,7 +232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
231232
"f32"
232233
};
233234
match expr.node {
234-
hir::ExprKind::Lit(ref lit) => {
235+
ExprKind::Lit(ref lit) => {
235236
// numeric literal
236237
let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
237238
.unwrap_or_else(|_| "<numeric literal>".to_owned());
@@ -247,9 +248,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
247248
Applicability::MaybeIncorrect,
248249
);
249250
}
250-
hir::ExprKind::Path(ref qpath) => {
251+
ExprKind::Path(ref qpath) => {
251252
// local binding
252-
if let &hir::QPath::Resolved(_, ref path) = &qpath {
253+
if let &QPath::Resolved(_, ref path) = &qpath {
253254
if let hir::def::Def::Local(node_id) = path.def {
254255
let span = tcx.hir().span(node_id);
255256
let snippet = tcx.sess.source_map().span_to_snippet(span)
@@ -294,15 +295,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
294295
} else {
295296
let mut err = struct_span_err!(
296297
tcx.sess,
297-
span,
298+
item_name.span,
298299
E0599,
299300
"no {} named `{}` found for type `{}` in the current scope",
300301
item_kind,
301302
item_name,
302303
ty_str
303304
);
304305
if let Some(suggestion) = suggestion {
305-
err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion));
306+
// enum variant
307+
err.help(&format!("did you mean `{}`?", suggestion));
306308
}
307309
err
308310
}
@@ -326,7 +328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
326328

327329
// If the method name is the name of a field with a function or closure type,
328330
// give a helping note that it has to be called as `(x.f)(...)`.
329-
if let Some(expr) = rcvr_expr {
331+
if let SelfSource::MethodCall(expr) = source {
330332
for (ty, _) in self.autoderef(span, rcvr_ty) {
331333
if let ty::Adt(def, substs) = ty.sty {
332334
if !def.is_enum() {
@@ -377,10 +379,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
377379
}
378380
}
379381

380-
if let Some(expr) = rcvr_expr {
382+
if let SelfSource::MethodCall(expr) = source {
381383
if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
382384
report_function!(expr.span, expr_string);
383-
} else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) =
385+
} else if let ExprKind::Path(QPath::Resolved(_, ref path)) =
384386
expr.node
385387
{
386388
if let Some(segment) = path.segments.last() {
@@ -396,7 +398,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
396398
err.span_label(span, "this is an associated function, not a method");
397399
}
398400
if static_sources.len() == 1 {
399-
if let Some(expr) = rcvr_expr {
401+
if let SelfSource::MethodCall(expr) = source {
400402
err.span_suggestion_with_applicability(expr.span.to(span),
401403
"use associated function syntax instead",
402404
format!("{}::{}",
@@ -433,7 +435,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
433435
span,
434436
rcvr_ty,
435437
item_name,
436-
rcvr_expr,
438+
source,
437439
out_of_scope_traits);
438440
}
439441

@@ -571,18 +573,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
571573
}
572574
}
573575

574-
fn suggest_traits_to_import(&self,
575-
err: &mut DiagnosticBuilder,
576-
span: Span,
577-
rcvr_ty: Ty<'tcx>,
578-
item_name: ast::Ident,
579-
rcvr_expr: Option<&hir::Expr>,
580-
valid_out_of_scope_traits: Vec<DefId>) {
576+
fn suggest_traits_to_import<'b>(&self,
577+
err: &mut DiagnosticBuilder,
578+
span: Span,
579+
rcvr_ty: Ty<'tcx>,
580+
item_name: ast::Ident,
581+
source: SelfSource<'b>,
582+
valid_out_of_scope_traits: Vec<DefId>) {
581583
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
582584
return;
583585
}
584586

585-
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr);
587+
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
586588

587589
// There are no traits implemented, so lets suggest some traits to
588590
// implement, by finding ones that have the item name, and are
@@ -663,14 +665,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
663665

664666
// This occurs for UFCS desugaring of `T::method`, where there is no
665667
// receiver expression for the method call, and thus no autoderef.
666-
if rcvr_expr.is_none() {
668+
if let SelfSource::QPath(_) = source {
667669
return is_local(self.resolve_type_vars_with_obligations(rcvr_ty));
668670
}
669671

670672
self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
671673
}
672674
}
673675

676+
#[derive(Copy, Clone)]
677+
pub enum SelfSource<'a> {
678+
QPath(&'a hir::Ty),
679+
MethodCall(&'a hir::Expr /* rcvr */),
680+
}
681+
674682
#[derive(Copy, Clone)]
675683
pub struct TraitInfo {
676684
pub def_id: DefId,

0 commit comments

Comments
 (0)