Skip to content

Commit d227506

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 93bf84c commit d227506

File tree

25 files changed

+376
-257
lines changed

25 files changed

+376
-257
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

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

109-
/// Normalize an associated type coming from the user.
110-
///
111-
/// This should only be used by astconv. Use `FnCtxt::normalize`
112-
/// or `ObligationCtxt::normalize` in downstream crates.
113-
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
109+
fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
110+
ty
111+
}
114112

115113
/// Invoked when we encounter an error from some prior pass
116114
/// (e.g., resolve) that is translated into a ty-error. This is
@@ -485,14 +483,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
485483
// Avoid ICE #86756 when type error recovery goes awry.
486484
return tcx.ty_error().into();
487485
}
488-
self.astconv
489-
.normalize_ty(
490-
self.span,
491-
tcx.at(self.span)
492-
.bound_type_of(param.def_id)
493-
.subst(tcx, substs),
494-
)
495-
.into()
486+
tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into()
496487
} else if infer_args {
497488
self.astconv.ty_infer(Some(param), self.span).into()
498489
} else {
@@ -1254,7 +1245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12541245
item_segment: &hir::PathSegment<'_>,
12551246
) -> Ty<'tcx> {
12561247
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
1257-
self.normalize_ty(span, self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs))
1248+
self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)
12581249
}
12591250

12601251
fn conv_object_ty_poly_trait_ref(
@@ -1786,7 +1777,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17861777
Ok(bound)
17871778
}
17881779

1789-
// Create a type from a path to an associated type.
1780+
// Create a type from a path to an associated type or to an enum variant.
17901781
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
17911782
// and item_segment is the path segment for `D`. We return a type and a def for
17921783
// the whole path.
@@ -1814,7 +1805,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18141805

18151806
// Check if we have an enum variant.
18161807
let mut variant_resolution = None;
1817-
if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() {
1808+
if let ty::Adt(adt_def, adt_substs) = self.normalize_ty_2(span, qself_ty).kind() {
18181809
if adt_def.is_enum() {
18191810
let variant_def = adt_def
18201811
.variants()
@@ -1923,7 +1914,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
19231914
adt_substs,
19241915
);
19251916
let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
1926-
let ty = self.normalize_ty(span, ty);
19271917
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
19281918
}
19291919
}
@@ -2020,7 +2010,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20202010
};
20212011

20222012
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
2023-
let ty = self.normalize_ty(span, ty);
20242013

20252014
if let Some(variant_def_id) = variant_resolution {
20262015
tcx.struct_span_lint_hir(
@@ -2156,7 +2145,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
21562145

21572146
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
21582147

2159-
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
2148+
tcx.mk_projection(item_def_id, item_substs)
21602149
}
21612150

21622151
pub fn prohibit_generics<'a>(
@@ -2417,7 +2406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
24172406
err.note("`impl Trait` types can't have type parameters");
24182407
});
24192408
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
2420-
self.normalize_ty(span, tcx.mk_opaque(did, substs))
2409+
tcx.mk_opaque(did, substs)
24212410
}
24222411
Res::Def(
24232412
DefKind::Enum
@@ -2577,7 +2566,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25772566
}
25782567
tcx.ty_error_with_guaranteed(err.emit())
25792568
} else {
2580-
self.normalize_ty(span, ty)
2569+
ty
25812570
}
25822571
}
25832572
Res::Def(DefKind::AssocTy, def_id) => {
@@ -2720,8 +2709,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27202709
None,
27212710
ty::BoundConstness::NotConst,
27222711
);
2723-
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
2724-
.subst(tcx, substs)
2712+
EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
27252713
}
27262714
hir::TyKind::Array(ref ty, ref length) => {
27272715
let length = match length {
@@ -2731,8 +2719,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27312719
}
27322720
};
27332721

2734-
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length));
2735-
self.normalize_ty(ast_ty.span, array_ty)
2722+
tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length))
27362723
}
27372724
hir::TyKind::Typeof(ref e) => {
27382725
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
@@ -505,11 +505,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
505505
}
506506
}
507507

508-
fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
509-
// Types in item signatures are not normalized to avoid undue dependencies.
510-
ty
511-
}
512-
513508
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
514509
// There's no obvious place to track this, so just let it go.
515510
}

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -647,14 +647,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
647647
),
648648
bound_vars,
649649
);
650-
// Astconv can't normalize inputs or outputs with escaping bound vars,
651-
// so normalize them here, after we've wrapped them in a binder.
652-
let result = self.normalize(self.tcx.hir().span(hir_id), result);
653650

654651
let c_result = self.inh.infcx.canonicalize_response(result);
655652
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
656653

657-
result
654+
// Normalize only after registering in `user_provided_sigs`.
655+
self.normalize(self.tcx.hir().span(hir_id), result)
658656
}
659657

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

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 42 additions & 25 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};
@@ -410,23 +410,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
410410
}
411411
}
412412

413-
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
413+
pub fn create_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
414+
RawTy { raw: ty, normalized: self.normalize(span, ty) }
415+
}
416+
417+
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
414418
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
415419
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
416-
t
420+
self.create_raw_ty(ast_t.span, t)
417421
}
418422

419423
pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
420424
let ty = self.to_ty(ast_ty);
421425
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
422426

423-
if Self::can_contain_user_lifetime_bounds(ty) {
424-
let c_ty = self.canonicalize_response(UserType::Ty(ty));
427+
if Self::can_contain_user_lifetime_bounds(ty.raw) {
428+
let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
425429
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
426430
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
427431
}
428432

429-
ty
433+
ty.normalized
430434
}
431435

