Skip to content

Commit 4973567

Browse files
Normalize yeet
1 parent aa8462b commit 4973567

File tree

9 files changed

+109
-76
lines changed

9 files changed

+109
-76
lines changed

Diff for: compiler/rustc_hir_typeck/src/expr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13171317
// Find the type of `e`. Supply hints based on the type we are casting to,
13181318
// if appropriate.
13191319
let t_cast = self.to_ty_saving_user_provided_ty(t);
1320-
let t_cast = self.resolve_vars_if_possible(t_cast);
1320+
// FIXME(-Ztrait-solver): This structural resolve is only here for diagnostics,
1321+
// because we use the TyKind to early return from `CastCheck::new`.
1322+
let t_cast = self.try_structurally_resolve_type(t.span, t_cast);
13211323
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
13221324
let t_expr = self.resolve_vars_if_possible(t_expr);
13231325

@@ -3142,7 +3144,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31423144
fields: &[Ident],
31433145
expr: &'tcx hir::Expr<'tcx>,
31443146
) -> Ty<'tcx> {
3145-
let container = self.to_ty(container).normalized;
3147+
// We only need to normalize in the old solver
3148+
let container = self.normalize(expr.span, self.to_ty(container));
31463149

31473150
let mut field_indices = Vec::with_capacity(fields.len());
31483151
let mut current_container = container;

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+55-34
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::callee::{self, DeferredCallResolution};
22
use crate::errors::CtorIsPrivate;
33
use crate::method::{self, MethodCallee, SelfSource};
44
use crate::rvalue_scopes;
5-
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, RawTy};
5+
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt};
66
use rustc_data_structures::captures::Captures;
77
use rustc_data_structures::fx::FxHashSet;
88
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
@@ -324,6 +324,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
324324
)
325325
}
326326

327+
// FIXME(-Ztrait-solver=next): This could be replaced with `try_structurally_resolve`
328+
// calls after the new trait solver is stable.
329+
/// TODO: I don't know what to call this.
330+
pub(super) fn structurally_normalize_after_astconv(
331+
&self,
332+
span: Span,
333+
value: Ty<'tcx>,
334+
) -> Ty<'tcx> {
335+
match self
336+
.at(&self.misc(span), self.param_env)
337+
.structurally_normalize(value, &mut **self.inh.fulfillment_cx.borrow_mut())
338+
{
339+
Ok(ty) => ty,
340+
Err(errors) => {
341+
let guar = self.err_ctxt().report_fulfillment_errors(&errors);
342+
Ty::new_error(self.tcx, guar)
343+
}
344+
}
345+
}
346+
327347
pub fn require_type_meets(
328348
&self,
329349
ty: Ty<'tcx>,
@@ -374,37 +394,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
374394
}
375395
}
376396

377-
pub fn handle_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
378-
RawTy { raw: ty, normalized: self.normalize(span, ty) }
379-
}
380-
381-
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
397+
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
382398
let t = self.astconv().ast_ty_to_ty(ast_t);
383399
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
384-
self.handle_raw_ty(ast_t.span, t)
400+
t
385401
}
386402

387403
pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
388404
let ty = self.to_ty(ast_ty);
389405
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
390406

391-
if Self::can_contain_user_lifetime_bounds(ty.raw) {
392-
let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
407+
if Self::can_contain_user_lifetime_bounds(ty) {
408+
let c_ty = self.canonicalize_response(UserType::Ty(ty));
393409
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
394410
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
395411
}
396412

397-
ty.normalized
413+
self.normalize(ast_ty.span, ty)
398414
}
399415

400-
pub(super) fn user_args_for_adt(ty: RawTy<'tcx>) -> UserArgs<'tcx> {
401-
match (ty.raw.kind(), ty.normalized.kind()) {
416+
pub(super) fn user_args_for_adt(raw: Ty<'tcx>, normalized: Ty<'tcx>) -> UserArgs<'tcx> {
417+
match (raw.kind(), normalized.kind()) {
402418
(ty::Adt(_, args), _) => UserArgs { args, user_self_ty: None },
403419
(_, ty::Adt(adt, args)) => UserArgs {
404420
args,
405-
user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: ty.raw }),
421+
user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: raw }),
406422
},
407-
_ => bug!("non-adt type {:?}", ty),
423+
_ => bug!("non-adt type {:?}", raw),
408424
}
409425
}
410426

@@ -817,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
817833
qpath: &'tcx QPath<'tcx>,
818834
hir_id: hir::HirId,
819835
span: Span,
820-
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
836+
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
821837
debug!(
822838
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
823839
qpath, hir_id, span
@@ -841,23 +857,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
841857
// We manually call `register_wf_obligation` in the success path
842858
// below.
843859
let ty = self.astconv().ast_ty_to_ty_in_path(qself);
844-
(self.handle_raw_ty(span, ty), qself, segment)
860+
(ty, qself, segment)
845861
}
846862
QPath::LangItem(..) => {
847863
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
848864
}
849865
};
866+
867+
// FIXME(-Ztrait-solver=next): Can use `try_structurally_resolve` after migration.
868+
let normalized =
869+
if !ty.is_ty_var() { self.structurally_normalize_after_astconv(span, ty) } else { ty };
870+
850871
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
851872
{
852-
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
873+
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
853874
// Return directly on cache hit. This is useful to avoid doubly reporting
854875
// errors with default match binding modes. See #44614.
855876
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
856877
return (def, Some(ty), slice::from_ref(&**item_segment));
857878
}
858879
let item_name = item_segment.ident;
859880
let result = self
860-
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
881+
.resolve_fully_qualified_call(span, item_name, normalized, qself.span, hir_id)
861882
.and_then(|r| {
862883
// lint bare trait if the method is found in the trait
863884
if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
@@ -876,14 +897,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
876897
};
877898

878899
let trait_missing_method =
879-
matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
900+
matches!(error, method::MethodError::NoMatch(_)) && normalized.is_trait();
880901
// If we have a path like `MyTrait::missing_method`, then don't register
881902
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
882903
// register a WF obligation so that we can detect any additional
883904
// errors in the self type.
884905
if !trait_missing_method {
885906
self.register_wf_obligation(
886-
ty.raw.into(),
907+
ty.into(),
887908
qself.span,
888909
traits::WellFormed(None),
889910
);
@@ -902,7 +923,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
902923
if item_name.name != kw::Empty {
903924
if let Some(mut e) = self.report_method_error(
904925
span,
905-
ty.normalized,
926+
normalized,
906927
item_name,
907928
SelfSource::QPath(qself),
908929
error,
@@ -918,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
918939
});
919940

920941
if result.is_ok() {
921-
self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
942+
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
922943
}
923944

924945
// Write back the new resolution.
@@ -1082,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10821103
pub fn instantiate_value_path(
10831104
&self,
10841105
segments: &[hir::PathSegment<'_>],
1085-
self_ty: Option<RawTy<'tcx>>,
1106+
self_ty: Option<Ty<'tcx>>,
10861107
res: Res,
10871108
span: Span,
10881109
hir_id: hir::HirId,
@@ -1093,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10931114
Res::Local(_) | Res::SelfCtor(_) => vec![],
10941115
Res::Def(kind, def_id) => self.astconv().def_ids_for_value_path_segments(
10951116
segments,
1096-
self_ty.map(|ty| ty.raw),
1117+
self_ty.map(|ty| ty),
10971118
kind,
10981119
def_id,
10991120
span,
@@ -1107,8 +1128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11071128
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
11081129
if let Some(self_ty) = self_ty =>
11091130
{
1110-
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
1111-
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
1131+
let adt_def = self.structurally_normalize_after_astconv(span, self_ty).ty_adt_def().unwrap();
1132+
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
11121133
is_alias_variant_ctor = true;
11131134
}
11141135
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
@@ -1127,7 +1148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11271148
// inherent impl, we need to record the
11281149
// `T` for posterity (see `UserSelfTy` for
11291150
// details).
1130-
let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
1151+
let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
11311152
user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
11321153
}
11331154
}
@@ -1206,9 +1227,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12061227
path_segs.last().is_some_and(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self);
12071228

12081229
let (res, self_ctor_args) = if let Res::SelfCtor(impl_def_id) = res {
1209-
let ty =
1210-
self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).instantiate_identity());
1211-
match ty.normalized.ty_adt_def() {
1230+
let ty = tcx.at(span).type_of(impl_def_id).instantiate_identity();
1231+
let normalized = self.structurally_normalize_after_astconv(span, ty);
1232+
match normalized.ty_adt_def() {
12121233
Some(adt_def) if adt_def.has_ctor() => {
12131234
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
12141235
// Check the visibility of the ctor.
@@ -1218,7 +1239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12181239
.emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
12191240
}
12201241
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1221-
let user_args = Self::user_args_for_adt(ty);
1242+
let user_args = Self::user_args_for_adt(ty, normalized);
12221243
user_self_ty = user_args.user_self_ty;
12231244
(new_res, Some(user_args.args))
12241245
}
@@ -1227,7 +1248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12271248
span,
12281249
"the `Self` constructor can only be used with tuple or unit structs",
12291250
);
1230-
if let Some(adt_def) = ty.normalized.ty_adt_def() {
1251+
if let Some(adt_def) = normalized.ty_adt_def() {
12311252
match adt_def.adt_kind() {
12321253
AdtKind::Enum => {
12331254
err.help("did you mean to use one of the enum's variants?");
@@ -1299,7 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12991320
self.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
13001321
}
13011322
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
1302-
self.fcx.to_ty(ty).raw.into()
1323+
self.fcx.to_ty(ty).into()
13031324
}
13041325
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
13051326
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@@ -1367,7 +1388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13671388
def_id,
13681389
&[],
13691390
has_self,
1370-
self_ty.map(|s| s.raw),
1391+
self_ty.map(|s| s),
13711392
&arg_count,
13721393
&mut CreateCtorSubstsContext {
13731394
fcx: self,

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+24-20
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::method::MethodCallee;
66
use crate::TupleArgumentsFlag::*;
77
use crate::{errors, Expectation::*};
88
use crate::{
9-
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag,
9+
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, TupleArgumentsFlag,
1010
};
1111
use rustc_ast as ast;
1212
use rustc_data_structures::fx::FxIndexSet;
@@ -1346,25 +1346,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13461346
) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
13471347
let path_span = qpath.span();
13481348
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1349+
let normalized = self.structurally_normalize_after_astconv(path_span, ty);
1350+
13491351
let variant = match def {
13501352
Res::Err => {
13511353
let guar =
13521354
self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
13531355
self.set_tainted_by_errors(guar);
13541356
return Err(guar);
13551357
}
1356-
Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1357-
Some(adt) => {
1358-
Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1359-
}
1360-
_ => bug!("unexpected type: {:?}", ty.normalized),
1358+
Res::Def(DefKind::Variant, _) => match normalized.ty_adt_def() {
1359+
Some(adt) => Some((
1360+
adt.variant_of_res(def),
1361+
adt.did(),
1362+
Self::user_args_for_adt(ty, normalized),
1363+
)),
1364+
_ => bug!("unexpected type: {:?}", normalized),
13611365
},
13621366
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
13631367
| Res::SelfTyParam { .. }
1364-
| Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1365-
Some(adt) if !adt.is_enum() => {
1366-
Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1367-
}
1368+
| Res::SelfTyAlias { .. } => match normalized.ty_adt_def() {
1369+
Some(adt) if !adt.is_enum() => Some((
1370+
adt.non_enum_variant(),
1371+
adt.did(),
1372+
Self::user_args_for_adt(ty, normalized),
1373+
)),
13681374
_ => None,
13691375
},
13701376
_ => bug!("unexpected definition: {:?}", def),
@@ -1379,9 +1385,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13791385
// Check bounds on type arguments used in the path.
13801386
self.add_required_obligations_for_hir(path_span, did, args, hir_id);
13811387

1382-
Ok((variant, ty.normalized))
1388+
Ok((variant, normalized))
13831389
} else {
1384-
Err(match *ty.normalized.kind() {
1390+
Err(match *normalized.kind() {
13851391
ty::Error(guar) => {
13861392
// E0071 might be caused by a spelling error, which will have
13871393
// already caused an error message and probably a suggestion
@@ -1394,7 +1400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13941400
path_span,
13951401
E0071,
13961402
"expected struct, variant or union type, found {}",
1397-
ty.normalized.sort_string(self.tcx)
1403+
normalized.sort_string(self.tcx)
13981404
)
13991405
.span_label(path_span, "not a struct")
14001406
.emit(),
@@ -1802,23 +1808,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18021808
qpath: &QPath<'_>,
18031809
path_span: Span,
18041810
hir_id: hir::HirId,
1805-
) -> (Res, RawTy<'tcx>) {
1811+
) -> (Res, Ty<'tcx>) {
18061812
match *qpath {
18071813
QPath::Resolved(ref maybe_qself, ref path) => {
1808-
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
1814+
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
18091815
let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
1810-
(path.res, self.handle_raw_ty(path_span, ty))
1816+
(path.res, ty)
18111817
}
18121818
QPath::TypeRelative(ref qself, ref segment) => {
18131819
let ty = self.to_ty(qself);
18141820

18151821
let result = self
18161822
.astconv()
1817-
.associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
1823+
.associated_path_to_ty(hir_id, path_span, ty, qself, segment, true);
18181824
let ty = result
18191825
.map(|(ty, _, _)| ty)
18201826
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
1821-
let ty = self.handle_raw_ty(path_span, ty);
18221827
let result = result.map(|(_, kind, def_id)| (kind, def_id));
18231828

18241829
// Write back the new resolution.
@@ -1827,8 +1832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18271832
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
18281833
}
18291834
QPath::LangItem(lang_item, span, id) => {
1830-
let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
1831-
(res, self.handle_raw_ty(path_span, ty))
1835+
self.resolve_lang_item_path(lang_item, span, hir_id, id)
18321836
}
18331837
}
18341838
}

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,3 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
325325
Some(&self.infcx)
326326
}
327327
}
328-
329-
/// Represents a user-provided type in the raw form (never normalized).
330-
///
331-
/// This is a bridge between the interface of `AstConv`, which outputs a raw `Ty`,
332-
/// and the API in this module, which expect `Ty` to be fully normalized.
333-
#[derive(Clone, Copy, Debug)]
334-
pub struct RawTy<'tcx> {
335-
pub raw: Ty<'tcx>,
336-
337-
/// The normalized form of `raw`, stored here for efficiency.
338-
pub normalized: Ty<'tcx>,
339-
}

0 commit comments

Comments
 (0)