Skip to content

Commit 4327a79

Browse files
committed
introduce AstConv::probe_adt
1 parent ea9517e commit 4327a79

File tree

6 files changed

+69
-21
lines changed

6 files changed

+69
-21
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,12 @@ pub trait AstConv<'tcx> {
108108
poly_trait_ref: ty::PolyTraitRef<'tcx>,
109109
) -> Ty<'tcx>;
110110

111-
fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
112-
ty
113-
}
111+
/// Returns `AdtDef` if `ty` is an ADT.
112+
/// Note that `ty` might be a projection type that needs normalization.
113+
/// This used to get the enum variants in scope of the type.
114+
/// For example, `Self::A` could refer to an associated type
115+
/// or to an enum variant depending on the result of this function.
116+
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
114117

115118
/// Invoked when we encounter an error from some prior pass
116119
/// (e.g., resolve) that is translated into a ty-error. This is
@@ -1811,7 +1814,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18111814

18121815
// Check if we have an enum variant.
18131816
let mut variant_resolution = None;
1814-
if let ty::Adt(adt_def, _) = self.normalize_ty_2(span, qself_ty).kind() {
1817+
if let Some(adt_def) = self.probe_adt(span, qself_ty) {
18151818
if adt_def.is_enum() {
18161819
let variant_def = adt_def
18171820
.variants()
@@ -2263,6 +2266,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22632266
self_ty: Option<Ty<'tcx>>,
22642267
kind: DefKind,
22652268
def_id: DefId,
2269+
span: Span,
22662270
) -> Vec<PathSeg> {
22672271
// We need to extract the type parameters supplied by the user in
22682272
// the path `path`. Due to the current setup, this is a bit of a
@@ -2330,8 +2334,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23302334

23312335
// Case 2. Reference to a variant constructor.
23322336
DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
2333-
let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
2334-
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
2337+
let (generics_def_id, index) = if let Some(self_ty) = self_ty {
2338+
let adt_def = self.probe_adt(span, self_ty).unwrap();
23352339
debug_assert!(adt_def.is_enum());
23362340
(adt_def.did(), last)
23372341
} else if last >= 1 && segments[last - 1].args.is_some() {
@@ -2428,7 +2432,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
24282432
assert_eq!(opt_self_ty, None);
24292433

24302434
let path_segs =
2431-
self.def_ids_for_value_path_segments(path.segments, None, kind, def_id);
2435+
self.def_ids_for_value_path_segments(path.segments, None, kind, def_id, span);
24322436
let generic_segs: FxHashSet<_> =
24332437
path_segs.iter().map(|PathSeg(_, index)| index).collect();
24342438
self.prohibit_generics(

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,12 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
513513
}
514514
}
515515

516+
fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
517+
// FIXME(aliemjay): We should handle the case where `ty` is a projection,
518+
// but we currently don't. See #103640.
519+
ty.ty_adt_def()
520+
}
521+
516522
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
517523
// There's no obvious place to track this, so just let it go.
518524
}

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,9 +1059,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10591059
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
10601060
self,
10611061
segments,
1062-
self_ty.map(|ty| ty.normalized),
1062+
self_ty.map(|ty| ty.raw),
10631063
kind,
10641064
def_id,
1065+
span,
10651066
),
10661067
_ => bug!("instantiate_value_path on {:?}", res),
10671068
};
@@ -1174,7 +1175,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11741175
.unwrap_or(false);
11751176

11761177
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
1177-
let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id));
1178+
let ty = tcx.at(span).type_of(impl_def_id);
1179+
let ty = self.normalize_associated_types_in(span, ty);
11781180
match *ty.kind() {
11791181
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
11801182
let variant = adt_def.non_enum_variant();
@@ -1297,10 +1299,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12971299
// If we have a default, then we it doesn't matter that we're not
12981300
// inferring the type arguments: we provide the default where any
12991301
// is missing.
1300-
let default = tcx.bound_type_of(param.def_id);
1301-
self.fcx
1302-
.normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
1303-
.into()
1302+
let default =
1303+
tcx.bound_type_of(param.def_id).subst(tcx, substs.unwrap());
1304+
self.fcx.normalize_associated_types_in(self.span, default).into()
13041305
} else {
13051306
// If no type arguments were provided, we have to infer them.
13061307
// This case also occurs as a result of some malformed input, e.g.

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
1717
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1818
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
1919
use rustc_middle::ty::subst::GenericArgKind;
20-
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
20+
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
2121
use rustc_session::Session;
2222
use rustc_span::symbol::Ident;
2323
use rustc_span::{self, Span};
@@ -281,12 +281,15 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
281281
self.tcx().mk_projection(item_def_id, item_substs)
282282
}
283283

284-
fn normalize_ty_2(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
285-
use rustc_middle::ty::TypeVisitable;
286-
if ty.has_escaping_bound_vars() {
287-
ty // FIXME: normalization and escaping regions
288-
} else {
289-
self.normalize_associated_types_in(span, ty)
284+
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
285+
match ty.kind() {
286+
ty::Adt(adt_def, _) => Some(*adt_def),
287+
// FIXME: We should normalize even with escaping bound vars.
288+
// See test/ui/associated-types/bound-region-variant-resolution.rs
289+
ty::Projection(_) if !ty.has_escaping_bound_vars() => {
290+
self.normalize_associated_types_in(span, ty).ty_adt_def()
291+
}
292+
_ => None,
290293
}
291294
}
292295

@@ -295,7 +298,11 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
295298
}
296299

297300
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
298-
self.write_ty(hir_id, self.normalize_ty_2(span, ty))
301+
let ty_normalized = match ty.has_escaping_bound_vars() {
302+
false => self.normalize_associated_types_in(span, ty),
303+
true => ty, // FIXME: normalization and escaping regions
304+
};
305+
self.write_ty(hir_id, ty_normalized)
299306
}
300307
}
301308

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This is a bug!
2+
// We should emit the same error message regardless of
3+
// whether the projection type contains bound regions.
4+
5+
// check-fail
6+
7+
fn test<'x>() {
8+
use std::ops::Deref;
9+
None::<for<'y> fn(<&'x Option<()> as Deref>::Target::Some)>;
10+
//~^ ERROR expected type, found variant
11+
None::<for<'y> fn(<&'y Option<()> as Deref>::Target::Some)>;
12+
//~^ ERROR ambiguous associated type
13+
}
14+
15+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: expected type, found variant `Some`
2+
--> $DIR/bound-region-variant-resolution.rs:9:23
3+
|
4+
LL | None::<for<'y> fn(<&'x Option<()> as Deref>::Target::Some)>;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0223]: ambiguous associated type
8+
--> $DIR/bound-region-variant-resolution.rs:11:23
9+
|
10+
LL | None::<for<'y> fn(<&'y Option<()> as Deref>::Target::Some)>;
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<&'y Option<()> as Deref>::Target as Trait>::Some`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)