From 797eff974d99f820f4092374e49fc9e55a71347b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Jan 2019 23:23:30 +0300 Subject: [PATCH 1/2] Revert "Changed resolution of enum variants to low priority." This reverts commit 5adf8c358ad70f9a50536a0bd47f938cb0aaea18. --- src/librustc_typeck/astconv.rs | 36 +++++++------- src/librustc_typeck/check/method/mod.rs | 63 +++++++++++-------------- 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8e5eaa18b9de0..3aaa743b7e477 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1298,11 +1298,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(slice::from_ref(item_segment)); + // Check if we have an enum variant here. + match ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + 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 { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::Variant(variant_def.did); + tcx.check_stability(def.def_id(), Some(ref_id), span); + return (ty, def); + } + }, + _ => (), + } + // Find the type of the associated item, and the trait where the associated // item is declared. let bound = match (&ty.sty, ty_path_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { - // `Self` in an impl of a trait -- we have a concrete self type and a + // `Self` in an impl of a trait -- we have a concrete `self` type and a // trait reference. let trait_ref = match tcx.impl_trait_ref(impl_def_id) { Some(trait_ref) => trait_ref, @@ -1354,23 +1371,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { return (tcx.types.err, Def::Err); } _ => { - // Check if we have an enum variant. - match ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - 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 { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); - } - }, - _ => (), - } - // Don't print `TyErr` to the user. if !ty.references_error() { self.report_ambiguous_associated_type(span, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 02687df6a94fc..cacd486b6cb45 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -408,45 +408,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - let mode = probe::Mode::Path; - match self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope) { - Ok(pick) => { - debug!("resolve_ufcs: pick={:?}", pick); - if let Some(import_id) = pick.import_id { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + // Check if we have an enum variant here. + match self_ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + 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 { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); } + }, + _ => (), + } - let def = pick.item.def(); - debug!("resolve_ufcs: def={:?}", def); - tcx.check_stability(def.def_id(), Some(expr_id), span); - - Ok(def) - } - Err(err) => { - // Check if we have an enum variant. - match self_ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - 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 { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - tcx.check_stability(def.def_id(), Some(expr_id), span); - return Ok(def); - } - }, - _ => (), - } + let mode = probe::Mode::Path; + let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope)?; - Err(err) - } + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } + + let def = pick.item.def(); + tcx.check_stability(def.def_id(), Some(expr_id), span); + + Ok(def) } /// Find item with name `item_name` defined in impl/trait `def_id` From dcaebe0c2f82063073c19afa37e031fab2d8e8ce Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 11 Jan 2019 00:48:21 +0300 Subject: [PATCH 2/2] [WIP] High priority resolutions for associated variants --- src/librustc/lint/builtin.rs | 7 ++++ src/librustc_typeck/astconv.rs | 23 +++++++++---- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/lib.rs | 30 ++++++++-------- .../feature-gate-type_alias_enum_variants.rs | 2 ++ ...ature-gate-type_alias_enum_variants.stderr | 34 ------------------- .../ui/type-alias-enum-variants-priority-2.rs | 13 +++++++ ...type-alias-enum-variants-priority-2.stderr | 12 +++++++ .../ui/type-alias-enum-variants-priority.rs | 17 ++++++++++ .../type-alias-enum-variants-priority.stderr | 10 ++++++ 10 files changed, 94 insertions(+), 56 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 22854382df15c..ca17dccaac3d7 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -149,6 +149,12 @@ declare_lint! { "safe access to extern statics was erroneously allowed" } +declare_lint! { + pub TYPE_VS_VARIANT_AMBIGUITY, + Forbid, + "type vs variant ambiguity" +} + declare_lint! { pub SAFE_PACKED_BORROWS, Warn, @@ -400,6 +406,7 @@ impl LintPass for HardwiredLints { CONST_ERR, RENAMED_AND_REMOVED_LINTS, SAFE_EXTERN_STATICS, + TYPE_VS_VARIANT_AMBIGUITY, SAFE_PACKED_BORROWS, PATTERNS_IN_FNS_WITHOUT_BODY, LEGACY_DIRECTORY_OWNERSHIP, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3aaa743b7e477..1e1b430ed9f7b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1288,7 +1288,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { span: Span, ty: Ty<'tcx>, ty_path_def: Def, - item_segment: &hir::PathSegment) + item_segment: &hir::PathSegment, + permit_variants: bool) -> (Ty<'tcx>, Def) { let tcx = self.tcx(); @@ -1305,11 +1306,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) }); if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); + if permit_variants { + check_type_alias_enum_variants_enabled(tcx, span); - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); + let def = Def::Variant(variant_def.did); + tcx.check_stability(def.def_id(), Some(ref_id), span); + return (ty, def); + } else { + use rustc::lint::builtin::TYPE_VS_VARIANT_AMBIGUITY; + tcx.lint_node( + TYPE_VS_VARIANT_AMBIGUITY, + ref_id, + span, + "type vs variant ambiguity", + ); + } } }, _ => (), @@ -1773,7 +1784,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 + self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1a5d164873d32..86ff5b1ea72b9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4623,7 +4623,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Err }; let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, def, segment); + ty, def, segment, true); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c55a1258ce955..2e5d18b19c600 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -111,7 +111,7 @@ use rustc::infer::InferOk; use rustc::lint; use rustc::middle; use rustc::session; -use rustc::session::config::nightly_options; +// use rustc::session::config::nightly_options; use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; @@ -130,20 +130,20 @@ pub struct TypeAndSubsts<'tcx> { ty: Ty<'tcx>, } -fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - span: Span) { - if !tcx.features().type_alias_enum_variants { - let mut err = tcx.sess.struct_span_err( - span, - "enum variants on type aliases are experimental" - ); - if nightly_options::is_nightly_build() { - help!(&mut err, - "add `#![feature(type_alias_enum_variants)]` to the \ - crate attributes to enable"); - } - err.emit(); - } +fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>, + _span: Span) { + // if !tcx.features().type_alias_enum_variants { + // let mut err = tcx.sess.struct_span_err( + // span, + // "enum variants on type aliases are experimental" + // ); + // if nightly_options::is_nightly_build() { + // help!(&mut err, + // "add `#![feature(type_alias_enum_variants)]` to the \ + // crate attributes to enable"); + // } + // err.emit(); + // } } fn require_c_abi_if_variadic(tcx: TyCtxt, diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs index 8997c1824ca6d..7dfbb4cb37093 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-pass + enum Foo { Bar(i32), Baz { i: i32 }, diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr deleted file mode 100644 index cba643e18ca1a..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:19:13 - | -LL | let t = Alias::Bar(0); - | ^^^^^^^^^^ - | - = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable - -error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:21:13 - | -LL | let t = Alias::Baz { i: 0 }; - | ^^^^^^^^^^ - | - = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable - -error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:24:9 - | -LL | Alias::Bar(_i) => {} - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable - -error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:26:9 - | -LL | Alias::Baz { i: _i } => {} - | ^^^^^^^^^^ - | - = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs new file mode 100644 index 0000000000000..295f8acf62f85 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V(u8) +} + +impl E { + fn V() {} +} + +fn main() { + ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied +} diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr new file mode 100644 index 0000000000000..c6ec96ebb7d3b --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr @@ -0,0 +1,12 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/type-alias-enum-variants-priority-2.rs:12:5 + | +LL | V(u8) + | ----- defined here +... +LL | ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^^^^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs new file mode 100644 index 0000000000000..e93c79a5366d1 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V(u8) +} + +trait Tr { + type V; + fn f() -> Self::V; +} + +impl Tr for E { + type V = u8; + fn f() -> Self::V { loop {} } //~ ERROR type vs variant ambiguity +} + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr new file mode 100644 index 0000000000000..0222ff63fbda3 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.stderr @@ -0,0 +1,10 @@ +error: type vs variant ambiguity + --> $DIR/type-alias-enum-variants-priority.rs:14:15 + | +LL | fn f() -> Self::V { loop {} } //~ ERROR type vs variant ambiguity + | ^^^^^^^ + | + = note: #[forbid(type_vs_variant_ambiguity)] on by default + +error: aborting due to previous error +