Skip to content

Commit ea9517e

Browse files
committed
don't normalize in astconv
We delay projection normalization to further stages in order to register user type annotations before normalization in HIR typeck. There are two consumers of astconv: ItemCtxt and FnCtxt. The former already expects unnormalized types from astconv, see its AstConv trait impl. The latter needs `RawTy` for a cleaner interface. Unfortunately astconv still needs the normalization machinery in order to resolve enum variants that have projections in the self type, e.g. `<<T as Trait>::Assoc>::StructVariant {}`. This is why `AstConv::normalize_ty_2` is necessary.
1 parent a78c9be commit ea9517e

File tree

25 files changed

+380
-254
lines changed

25 files changed

+380
-254
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

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

111-
/// Normalize an associated type coming from the user.
112-
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
111+
fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
112+
ty
113+
}
113114

114115
/// Invoked when we encounter an error from some prior pass
115116
/// (e.g., resolve) that is translated into a ty-error. This is
@@ -484,12 +485,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
484485
// Avoid ICE #86756 when type error recovery goes awry.
485486
return tcx.ty_error().into();
486487
}
487-
self.astconv
488-
.normalize_ty(
489-
self.span,
490-
EarlyBinder(tcx.at(self.span).type_of(param.def_id))
491-
.subst(tcx, substs),
492-
)
488+
EarlyBinder(tcx.at(self.span).type_of(param.def_id))
489+
.subst(tcx, substs)
493490
.into()
494491
} else if infer_args {
495492
self.astconv.ty_infer(Some(param), self.span).into()
@@ -1254,10 +1251,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12541251
item_segment: &hir::PathSegment<'_>,
12551252
) -> Ty<'tcx> {
12561253
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
1257-
self.normalize_ty(
1258-
span,
1259-
EarlyBinder(self.tcx().at(span).type_of(did)).subst(self.tcx(), substs),
1260-
)
1254+
EarlyBinder(self.tcx().at(span).type_of(did)).subst(self.tcx(), substs)
12611255
}
12621256

12631257
fn conv_object_ty_poly_trait_ref(
@@ -1789,7 +1783,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17891783
Ok(bound)
17901784
}
17911785

1792-
// Create a type from a path to an associated type.
1786+
// Create a type from a path to an associated type or to an enum variant.
17931787
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
17941788
// and item_segment is the path segment for `D`. We return a type and a def for
17951789
// the whole path.
@@ -1817,7 +1811,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18171811

18181812
// Check if we have an enum variant.
18191813
let mut variant_resolution = None;
1820-
if let ty::Adt(adt_def, _) = qself_ty.kind() {
1814+
if let ty::Adt(adt_def, _) = self.normalize_ty_2(span, qself_ty).kind() {
18211815
if adt_def.is_enum() {
18221816
let variant_def = adt_def
18231817
.variants()
@@ -2017,7 +2011,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20172011
};
20182012

20192013
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
2020-
let ty = self.normalize_ty(span, ty);
20212014

20222015
if let Some(variant_def_id) = variant_resolution {
20232016
tcx.struct_span_lint_hir(
@@ -2153,7 +2146,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
21532146

21542147
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
21552148

2156-
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
2149+
tcx.mk_projection(item_def_id, item_substs)
21572150
}
21582151

21592152
pub fn prohibit_generics<'a>(
@@ -2391,6 +2384,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23912384
}
23922385

23932386
// Check a type `Path` and convert it to a `Ty`.
2387+
// If the path is an enum variant the returned type is the type of the enum.
23942388
pub fn res_to_ty(
23952389
&self,
23962390
opt_self_ty: Option<Ty<'tcx>>,
@@ -2414,7 +2408,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
24142408
err.note("`impl Trait` types can't have type parameters");
24152409
});
24162410
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
2417-
self.normalize_ty(span, tcx.mk_opaque(did, substs))
2411+
tcx.mk_opaque(did, substs)
24182412
}
24192413
Res::Def(
24202414
DefKind::Enum
@@ -2574,7 +2568,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25742568
}
25752569
tcx.ty_error_with_guaranteed(err.emit())
25762570
} else {
2577-
self.normalize_ty(span, ty)
2571+
ty
25782572
}
25792573
}
25802574
Res::Def(DefKind::AssocTy, def_id) => {
@@ -2717,8 +2711,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27172711
None,
27182712
ty::BoundConstness::NotConst,
27192713
);
2720-
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
2721-
.subst(tcx, substs)
2714+
EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
27222715
}
27232716
hir::TyKind::Array(ref ty, ref length) => {
27242717
let length = match length {
@@ -2728,8 +2721,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27282721
}
27292722
};
27302723

