Skip to content

Commit 5f78915

Browse files
committed
Auto merge of #57501 - petrochenkov:highvar, r=<try>
[WIP] High priority resolutions for associated variants cc #56225 (comment)
2 parents 6ecad33 + dcaebe0 commit 5f78915

11 files changed

+136
-105
lines changed

src/librustc/lint/builtin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ declare_lint! {
149149
"safe access to extern statics was erroneously allowed"
150150
}
151151

152+
declare_lint! {
153+
pub TYPE_VS_VARIANT_AMBIGUITY,
154+
Forbid,
155+
"type vs variant ambiguity"
156+
}
157+
152158
declare_lint! {
153159
pub SAFE_PACKED_BORROWS,
154160
Warn,
@@ -400,6 +406,7 @@ impl LintPass for HardwiredLints {
400406
CONST_ERR,
401407
RENAMED_AND_REMOVED_LINTS,
402408
SAFE_EXTERN_STATICS,
409+
TYPE_VS_VARIANT_AMBIGUITY,
403410
SAFE_PACKED_BORROWS,
404411
PATTERNS_IN_FNS_WITHOUT_BODY,
405412
LEGACY_DIRECTORY_OWNERSHIP,

src/librustc_typeck/astconv.rs

+31-20
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12881288
span: Span,
12891289
ty: Ty<'tcx>,
12901290
ty_path_def: Def,
1291-
item_segment: &hir::PathSegment)
1291+
item_segment: &hir::PathSegment,
1292+
permit_variants: bool)
12921293
-> (Ty<'tcx>, Def)
12931294
{
12941295
let tcx = self.tcx();
@@ -1298,11 +1299,38 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12981299

12991300
self.prohibit_generics(slice::from_ref(item_segment));
13001301

1302+
// Check if we have an enum variant here.
1303+
match ty.sty {
1304+
ty::Adt(adt_def, _) if adt_def.is_enum() => {
1305+
let variant_def = adt_def.variants.iter().find(|vd| {
1306+
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1307+
});
1308+
if let Some(variant_def) = variant_def {
1309+
if permit_variants {
1310+
check_type_alias_enum_variants_enabled(tcx, span);
1311+
1312+
let def = Def::Variant(variant_def.did);
1313+
tcx.check_stability(def.def_id(), Some(ref_id), span);
1314+
return (ty, def);
1315+
} else {
1316+
use rustc::lint::builtin::TYPE_VS_VARIANT_AMBIGUITY;
1317+
tcx.lint_node(
1318+
TYPE_VS_VARIANT_AMBIGUITY,
1319+
ref_id,
1320+
span,
1321+
"type vs variant ambiguity",
1322+
);
1323+
}
1324+
}
1325+
},
1326+
_ => (),
1327+
}
1328+
13011329
// Find the type of the associated item, and the trait where the associated
13021330
// item is declared.
13031331
let bound = match (&ty.sty, ty_path_def) {
13041332
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
1305-
// `Self` in an impl of a trait -- we have a concrete self type and a
1333+
// `Self` in an impl of a trait -- we have a concrete `self` type and a
13061334
// trait reference.
13071335
let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
13081336
Some(trait_ref) => trait_ref,
@@ -1354,23 +1382,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
13541382
return (tcx.types.err, Def::Err);
13551383
}
13561384
_ => {
1357-
// Check if we have an enum variant.
1358-
match ty.sty {
1359-
ty::Adt(adt_def, _) if adt_def.is_enum() => {
1360-
let variant_def = adt_def.variants.iter().find(|vd| {
1361-
tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
1362-
});
1363-
if let Some(variant_def) = variant_def {
1364-
check_type_alias_enum_variants_enabled(tcx, span);
1365-
1366-
let def = Def::Variant(variant_def.did);
1367-
tcx.check_stability(def.def_id(), Some(ref_id), span);
1368-
return (ty, def);
1369-
}
1370-
},
1371-
_ => (),
1372-
}
1373-
13741385
// Don't print `TyErr` to the user.
13751386
if !ty.references_error() {
13761387
self.report_ambiguous_associated_type(span,
@@ -1773,7 +1784,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
17731784
} else {
17741785
Def::Err
17751786
};
1776-
self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
1787+
self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0
17771788
}
17781789
hir::TyKind::Array(ref ty, ref length) => {
17791790
let length_def_id = tcx.hir().local_def_id(length.id);

src/librustc_typeck/check/method/mod.rs

+28-35
Original file line numberDiff line numberDiff line change
@@ -408,45 +408,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
408408

409409
let tcx = self.tcx;
410410

411-
let mode = probe::Mode::Path;
412-
match self.probe_for_name(span, mode, method_name, IsSuggestion(false),
413-
self_ty, expr_id, ProbeScope::TraitsInScope) {
414-
Ok(pick) => {
415-
debug!("resolve_ufcs: pick={:?}", pick);
416-
if let Some(import_id) = pick.import_id {
417-
let import_def_id = tcx.hir().local_def_id(import_id);
418-
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
419-
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
420-
.unwrap().insert(import_def_id);
411+
// Check if we have an enum variant here.
412+
match self_ty.sty {
413+
ty::Adt(adt_def, _) if adt_def.is_enum() => {
414+
let variant_def = adt_def.variants.iter().find(|vd| {
415+
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
416+
});
417+
if let Some(variant_def) = variant_def {
418+
check_type_alias_enum_variants_enabled(tcx, span);
419+
420+
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
421+
tcx.check_stability(def.def_id(), Some(expr_id), span);
422+
return Ok(def);
421423
}
424+
},
425+
_ => (),
426+
}
422427

423-
let def = pick.item.def();
424-
debug!("resolve_ufcs: def={:?}", def);
425-
tcx.check_stability(def.def_id(), Some(expr_id), span);
426-
427-
Ok(def)
428-
}
429-
Err(err) => {
430-
// Check if we have an enum variant.
431-
match self_ty.sty {
432-
ty::Adt(adt_def, _) if adt_def.is_enum() => {
433-
let variant_def = adt_def.variants.iter().find(|vd| {
434-
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
435-
});
436-
if let Some(variant_def) = variant_def {
437-
check_type_alias_enum_variants_enabled(tcx, span);
438-
439-
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
440-
tcx.check_stability(def.def_id(), Some(expr_id), span);
441-
return Ok(def);
442-
}
443-
},
444-
_ => (),
445-
}
428+
let mode = probe::Mode::Path;
429+
let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false),
430+
self_ty, expr_id, ProbeScope::TraitsInScope)?;
446431

447-
Err(err)
448-
}
432+
if let Some(import_id) = pick.import_id {
433+
let import_def_id = tcx.hir().local_def_id(import_id);
434+
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
435+
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
436+
.unwrap().insert(import_def_id);
449437
}
438+
439+
let def = pick.item.def();
440+
tcx.check_stability(def.def_id(), Some(expr_id), span);
441+
442+
Ok(def)
450443
}
451444

452445
/// Find item with name `item_name` defined in impl/trait `def_id`

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4623,7 +4623,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46234623
Def::Err
46244624
};
46254625
let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span,
4626-
ty, def, segment);
4626+
ty, def, segment, true);
46274627

