Skip to content

Commit 3bea6bc

Browse files
committed
optimize and add test
1 parent a04088b commit 3bea6bc

File tree

11 files changed

+99
-310
lines changed

11 files changed

+99
-310
lines changed

compiler/rustc_hir_analysis/src/check/mod.rs

-254
Original file line numberDiff line numberDiff line change
@@ -113,260 +113,6 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
113113
tcx.calculate_dtor(def_id, dropck::check_drop_impl)
114114
}
115115

116-
/// If this `DefId` is a "primary tables entry", returns
117-
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
118-
///
119-
/// If this function returns `Some`, then `typeck_results(def_id)` will
120-
/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
121-
/// may not succeed. In some cases where this function returns `None`
122-
/// (notably closures), `typeck_results(def_id)` would wind up
123-
/// redirecting to the owning function.
124-
fn primary_body_of(
125-
tcx: TyCtxt<'_>,
126-
id: hir::HirId,
127-
) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
128-
match tcx.hir().get(id) {
129-
Node::Item(item) => match item.kind {
130-
hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
131-
Some((body, Some(ty), None))
132-
}
133-
hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
134-
_ => None,
135-
},
136-
Node::TraitItem(item) => match item.kind {
137-
hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
138-
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
139-
Some((body, None, Some(sig)))
140-
}
141-
_ => None,
142-
},
143-
Node::ImplItem(item) => match item.kind {
144-
hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
145-
hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
146-
_ => None,
147-
},
148-
Node::AnonConst(constant) => Some((constant.body, None, None)),
149-
_ => None,
150-
}
151-
}
152-
153-
fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
154-
// Closures' typeck results come from their outermost function,
155-
// as they are part of the same "inference environment".
156-
let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
157-
if typeck_root_def_id != def_id {
158-
return tcx.has_typeck_results(typeck_root_def_id);
159-
}
160-
161-
if let Some(def_id) = def_id.as_local() {
162-
let id = tcx.hir().local_def_id_to_hir_id(def_id);
163-
primary_body_of(tcx, id).is_some()
164-
} else {
165-
false
166-
}
167-
}
168-
169-
fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
170-
&*tcx.typeck(def_id).used_trait_imports
171-
}
172-
173-
fn typeck_const_arg<'tcx>(
174-
tcx: TyCtxt<'tcx>,
175-
(did, param_did): (LocalDefId, DefId),
176-
) -> &ty::TypeckResults<'tcx> {
177-
let fallback = move || tcx.type_of(param_did);
178-
typeck_with_fallback(tcx, did, fallback)
179-
}
180-
181-
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
182-
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
183-
tcx.typeck_const_arg((def_id, param_did))
184-
} else {
185-
let fallback = move || tcx.type_of(def_id.to_def_id());
186-
typeck_with_fallback(tcx, def_id, fallback)
187-
}
188-
}
189-
190-
/// Used only to get `TypeckResults` for type inference during error recovery.
191-
/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
192-
fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
193-
let fallback = move || {
194-
let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
195-
tcx.ty_error_with_message(span, "diagnostic only typeck table used")
196-
};
197-
typeck_with_fallback(tcx, def_id, fallback)
198-
}
199-
200-
fn typeck_with_fallback<'tcx>(
201-
tcx: TyCtxt<'tcx>,
202-
def_id: LocalDefId,
203-
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
204-
) -> &'tcx ty::TypeckResults<'tcx> {
205-
// Closures' typeck results come from their outermost function,
206-
// as they are part of the same "inference environment".
207-
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
208-
if typeck_root_def_id != def_id {
209-
return tcx.typeck(typeck_root_def_id);
210-
}
211-
212-
let id = tcx.hir().local_def_id_to_hir_id(def_id);
213-
let span = tcx.hir().span(id);
214-
215-
// Figure out what primary body this item has.
216-
let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
217-
span_bug!(span, "can't type-check body of {:?}", def_id);
218-
});
219-
let body = tcx.hir().body(body_id);
220-
221-
let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
222-
let param_env = tcx.param_env(def_id);
223-
let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
224-
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
225-
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
226-
<dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
227-
} else {
228-
tcx.fn_sig(def_id)
229-
};
230-
231-
check_abi(tcx, id, span, fn_sig.abi());
232-
233-
// Compute the function signature from point of view of inside the fn.
234-
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
235-
let fn_sig = inh.normalize_associated_types_in(
236-
body.value.span,
237-
body_id.hir_id,
238-
param_env,
239-
fn_sig,
240-
);
241-
check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
242-
} else {
243-
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
244-
let expected_type = body_ty
245-
.and_then(|ty| match ty.kind {
246-
hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
247-
_ => None,
248-
})
249-
.unwrap_or_else(|| match tcx.hir().get(id) {
250-
Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
251-
Node::Expr(&hir::Expr {
252-
kind: hir::ExprKind::ConstBlock(ref anon_const),
253-
..
254-
}) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
255-
kind: TypeVariableOriginKind::TypeInference,
256-
span,
257-
}),
258-
Node::Ty(&hir::Ty {
259-
kind: hir::TyKind::Typeof(ref anon_const), ..
260-
}) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
261-
kind: TypeVariableOriginKind::TypeInference,
262-
span,
263-
}),
264-
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
265-
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
266-
let operand_ty = asm
267-
.operands
268-
.iter()
269-
.filter_map(|(op, _op_sp)| match op {
270-
hir::InlineAsmOperand::Const { anon_const }
271-
if anon_const.hir_id == id =>
272-
{
273-
// Inline assembly constants must be integers.
274-
Some(fcx.next_int_var())
275-
}
276-
hir::InlineAsmOperand::SymFn { anon_const }
277-
if anon_const.hir_id == id =>
278-
{
279-
Some(fcx.next_ty_var(TypeVariableOrigin {
280-
kind: TypeVariableOriginKind::MiscVariable,
281-
span,
282-
}))
283-
}
284-
_ => None,
285-
})
286-
.next();
287-
operand_ty.unwrap_or_else(fallback)
288-
}
289-
_ => fallback(),
290-
},
291-
_ => fallback(),
292-
});
293-
294-
let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
295-
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
296-
297-
// Gather locals in statics (because of block expressions).
298-
GatherLocalsVisitor::new(&fcx).visit_body(body);
299-
300-
fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
301-
302-
fcx.write_ty(id, expected_type);
303-
304-
fcx
305-
};
306-
307-
let fallback_has_occurred = fcx.type_inference_fallback();
308-
309-
// Even though coercion casts provide type hints, we check casts after fallback for
310-
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
311-
fcx.check_casts();
312-
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
313-
314-
// Closure and generator analysis may run after fallback
315-
// because they don't constrain other type variables.
316-
// Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
317-
let prev_constness = fcx.param_env.constness();
318-
fcx.param_env = fcx.param_env.without_const();
319-
fcx.closure_analyze(body);
320-
fcx.param_env = fcx.param_env.with_constness(prev_constness);
321-
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
322-
// Before the generator analysis, temporary scopes shall be marked to provide more
323-
// precise information on types to be captured.
324-
fcx.resolve_rvalue_scopes(def_id.to_def_id());
325-
fcx.resolve_generator_interiors(def_id.to_def_id());
326-
327-
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
328-
let ty = fcx.normalize_ty(span, ty);
329-
fcx.require_type_is_sized(ty, span, code);
330-
}
331-
332-
fcx.resolve_base_expr();
333-
334-
fcx.select_all_obligations_or_error();
335-
336-
if !fcx.infcx.is_tainted_by_errors() {
337-
fcx.check_transmutes();
338-
}
339-
340-
fcx.check_asms();
341-
342-
fcx.infcx.skip_region_resolution();
343-
344-
fcx.resolve_type_vars_in_body(body)
345-
});
346-
347-
// Consistency check our TypeckResults instance can hold all ItemLocalIds
348-
// it will need to hold.
349-
assert_eq!(typeck_results.hir_owner, id.owner);
350-
351-
typeck_results
352-
}
353-
354-
/// When `check_fn` is invoked on a generator (i.e., a body that
355-
/// includes yield), it returns back some information about the yield
356-
/// points.
357-
struct GeneratorTypes<'tcx> {
358-
/// Type of generator argument / values returned by `yield`.
359-
resume_ty: Ty<'tcx>,
360-
361-
/// Type of value that is yielded.
362-
yield_ty: Ty<'tcx>,
363-
364-
/// Types that are captured (see `GeneratorInterior` for more).
365-
interior: Ty<'tcx>,
366-
367-
/// Indicates if the generator is movable or static (immovable).
368-
movability: hir::Movability,
369-
}
370116
/// Given a `DefId` for an opaque type in return position, find its parent item's return
371117
/// expressions.
372118
fn get_owner_return_paths<'tcx>(

