Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 55 additions & 17 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ pub struct InherentAssocCandidate {
pub scope: DefId,
}

pub struct ResolvedStructPath<'tcx> {
pub res: Result<Res, ErrorGuaranteed>,
pub ty: Ty<'tcx>,
}

/// A context which can lower type-system entities from the [HIR][hir] to
/// the [`rustc_middle::ty`] representation.
///
Expand Down Expand Up @@ -2558,38 +2563,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::new_error(tcx, e)
};

let (ty, variant_did) = match qpath {
let ResolvedStructPath { res: opt_res, ty } =
self.lower_path_for_struct_expr(qpath, span, hir_id);

let variant_did = match qpath {
hir::QPath::Resolved(maybe_qself, path) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
let ty =
self.lower_resolved_ty_path(opt_self_ty, path, hir_id, PermitVariants::Yes);
let variant_did = match path.res {
Res::Def(DefKind::Variant | DefKind::Struct, did) => did,
_ => return non_adt_or_variant_res(),
};

(ty, variant_did)
variant_did
}
hir::QPath::TypeRelative(hir_self_ty, segment) => {
debug!(?hir_self_ty, ?segment);
let self_ty = self.lower_ty(hir_self_ty);
let opt_res = self.lower_type_relative_ty_path(
self_ty,
hir_self_ty,
segment,
hir_id,
span,
PermitVariants::Yes,
);

let (ty, _, res_def_id) = match opt_res {
Ok(r @ (_, DefKind::Variant | DefKind::Struct, _)) => r,
let res_def_id = match opt_res {
Ok(r)
if matches!(
tcx.def_kind(r.def_id()),
DefKind::Variant | DefKind::Struct
) =>
{
r.def_id()
}
Ok(_) => return non_adt_or_variant_res(),
Err(e) => return ty::Const::new_error(tcx, e),
};

(ty, res_def_id)
res_def_id
}
};

Expand Down Expand Up @@ -2650,6 +2653,41 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::new_value(tcx, valtree, ty)
}

pub fn lower_path_for_struct_expr(
&self,
qpath: hir::QPath<'tcx>,
path_span: Span,
hir_id: HirId,
) -> ResolvedStructPath<'tcx> {
match qpath {
hir::QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
let ty = self.lower_resolved_ty_path(self_ty, path, hir_id, PermitVariants::Yes);
ResolvedStructPath { res: Ok(path.res), ty }
}
hir::QPath::TypeRelative(hir_self_ty, segment) => {
let self_ty = self.lower_ty(hir_self_ty);

let result = self.lower_type_relative_ty_path(
self_ty,
hir_self_ty,
segment,
hir_id,
path_span,
PermitVariants::Yes,
);
let ty = result
.map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));

ResolvedStructPath {
res: result.map(|(_, kind, def_id)| Res::Def(kind, def_id)),
ty,
}
}
}
}

/// Lower a [resolved][hir::QPath::Resolved] path to a (type-level) constant.
fn lower_resolved_const_path(
&self,
Expand Down
37 changes: 9 additions & 28 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath, is_range_literal};
use rustc_hir_analysis::check::potentially_plural_count;
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
use rustc_index::IndexVec;
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
use rustc_middle::ty::adjustment::AllowTwoPhase;
Expand Down Expand Up @@ -1285,38 +1285,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path_span: Span,
hir_id: HirId,
) -> (Res, LoweredTy<'tcx>) {
let ResolvedStructPath { res: result, ty } =
self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
match *qpath {
QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
let ty = self.lowerer().lower_resolved_ty_path(
self_ty,
path,
hir_id,
PermitVariants::Yes,
);
(path.res, LoweredTy::from_raw(self, path_span, ty))
}
QPath::TypeRelative(hir_self_ty, segment) => {
let self_ty = self.lower_ty(hir_self_ty);

let result = self.lowerer().lower_type_relative_ty_path(
self_ty.raw,
hir_self_ty,
segment,
hir_id,
path_span,
PermitVariants::Yes,
);
let ty = result
.map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
QPath::TypeRelative(_, _) => {
let ty = LoweredTy::from_raw(self, path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id));
let resolution =
result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));

// Write back the new resolution.
self.write_resolution(hir_id, result);
self.write_resolution(hir_id, resolution);

(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
(result.unwrap_or(Res::Err), ty)
}
}
}
Expand Down
Loading