Skip to content

Commit b5b2716

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

File tree

5 files changed

+83
-68
lines changed

5 files changed

+83
-68
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12631263
ref_id: ast::NodeId,
12641264
span: Span,
12651265
ty: Ty<'tcx>,
1266-
ty_hir: &hir::Ty,
1266+
qself: &hir::Ty,
12671267
ty_path_def: Def,
12681268
item_segment: &hir::PathSegment)
12691269
-> (Ty<'tcx>, Def)
@@ -1278,11 +1278,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12781278
// Check if we have an enum variant here.
12791279
if let ty::Adt(adt_def, _) = ty.sty {
12801280
if adt_def.is_enum() {
1281-
if allow_type_alias_enum_variants(tcx, ty_hir, span) {
1282-
let variant_def = adt_def.variants.iter().find(|vd| {
1283-
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1284-
});
1285-
if let Some(variant_def) = variant_def {
1281+
let variant_def = adt_def.variants.iter().find(|vd| {
1282+
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1283+
});
1284+
if let Some(variant_def) = variant_def {
1285+
if allow_type_alias_enum_variants(tcx, qself, span) {
12861286
let def = Def::Variant(variant_def.did);
12871287
return (ty, def);
12881288
}

src/librustc_typeck/check/method/mod.rs

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

1919
pub use self::MethodError::*;
2020
pub use self::CandidateSource::*;
21-
pub use self::suggest::TraitInfo;
21+
pub use self::suggest::{SelfSource, TraitInfo};
2222

2323
use check::FnCtxt;
2424
use namespace::Namespace;
@@ -370,7 +370,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
370370
span: Span,
371371
method_name: ast::Ident,
372372
self_ty: Ty<'tcx>,
373-
self_ty_hir: &hir::Ty,
373+
qself: &hir::Ty,
374374
expr_id: ast::NodeId)
375375
-> Result<Def, MethodError<'tcx>> {
376376
debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
@@ -384,11 +384,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
384384
// Check if we have an enum variant here.
385385
if let ty::Adt(adt_def, _) = self_ty.sty {
386386
if adt_def.is_enum() {
387-
if allow_type_alias_enum_variants(tcx, self_ty_hir, span) {
388-
let variant_def = adt_def.variants.iter().find(|vd| {
389-
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
390-
});
391-
if let Some(variant_def) = variant_def {
387+
let variant_def = adt_def.variants.iter().find(|vd| {
388+
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
389+
});
390+
if let Some(variant_def) = variant_def {
391+
if allow_type_alias_enum_variants(tcx, qself, span) {
392392
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
393393
return Ok(def);
394394
}

src/librustc_typeck/check/method/suggest.rs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use errors::{Applicability, DiagnosticBuilder};
1616
use middle::lang_items::FnOnceTraitLangItem;
1717
use namespace::Namespace;
1818
use rustc_data_structures::sync::Lrc;
19-
use rustc::hir::{self, Node};
19+
use rustc::hir::{self, ExprKind, Node, QPath};
2020
use rustc::hir::def::Def;
2121
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
2222
use rustc::hir::map as hir_map;
@@ -70,13 +70,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7070
}
7171
}
7272

73-
pub fn report_method_error(&self,
74-
span: Span,
75-
rcvr_ty: Ty<'tcx>,
76-
item_name: ast::Ident,
77-
rcvr_expr: Option<&hir::Expr>,
78-
error: MethodError<'tcx>,
79-
args: Option<&'gcx [hir::Expr]>) {
73+
pub fn report_method_error<'b>(&self,
74+
span: Span,
75+
rcvr_ty: Ty<'tcx>,
76+
item_name: ast::Ident,
77+
source: SelfSource<'b>,
78+
error: MethodError<'tcx>,
79+
args: Option<&'gcx [hir::Expr]>) {
8080
// Avoid suggestions when we don't know what's going on.
8181
if rcvr_ty.references_error() {
8282
return;
@@ -222,10 +222,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
222222
.filter_map(|info|
223223
self.associated_item(info.def_id, item_name, Namespace::Value)
224224
);
225-
if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(),
226-
actual.has_concrete_skeleton(),
227-
rcvr_expr,
228-
candidates.next()) {
225+
if let (true, false, SelfSource::MethodCall(expr), Some(_)) =
226+
(actual.is_numeric(),
227+
actual.has_concrete_skeleton(),
228+
source,
229+
candidates.next()) {
229230
let mut err = struct_span_err!(
230231
tcx.sess,
231232
span,
@@ -241,7 +242,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
241242
"f32"
242243
};
243244
match expr.node {
244-
hir::ExprKind::Lit(ref lit) => {
245+
ExprKind::Lit(ref lit) => {
245246
// numeric literal
246247
let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
247248
.unwrap_or_else(|_| "<numeric literal>".to_owned());
@@ -257,9 +258,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
257258
Applicability::MaybeIncorrect,
258259
);
259260
}
260-
hir::ExprKind::Path(ref qpath) => {
261+
ExprKind::Path(ref qpath) => {
261262
// local binding
262-
if let &hir::QPath::Resolved(_, ref path) = &qpath {
263+
if let &QPath::Resolved(_, ref path) = &qpath {
263264
if let hir::def::Def::Local(node_id) = path.def {
264265
let span = tcx.hir().span(node_id);
265266
let snippet = tcx.sess.source_map().span_to_snippet(span)
@@ -304,15 +305,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
304305
} else {
305306
let mut err = struct_span_err!(
306307
tcx.sess,
307-
span,
308+
item_name.span,
308309
E0599,
309310
"no {} named `{}` found for type `{}` in the current scope",
310311
item_kind,
311312
item_name,
312313
ty_str
313314
);
314315
if let Some(suggestion) = suggestion {
315-
err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion));
316+
// enum variant
317+
err.help(&format!("did you mean `{}`?", suggestion));
316318
}
317319
err
318320
}
@@ -336,7 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
336338

337339
// If the method name is the name of a field with a function or closure type,
338340
// give a helping note that it has to be called as `(x.f)(...)`.
339-
if let Some(expr) = rcvr_expr {
341+
if let SelfSource::MethodCall(expr) = source {
340342
for (ty, _) in self.autoderef(span, rcvr_ty) {
341343
if let ty::Adt(def, substs) = ty.sty {
342344
if !def.is_enum() {
@@ -387,10 +389,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
387389
}
388390
}
389391

390-
if let Some(expr) = rcvr_expr {
392+
if let SelfSource::MethodCall(expr) = source {
391393
if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
392394
report_function!(expr.span, expr_string);
393-
} else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) =
395+
} else if let ExprKind::Path(QPath::Resolved(_, ref path)) =
394396
expr.node
395397
{
396398
if let Some(segment) = path.segments.last() {
@@ -406,7 +408,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
406408
err.span_label(span, "this is an associated function, not a method");
407409
}
408410
if static_sources.len() == 1 {
409-
if let Some(expr) = rcvr_expr {
411+
if let SelfSource::MethodCall(expr) = source {
410412
err.span_suggestion_with_applicability(expr.span.to(span),
411413
"use associated function syntax instead",
412414
format!("{}::{}",
@@ -441,7 +443,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
441443
span,
442444
rcvr_ty,
443445
item_name,
444-
rcvr_expr,
446+
source,
445447
out_of_scope_traits);
446448
}
447449

@@ -579,18 +581,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
579581
}
580582
}
581583

582-
fn suggest_traits_to_import(&self,
583-
err: &mut DiagnosticBuilder,
584-
span: Span,
585-
rcvr_ty: Ty<'tcx>,
586-
item_name: ast::Ident,
587-
rcvr_expr: Option<&hir::Expr>,
588-
valid_out_of_scope_traits: Vec<DefId>) {
584+
fn suggest_traits_to_import<'b>(&self,
585+
err: &mut DiagnosticBuilder,
586+
span: Span,
587+
rcvr_ty: Ty<'tcx>,
588+
item_name: ast::Ident,
589+
source: SelfSource<'b>,
590+
valid_out_of_scope_traits: Vec<DefId>) {
589591
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
590592
return;
591593
}
592594

593-
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr);
595+
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
594596

595597
// There are no traits implemented, so lets suggest some traits to
596598
// implement, by finding ones that have the item name, and are
@@ -671,14 +673,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
671673

672674
// This occurs for UFCS desugaring of `T::method`, where there is no
673675
// receiver expression for the method call, and thus no autoderef.
674-
if rcvr_expr.is_none() {
676+
if let SelfSource::QPath(_) = source {
675677
return is_local(self.resolve_type_vars_with_obligations(rcvr_ty));
676678
}
677679

678680
self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
679681
}
680682
}
681683

684+
#[derive(Copy, Clone)]
685+
pub enum SelfSource<'a> {
686+
QPath(&'a hir::Ty),
687+
MethodCall(&'a hir::Expr /* rcvr */),
688+
}
689+
682690
#[derive(Copy, Clone)]
683691
pub struct TraitInfo {
684692
pub def_id: DefId,

0 commit comments

Comments
 (0)