432436
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
@@ -780,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
780784
qpath: &'tcx QPath<'tcx>,
781785
hir_id: hir::HirId,
782786
span: Span,
783-
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
787+
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
784788
debug!(
785789
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
786790
qpath, hir_id, span
@@ -803,23 +807,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
803807
// to be object-safe.
804808
// We manually call `register_wf_obligation` in the success path
805809
// below.
806-
(<dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself), qself, segment)
810+
let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself);
811+
(self.create_raw_ty(span, ty), qself, segment)
807812
}
808813
QPath::LangItem(..) => {
809814
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
810815
}
811816
};
812817
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
813818
{
814-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
819+
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
815820
// Return directly on cache hit. This is useful to avoid doubly reporting
816821
// errors with default match binding modes. See #44614.
817822
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
818823
return (def, Some(ty), slice::from_ref(&**item_segment));
819824
}
820825
let item_name = item_segment.ident;
821826
let result = self
822-
.resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id)
827+
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
823828
.or_else(|error| {
824829
let result = match error {
825830
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
@@ -830,13 +835,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
830835
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
831836
// register a WF obligation so that we can detect any additional
832837
// errors in the self type.
833-
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
834-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
838+
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
839+
self.register_wf_obligation(
840+
ty.raw.into(),
841+
qself.span,
842+
traits::WellFormed(None),
843+
);
835844
}
836845
if item_name.name != kw::Empty {
837846
if let Some(mut e) = self.report_method_error(
838847
span,
839-
ty,
848+
ty.normalized,
840849
item_name,
841850
SelfSource::QPath(qself),
842851
error,
@@ -849,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
849858
});
850859

851860
if result.is_ok() {
852-
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
861+
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
853862
}
854863

855864
// Write back the new resolution.
@@ -986,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
986995
pub fn instantiate_value_path(
987996
&self,
988997
segments: &[hir::PathSegment<'_>],
989-
self_ty: Option<Ty<'tcx>>,
998+
self_ty: Option<RawTy<'tcx>>,
990999
res: Res,
9911000
span: Span,
9921001
hir_id: hir::HirId,
@@ -996,7 +1005,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9961005
let path_segs = match res {
9971006
Res::Local(_) | Res::SelfCtor(_) => vec![],
9981007
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
999-
self, segments, self_ty, kind, def_id,
1008+
self,
1009+
segments,
1010+
self_ty.map(|ty| ty.normalized),
1011+
kind,
1012+
def_id,
10001013
),
10011014
_ => bug!("instantiate_value_path on {:?}", res),
10021015
};
@@ -1007,8 +1020,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10071020
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
10081021
if let Some(self_ty) = self_ty =>
10091022
{
1010-
let adt_def = self_ty.ty_adt_def().unwrap();
1011-
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
1023+
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
1024+
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
10121025
is_alias_variant_ctor = true;
10131026
}
10141027
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
@@ -1027,7 +1040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10271040
// inherent impl, we need to record the
10281041
// `T` for posterity (see `UserSelfTy` for
10291042
// details).
1030-
let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
1043+
let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
10311044
user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
10321045
}
10331046
}
@@ -1109,7 +1122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11091122
.unwrap_or(false);
11101123

11111124
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
1112-
let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id));
1125+
let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id));
11131126
match *ty.kind() {
11141127
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
11151128
let variant = adt_def.non_enum_variant();
@@ -1193,7 +1206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11931206
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
11941207
}
11951208
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
1196-
self.fcx.to_ty(ty).into()
1209+
self.fcx.to_ty(ty).raw.into()
11971210
}
11981211
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
11991212
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@@ -1227,7 +1240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12271240
// is missing.
12281241
let default = tcx.bound_type_of(param.def_id);
12291242
self.fcx
1230-
.normalize_ty(self.span, default.subst(tcx, substs.unwrap()))
1243+
.normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
12311244
.into()
12321245
} else {
12331246
// If no type arguments were provided, we have to infer them.
@@ -1250,13 +1263,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12501263
}
12511264
}
12521265

1253-
let substs = self_ctor_substs.unwrap_or_else(|| {
1266+
let substs_raw = self_ctor_substs.unwrap_or_else(|| {
12541267
<dyn AstConv<'_>>::create_substs_for_generic_args(
12551268
tcx,
12561269
def_id,
12571270
&[],
12581271
has_self,
1259-
self_ty,
1272+
self_ty.map(|s| s.raw),
12601273
&arg_count,
12611274
&mut CreateCtorSubstsContext {
12621275
fcx: self,
@@ -1269,7 +1282,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12691282
});
12701283

12711284
// First, store the "user substs" for later.
1272-
self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
1285+
self.write_user_type_annotation_from_substs(hir_id, def_id, substs_raw, user_self_ty);
1286+
1287+
// Normalize only after registering type annotations.
1288+
let substs = self.normalize(span, substs_raw);
12731289

12741290
self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
12751291

@@ -1287,6 +1303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12871303
// with the substituted impl type.
12881304
// This also occurs for an enum variant on a type alias.
12891305
let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs));
1306+
let self_ty = self.normalize(span, self_ty);
12901307
match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
12911308
Ok(ok) => self.register_infer_ok_obligations(ok),
12921309
Err(_) => {

0 commit comments

Comments
 (0)