2731-
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length));
2732-
self.normalize_ty(ast_ty.span, array_ty)
2724+
tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length))
27332725
}
27342726
hir::TyKind::Typeof(ref e) => {
27352727
let ty_erased = tcx.type_of(e.def_id);

compiler/rustc_hir_analysis/src/collect.rs

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

516-
fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
517-
// Types in item signatures are not normalized to avoid undue dependencies.
518-
ty
519-
}
520-
521516
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
522517
// There's no obvious place to track this, so just let it go.
523518
}

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,14 +621,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
621621
),
622622
bound_vars,
623623
);
624-
// Astconv can't normalize inputs or outputs with escaping bound vars,
625-
// so normalize them here, after we've wrapped them in a binder.
626-
let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result);
627624

628625
let c_result = self.inh.infcx.canonicalize_response(result);
629626
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
630627

631-
result
628+
// Normalize only after registering in `user_provided_sigs`.
629+
self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result)
632630
}
633631

634632
/// Invoked when we are translating the generator that results

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::callee::{self, DeferredCallResolution};
22
use crate::method::{self, MethodCallee, SelfSource};
33
use crate::rvalue_scopes;
4-
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
4+
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
55
use rustc_data_structures::captures::Captures;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
@@ -464,23 +464,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
464464
}
465465
}
466466

467-
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
467+
pub fn create_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
468+
RawTy { raw: ty, normalized: self.normalize_associated_types_in(span, ty) }
469+
}
470+
471+
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
468472
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
469473
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
470-
t
474+
self.create_raw_ty(ast_t.span, t)
471475
}
472476

473477
pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
474478
let ty = self.to_ty(ast_ty);
475479
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
476480

477-
if Self::can_contain_user_lifetime_bounds(ty) {
478-
let c_ty = self.canonicalize_response(UserType::Ty(ty));
481+
if Self::can_contain_user_lifetime_bounds(ty.raw) {
482+
let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
479483
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
480484
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
481485
}
482486

483-
ty
487+
ty.normalized
484488
}
485489