compiler/rustc_hir_typeck/src/demand.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
use crate::FnCtxt;
2-
use rustc_infer::infer::base_struct::base_struct;
3-
use rustc_infer::infer::InferOk;
4-
use rustc_middle::middle::stability::EvalResult;
5-
use rustc_trait_selection::infer::InferCtxtExt as _;
6-
use rustc_trait_selection::traits::ObligationCause;
72
use rustc_ast::util::parser::PREC_POSTFIX;
83
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
94
use rustc_hir as hir;
105
use rustc_hir::lang_items::LangItem;
116
use rustc_hir::{is_range_literal, Node};
7+
use rustc_infer::infer::base_struct::base_struct;
128
use rustc_infer::infer::InferOk;
139
use rustc_middle::lint::in_external_macro;
1410
use rustc_middle::middle::stability::EvalResult;
@@ -183,16 +179,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183179
pub fn demand_base_struct(
184180
&self,
185181
cause: &ObligationCause<'tcx>,
186-
expected: Ty<'tcx>,
187-
actual: Ty<'tcx>,
182+
adt_ty: Ty<'tcx>,
183+
base_ty: Ty<'tcx>,
188184
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
189185
let at = self.at(cause, self.param_env);
190-
match base_struct(at, expected, actual) {
186+
match base_struct(at, adt_ty, base_ty) {
191187
Ok(InferOk { obligations, value: () }) => {
192188
self.register_predicates(obligations);
193189
None
194190
}
195-
Err(e) => Some(self.report_mismatched_types(&cause, expected, actual, e)),
191+
Err(e) => Some(self.err_ctxt().report_mismatched_types(&cause, adt_ty, base_ty, e)),
196192
}
197193
}
198194

compiler/rustc_hir_typeck/src/expr.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -1667,16 +1667,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16671667
self.register_predicates(obligations)
16681668
}
16691669
Err(_) => {
1670-
// This should never happen, since we're just subtyping the
1671-
// remaining_fields, but it's fine to emit this, I guess.
1672-
self.err_ctxt()
1673-
.report_mismatched_types(
1674-
&cause,
1675-
target_ty,
1676-
fru_ty,
1677-
FieldMisMatch(variant.name, ident.name),
1678-
)
1679-
.emit(); }
1670+
bug!("subtype fresh substs failed")
1671+
}
16801672
}
16811673
}
16821674
self.resolve_vars_if_possible(fru_ty)
@@ -1701,12 +1693,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17011693
// This is important to allow coercions to happen in
17021694
// `other_struct` itself. See `coerce-in-base-expr.rs`.
17031695
let fresh_base_ty = self.tcx.mk_adt(*adt, fresh_substs);
1704-
self.check_expr_has_type_or_error(
1705-
base_expr,
1706-
fresh_base_ty,
1707-
|_| {},
1708-
);
1709-
self.typeck_results.borrow_mut().base_expr_backup_mut().insert(base_expr.hir_id, (fresh_base_ty, adt_ty));
1696+
self.check_expr_has_type_or_error(base_expr, fresh_base_ty, |_| {});
1697+
let fresh_base_ty = self.resolve_vars_if_possible(fresh_base_ty);
1698+
if fresh_base_ty.needs_infer() {
1699+
self.typeck_results.borrow_mut().base_expr_backup.push((
1700+
base_expr.span,
1701+
adt_ty,
1702+
fresh_base_ty,
1703+
));
1704+
}
17101705
fru_tys
17111706
} else {
17121707
// Check the base_expr, regardless of a bad expected adt_ty, so we can get

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -606,11 +606,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
606606
}
607607

608608
pub(in super::super) fn resolve_base_expr(&self) {
609-
for (_, (base_ty, adt_ty)) in self.typeck_results.borrow().base_expr_backup().iter() {
609+
for (span, adt_ty, base_ty) in self.typeck_results.borrow().base_expr_backup.iter() {
610610
let base_ty = self.resolve_vars_if_possible(*base_ty);
611-
if base_ty.has_infer_types() {
612-
if let Some(mut err) =
613-
self.demand_base_struct(&self.misc(DUMMY_SP), *adt_ty, base_ty)
611+
if base_ty.needs_infer() {
612+
if let Some(mut err) = self.demand_base_struct(&self.misc(*span), *adt_ty, base_ty)
614613
{
615614
err.emit();
616615
}

compiler/rustc_hir_typeck/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,10 @@ fn typeck_with_fallback<'tcx>(
341341
fcx.require_type_is_sized(ty, span, code);
342342
}
343343

344+
// If the base structs used to creat structs still remain infer generics,
345+
// unify it with the created ones.
346+
fcx.resolve_base_expr();
347+
344348
fcx.select_all_obligations_or_error();
345349

346350
if !fcx.infcx.is_tainted_by_errors() {

0 commit comments

Comments
 (0)