46284628
// Write back the new resolution.
46294629
let hir_id = self.tcx.hir().node_to_hir_id(node_id);

src/librustc_typeck/lib.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ use rustc::infer::InferOk;
111111
use rustc::lint;
112112
use rustc::middle;
113113
use rustc::session;
114-
use rustc::session::config::nightly_options;
114+
// use rustc::session::config::nightly_options;
115115
use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
116116
use rustc::ty::subst::Substs;
117117
use rustc::ty::{self, Ty, TyCtxt};
@@ -130,20 +130,20 @@ pub struct TypeAndSubsts<'tcx> {
130130
ty: Ty<'tcx>,
131131
}
132132

133-
fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
134-
span: Span) {
135-
if !tcx.features().type_alias_enum_variants {
136-
let mut err = tcx.sess.struct_span_err(
137-
span,
138-
"enum variants on type aliases are experimental"
139-
);
140-
if nightly_options::is_nightly_build() {
141-
help!(&mut err,
142-
"add `#![feature(type_alias_enum_variants)]` to the \
143-
crate attributes to enable");
144-
}
145-
err.emit();
146-
}
133+
fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
134+
_span: Span) {
135+
// if !tcx.features().type_alias_enum_variants {
136+
// let mut err = tcx.sess.struct_span_err(
137+
// span,
138+
// "enum variants on type aliases are experimental"
139+
// );
140+
// if nightly_options::is_nightly_build() {
141+
// help!(&mut err,
142+
// "add `#![feature(type_alias_enum_variants)]` to the \
143+
// crate attributes to enable");
144+
// }
145+
// err.emit();
146+
// }
147147
}
148148

149149
fn require_c_abi_if_variadic(tcx: TyCtxt,

src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-pass
12+
1113
enum Foo {
1214
Bar(i32),
1315
Baz { i: i32 },

src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr

-34
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(type_alias_enum_variants)]
2+
3+
enum E {
4+
V(u8)
5+
}
6+
7+
impl E {
8+
fn V() {}
9+
}
10+
11+
fn main() {
12+
<E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
2+
--> $DIR/type-alias-enum-variants-priority-2.rs:12:5
3+
|
4+
LL | V(u8)
5+
| ----- defined here
6+
...
7+
LL | <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
8+
| ^^^^^^^^ expected 1 parameter
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0061`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(type_alias_enum_variants)]
2+
3+
enum E {
4+
V(u8)
5+
}
6+
7+
trait Tr {
8+
type V;
9+
fn f() -> Self::V;
10+
}
11+
12+
impl Tr for E {
13+
type V = u8;
14+
fn f() -> Self::V { loop {} } //~ ERROR type vs variant ambiguity
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: type vs variant ambiguity
2+
--> $DIR/type-alias-enum-variants-priority.rs:14:15
3+
|
4+
LL | fn f() -> Self::V { loop {} } //~ ERROR type vs variant ambiguity
5+
| ^^^^^^^
6+
|
7+
= note: #[forbid(type_vs_variant_ambiguity)] on by default
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)