486490
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
@@ -831,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
831835
qpath: &'tcx QPath<'tcx>,
832836
hir_id: hir::HirId,
833837
span: Span,
834-
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
838+
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
835839
debug!(
836840
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
837841
qpath, hir_id, span
@@ -854,23 +858,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
854858
// to be object-safe.
855859
// We manually call `register_wf_obligation` in the success path
856860
// below.
857-
(<dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself), qself, segment)
861+
let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself);
862+
(self.create_raw_ty(span, ty), qself, segment)
858863
}
859864
QPath::LangItem(..) => {
860865
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
861866
}
862867
};
863868
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
864869
{
865-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
870+
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
866871
// Return directly on cache hit. This is useful to avoid doubly reporting
867872
// errors with default match binding modes. See #44614.
868873
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
869874
return (def, Some(ty), slice::from_ref(&**item_segment));
870875
}
871876
let item_name = item_segment.ident;
872877
let result = self
873-
.resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id)
878+
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
874879
.or_else(|error| {
875880
let result = match error {
876881
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
@@ -881,13 +886,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
881886
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
882887
// register a WF obligation so that we can detect any additional
883888
// errors in the self type.
884-
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
885-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
889+
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
890+
self.register_wf_obligation(
891+
ty.raw.into(),
892+
qself.span,
893+
traits::WellFormed(None),
894+
);
886895
}
887896
if item_name.name != kw::Empty {
888897
if let Some(mut e) = self.report_method_error(
889898
span,
890-
ty,
899+
ty.normalized,
891900
item_name,
892901
SelfSource::QPath(qself),
893902
error,
@@ -900,7 +909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
900909
});
901910

902911
if result.is_ok() {
903-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
912+
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
904913
}
905914

906915
// Write back the new resolution.
@@ -1037,17 +1046,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10371046
pub fn instantiate_value_path(
10381047
&self,
10391048
segments: &[hir::PathSegment<'_>],
1040-
self_ty: Option<Ty<'tcx>>,
1049+
self_ty: Option<RawTy<'tcx>>,
10411050
res: Res,
10421051
span: Span,
10431052
hir_id: hir::HirId,
10441053
) -> (Ty<'tcx>, Res) {
10451054
let tcx = self.tcx;
1055+
assert_eq!(res.ns(), Some(rustc_hir::def::Namespace::ValueNS));
10461056

10471057
let path_segs = match res {
10481058
Res::Local(_) | Res::SelfCtor(_) => vec![],
10491059
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
1050-
self, segments, self_ty, kind, def_id,
1060+
self,
1061+
segments,
1062+
self_ty.map(|ty| ty.normalized),
1063+
kind,
1064+
def_id,
10511065
),
10521066
_ => bug!("instantiate_value_path on {:?}", res),
10531067
};
@@ -1058,8 +1072,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10581072
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
10591073
if let Some(self_ty) = self_ty =>
10601074
{
1061-
let adt_def = self_ty.ty_adt_def().unwrap();
1062-
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
1075+
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
1076+
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
10631077
is_alias_variant_ctor = true;
10641078
}
10651079
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
@@ -1078,7 +1092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10781092
// inherent impl, we need to record the
10791093
// `T` for posterity (see `UserSelfTy` for
10801094
// details).
1081-
let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
1095+
let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
10821096
user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
10831097
}
10841098
}
@@ -1160,7 +1174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11601174
.unwrap_or(false);
11611175

11621176
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
1163-
let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id));
1177+
let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id));
11641178
match *ty.kind() {
11651179
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
11661180
let variant = adt_def.non_enum_variant();
@@ -1251,7 +1265,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12511265
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
12521266
}
12531267
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
1254-
self.fcx.to_ty(ty).into()
1268+
self.fcx.to_ty(ty).raw.into()
12551269
}
12561270
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
12571271
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@@ -1285,7 +1299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12851299
// is missing.
12861300
let default = tcx.bound_type_of(param.def_id);
12871301
self.fcx
1288-
.normalize_ty(self.span, default.subst(tcx, substs.unwrap()))
1302+
.normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
12891303
.into()
12901304
} else {
12911305
// If no type arguments were provided, we have to infer them.
@@ -1308,13 +1322,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13081322
}
13091323
}
13101324

1311-
let substs = self_ctor_substs.unwrap_or_else(|| {
1325+
let substs_raw = self_ctor_substs.unwrap_or_else(|| {
13121326
<dyn AstConv<'_>>::create_substs_for_generic_args(
13131327
tcx,
13141328
def_id,
13151329
&[],
13161330
has_self,
1317-
self_ty,
1331+
self_ty.map(|s| s.raw),
13181332
&arg_count,
13191333
&mut CreateCtorSubstsContext {
13201334
fcx: self,
@@ -1325,11 +1339,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13251339
},
13261340
)
13271341
});
1328-
assert!(!substs.has_escaping_bound_vars());
1342+
assert!(!substs_raw.has_escaping_bound_vars());
13291343
assert!(!ty.has_escaping_bound_vars());
13301344

13311345
// First, store the "user substs" for later.
1332-
self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
1346+
self.write_user_type_annotation_from_substs(hir_id, def_id, substs_raw, user_self_ty);
1347+
1348+
// Normalize only after registering type annotations.
1349+
let substs = self.normalize_associated_types_in(span, substs_raw);
13331350

13341351
self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
13351352

@@ -1346,6 +1363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13461363
let ty = tcx.type_of(impl_def_id);
13471364

13481365
let impl_ty = self.instantiate_type_scheme(span, &substs, ty);
1366+
let self_ty = self.normalize_associated_types_in(span, self_ty);
13491367
match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
13501368
Ok(ok) => self.register_infer_ok_obligations(ok),
13511369
Err(_) => {

0 commit comments

Comments
 (0)