Made suggestion diagnostics more consistent for enum variant names, relative to method names.
This commit is contained in:
parent
ecacad0770
commit
767ffced91
5 changed files with 84 additions and 69 deletions
|
|
@ -1277,7 +1277,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||
ref_id: ast::NodeId,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
ty_hir: &hir::Ty,
|
||||
qself: &hir::Ty,
|
||||
ty_path_def: Def,
|
||||
item_segment: &hir::PathSegment)
|
||||
-> (Ty<'tcx>, Def)
|
||||
|
|
@ -1292,11 +1292,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||
// Check if we have an enum variant here.
|
||||
if let ty::Adt(adt_def, _) = ty.sty {
|
||||
if adt_def.is_enum() {
|
||||
if allow_type_alias_enum_variants(tcx, ty_hir, span) {
|
||||
let variant_def = adt_def.variants.iter().find(|vd| {
|
||||
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
|
||||
});
|
||||
if let Some(variant_def) = variant_def {
|
||||
let variant_def = adt_def.variants.iter().find(|vd| {
|
||||
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
|
||||
});
|
||||
if let Some(variant_def) = variant_def {
|
||||
if allow_type_alias_enum_variants(tcx, qself, span) {
|
||||
let def = Def::Variant(variant_def.did);
|
||||
return (ty, def);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ mod suggest;
|
|||
|
||||
pub use self::MethodError::*;
|
||||
pub use self::CandidateSource::*;
|
||||
pub use self::suggest::TraitInfo;
|
||||
pub use self::suggest::{SelfSource, TraitInfo};
|
||||
|
||||
use check::FnCtxt;
|
||||
use namespace::Namespace;
|
||||
|
|
@ -361,7 +361,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
span: Span,
|
||||
method_name: ast::Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
self_ty_hir: &hir::Ty,
|
||||
qself: &hir::Ty,
|
||||
expr_id: ast::NodeId)
|
||||
-> Result<Def, MethodError<'tcx>> {
|
||||
debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
|
||||
|
|
@ -375,11 +375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Check if we have an enum variant here.
|
||||
if let ty::Adt(adt_def, _) = self_ty.sty {
|
||||
if adt_def.is_enum() {
|
||||
if allow_type_alias_enum_variants(tcx, self_ty_hir, span) {
|
||||
let variant_def = adt_def.variants.iter().find(|vd| {
|
||||
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
|
||||
});
|
||||
if let Some(variant_def) = variant_def {
|
||||
let variant_def = adt_def.variants.iter().find(|vd| {
|
||||
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
|
||||
});
|
||||
if let Some(variant_def) = variant_def {
|
||||
if allow_type_alias_enum_variants(tcx, qself, span) {
|
||||
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
|
||||
return Ok(def);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use errors::{Applicability, DiagnosticBuilder};
|
|||
use middle::lang_items::FnOnceTraitLangItem;
|
||||
use namespace::Namespace;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc::hir::{self, Node};
|
||||
use rustc::hir::{self, ExprKind, Node, QPath};
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
||||
use rustc::hir::map as hir_map;
|
||||
|
|
@ -60,13 +60,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn report_method_error(&self,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: ast::Ident,
|
||||
rcvr_expr: Option<&hir::Expr>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'gcx [hir::Expr]>) {
|
||||
pub fn report_method_error<'b>(&self,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: ast::Ident,
|
||||
source: SelfSource<'b>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'gcx [hir::Expr]>) {
|
||||
// Avoid suggestions when we don't know what's going on.
|
||||
if rcvr_ty.references_error() {
|
||||
return;
|
||||
|
|
@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
.filter_map(|info|
|
||||
self.associated_item(info.def_id, item_name, Namespace::Value)
|
||||
);
|
||||
if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(),
|
||||
actual.has_concrete_skeleton(),
|
||||
rcvr_expr,
|
||||
candidates.next()) {
|
||||
if let (true, false, SelfSource::MethodCall(expr), Some(_)) =
|
||||
(actual.is_numeric(),
|
||||
actual.has_concrete_skeleton(),
|
||||
source,
|
||||
candidates.next()) {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
|
|
@ -231,7 +232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
"f32"
|
||||
};
|
||||
match expr.node {
|
||||
hir::ExprKind::Lit(ref lit) => {
|
||||
ExprKind::Lit(ref lit) => {
|
||||
// numeric literal
|
||||
let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
|
||||
.unwrap_or_else(|_| "<numeric literal>".to_owned());
|
||||
|
|
@ -247,9 +248,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
ExprKind::Path(ref qpath) => {
|
||||
// local binding
|
||||
if let &hir::QPath::Resolved(_, ref path) = &qpath {
|
||||
if let &QPath::Resolved(_, ref path) = &qpath {
|
||||
if let hir::def::Def::Local(node_id) = path.def {
|
||||
let span = tcx.hir().span(node_id);
|
||||
let snippet = tcx.sess.source_map().span_to_snippet(span)
|
||||
|
|
@ -294,7 +295,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
} else {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
item_name.span,
|
||||
E0599,
|
||||
"no {} named `{}` found for type `{}` in the current scope",
|
||||
item_kind,
|
||||
|
|
@ -302,7 +303,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
ty_str
|
||||
);
|
||||
if let Some(suggestion) = suggestion {
|
||||
err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion));
|
||||
// enum variant
|
||||
err.help(&format!("did you mean `{}`?", suggestion));
|
||||
}
|
||||
err
|
||||
}
|
||||
|
|
@ -326,7 +328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// If the method name is the name of a field with a function or closure type,
|
||||
// give a helping note that it has to be called as `(x.f)(...)`.
|
||||
if let Some(expr) = rcvr_expr {
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
for (ty, _) in self.autoderef(span, rcvr_ty) {
|
||||
if let ty::Adt(def, substs) = ty.sty {
|
||||
if !def.is_enum() {
|
||||
|
|
@ -377,10 +379,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(expr) = rcvr_expr {
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
|
||||
report_function!(expr.span, expr_string);
|
||||
} else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) =
|
||||
} else if let ExprKind::Path(QPath::Resolved(_, ref path)) =
|
||||
expr.node
|
||||
{
|
||||
if let Some(segment) = path.segments.last() {
|
||||
|
|
@ -396,7 +398,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
err.span_label(span, "this is an associated function, not a method");
|
||||
}
|
||||
if static_sources.len() == 1 {
|
||||
if let Some(expr) = rcvr_expr {
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
err.span_suggestion_with_applicability(expr.span.to(span),
|
||||
"use associated function syntax instead",
|
||||
format!("{}::{}",
|
||||
|
|
@ -433,7 +435,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
span,
|
||||
rcvr_ty,
|
||||
item_name,
|
||||
rcvr_expr,
|
||||
source,
|
||||
out_of_scope_traits);
|
||||
}
|
||||
|
||||
|
|
@ -571,18 +573,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn suggest_traits_to_import(&self,
|
||||
err: &mut DiagnosticBuilder,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: ast::Ident,
|
||||
rcvr_expr: Option<&hir::Expr>,
|
||||
valid_out_of_scope_traits: Vec<DefId>) {
|
||||
fn suggest_traits_to_import<'b>(&self,
|
||||
err: &mut DiagnosticBuilder,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: ast::Ident,
|
||||
source: SelfSource<'b>,
|
||||
valid_out_of_scope_traits: Vec<DefId>) {
|
||||
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
|
||||
return;
|
||||
}
|
||||
|
||||
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr);
|
||||
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
|
||||
|
||||
// There are no traits implemented, so lets suggest some traits to
|
||||
// implement, by finding ones that have the item name, and are
|
||||
|
|
@ -663,7 +665,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// This occurs for UFCS desugaring of `T::method`, where there is no
|
||||
// receiver expression for the method call, and thus no autoderef.
|
||||
if rcvr_expr.is_none() {
|
||||
if let SelfSource::QPath(_) = source {
|
||||
return is_local(self.resolve_type_vars_with_obligations(rcvr_ty));
|
||||
}
|
||||
|
||||
|
|
@ -671,6 +673,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum SelfSource<'a> {
|
||||
QPath(&'a hir::Ty),
|
||||
MethodCall(&'a hir::Expr /* rcvr */),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TraitInfo {
|
||||
pub def_id: DefId,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ use self::autoderef::Autoderef;
|
|||
use self::callee::DeferredCallResolution;
|
||||
use self::coercion::{CoerceMany, DynamicCoerceMany};
|
||||
pub use self::compare_method::{compare_impl_method, compare_const_impl};
|
||||
use self::method::MethodCallee;
|
||||
use self::method::{MethodCallee, SelfSource};
|
||||
use self::TupleArgumentsFlag::*;
|
||||
|
||||
/// The type of a local binding, including the revealed type for anon types.
|
||||
|
|
@ -3244,7 +3244,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
self.report_method_error(span,
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
Some(rcvr),
|
||||
SelfSource::MethodCall(rcvr),
|
||||
error,
|
||||
Some(args));
|
||||
}
|
||||
|
|
@ -4558,7 +4558,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
span: Span)
|
||||
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
|
||||
{
|
||||
let (ty, ty_hir, item_segment) = match *qpath {
|
||||
let (ty, qself, item_segment) = match *qpath {
|
||||
hir::QPath::Resolved(ref opt_qself, ref path) => {
|
||||
return (path.def,
|
||||
opt_qself.as_ref().map(|qself| self.to_ty(qself)),
|
||||
|
|
@ -4575,7 +4575,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
return (*cached_def, Some(ty), slice::from_ref(&**item_segment))
|
||||
}
|
||||
let item_name = item_segment.ident;
|
||||
let def = match self.resolve_ufcs(span, item_name, ty, ty_hir, node_id) {
|
||||
let def = match self.resolve_ufcs(span, item_name, ty, qself, node_id) {
|
||||
Ok(def) => def,
|
||||
Err(error) => {
|
||||
let def = match error {
|
||||
|
|
@ -4583,7 +4583,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
_ => Def::Err,
|
||||
};
|
||||
if item_name.name != keywords::Invalid.name() {
|
||||
self.report_method_error(span, ty, item_name, None, error, None);
|
||||
self.report_method_error(span,
|
||||
ty,
|
||||
item_name,
|
||||
SelfSource::QPath(qself),
|
||||
error,
|
||||
None);
|
||||
}
|
||||
def
|
||||
}
|
||||
|
|
@ -5114,7 +5119,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// Case 2. Reference to a variant constructor.
|
||||
Def::VariantCtor(def_id, ..) => {
|
||||
if tcx.features().type_alias_enum_variants {
|
||||
if self.tcx.features().type_alias_enum_variants {
|
||||
let adt_def = self_ty.and_then(|t| t.ty_adt_def());
|
||||
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
|
||||
debug_assert!(adt_def.is_enum());
|
||||
|
|
@ -5192,16 +5197,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
node_id,
|
||||
);
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
let path_segs = self.def_ids_for_path_segments(segments, self_ty, def);
|
||||
|
||||
let mut user_self_ty = None;
|
||||
match def {
|
||||
Def::Method(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let container = self.tcx.associated_item(def_id).container;
|
||||
let container = tcx.associated_item(def_id).container;
|
||||
match container {
|
||||
ty::TraitContainer(trait_did) => {
|
||||
callee::check_legal_trait_for_method_call(self.tcx, span, trait_did)
|
||||
callee::check_legal_trait_for_method_call(tcx, span, trait_did)
|
||||
}
|
||||
ty::ImplContainer(impl_def_id) => {
|
||||
if segments.len() == 1 {
|
||||
|
|
@ -5231,7 +5238,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
match def {
|
||||
Def::VariantCtor(_, _) if self_ty.is_some() => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
|
@ -5249,7 +5256,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Def::Local(nid) | Def::Upvar(nid, ..) => {
|
||||
let ty = self.local_ty(span, nid).decl_ty;
|
||||
let ty = self.normalize_associated_types_in(span, &ty);
|
||||
self.write_ty(self.tcx.hir().node_to_hir_id(node_id), ty);
|
||||
self.write_ty(tcx.hir().node_to_hir_id(node_id), ty);
|
||||
return (ty, def);
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -5265,13 +5272,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let mut infer_args_for_err = FxHashSet::default();
|
||||
for &PathSeg(def_id, index) in &path_segs {
|
||||
let seg = &segments[index];
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
// Argument-position `impl Trait` is treated as a normal generic
|
||||
// parameter internally, but we don't allow users to specify the
|
||||
// parameter's value explicitly, so we have to do some error-
|
||||
// checking here.
|
||||
let suppress_errors = AstConv::check_generic_arg_count_for_call(
|
||||
self.tcx,
|
||||
tcx,
|
||||
span,
|
||||
&generics,
|
||||
&seg,
|
||||
|
|
@ -5284,7 +5291,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
|
||||
self.tcx.generics_of(*def_id).has_self
|
||||
tcx.generics_of(*def_id).has_self
|
||||
}).unwrap_or(false);
|
||||
|
||||
let mut new_def = def;
|
||||
|
|
@ -5297,10 +5304,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Some(adt_def) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
|
||||
(variant.did, self.tcx.type_of(variant.did))
|
||||
(variant.did, tcx.type_of(variant.did))
|
||||
}
|
||||
_ => {
|
||||
let mut err = self.tcx.sess.struct_span_err(span,
|
||||
let mut err = tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
|
|
@ -5318,14 +5325,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
err.emit();
|
||||
|
||||
(impl_def_id, self.tcx.types.err)
|
||||
(impl_def_id, tcx.types.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Def::VariantCtor(_, _) if self_ty.is_some() => {
|
||||
let def_id = def.def_id();
|
||||
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
let ty = tcx.type_of(def_id);
|
||||
if tcx.features().type_alias_enum_variants {
|
||||
if let Some(self_ty) = self_ty {
|
||||
match ty.ty_adt_def() {
|
||||
|
|
@ -5343,13 +5350,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
let ty = tcx.type_of(def_id);
|
||||
(def_id, ty)
|
||||
}
|
||||
};
|
||||
|
||||
let substs = AstConv::create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
tcx,
|
||||
def_id,
|
||||
&[][..],
|
||||
has_self,
|
||||
|
|
@ -5395,10 +5402,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// If we have a default, then we it doesn't matter that we're not
|
||||
// inferring the type arguments: we provide the default where any
|
||||
// is missing.
|
||||
let default = self.tcx.type_of(param.def_id);
|
||||
let default = tcx.type_of(param.def_id);
|
||||
self.normalize_ty(
|
||||
span,
|
||||
default.subst_spanned(self.tcx, substs.unwrap(), Some(span))
|
||||
default.subst_spanned(tcx, substs.unwrap(), Some(span))
|
||||
).into()
|
||||
} else {
|
||||
// If no type arguments were provided, we have to infer them.
|
||||
|
|
@ -5415,7 +5422,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
// First, store the "user substs" for later.
|
||||
let hir_id = self.tcx.hir().node_to_hir_id(node_id);
|
||||
let hir_id = tcx.hir().node_to_hir_id(node_id);
|
||||
self.write_user_substs_from_substs(hir_id, substs, user_self_ty);
|
||||
|
||||
// Add all the obligations that are required, substituting and
|
||||
|
|
@ -5434,7 +5441,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// is inherent, there is no `Self` parameter, instead, the impl needs
|
||||
// type parameters, which we can infer by unifying the provided `Self`
|
||||
// with the substituted impl type.
|
||||
let ty = self.tcx.type_of(impl_def_id);
|
||||
let ty = tcx.type_of(impl_def_id);
|
||||
|
||||
let impl_ty = self.instantiate_type_scheme(span, &substs, &ty);
|
||||
match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) {
|
||||
|
|
|
|||
|
|
@ -132,12 +132,12 @@ pub struct TypeAndSubsts<'tcx> {
|
|||
}
|
||||
|
||||
fn allow_type_alias_enum_variants<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
ty_hir: &hir::Ty,
|
||||
qself: &hir::Ty,
|
||||
span: Span) -> bool {
|
||||
let allow_feature = tcx.features().type_alias_enum_variants;
|
||||
if !allow_feature {
|
||||
// Only print error if we know the type is an alias.
|
||||
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ty_hir.node {
|
||||
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = qself.node {
|
||||
if let Def::TyAlias(_) = path.def {
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
span,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue