Skip to content

Commit 4fe666e

Browse files
committed
implied_bounds: clarify our assumptions
1 parent b7a8496 commit 4fe666e

22 files changed

+251
-172
lines changed

compiler/rustc_middle/src/query/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,14 @@ rustc_queries! {
765765
desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
766766
}
767767

768+
/// Returns the types assumed to be well formed while "inside" of the given item.
769+
///
770+
/// Note that we've liberated the late bound regions of function signatures, so
771+
/// this can not be used to check whether these types are well formed.
772+
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
773+
desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) }
774+
}
775+
768776
/// Computes the signature of the function.
769777
query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
770778
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::rustc_middle::ty::DefIdTree;
2+
use rustc_hir::{def::DefKind, def_id::DefId};
3+
use rustc_middle::ty::{self, Ty, TyCtxt};
4+
5+
pub fn provide(providers: &mut ty::query::Providers) {
6+
*providers = ty::query::Providers { assumed_wf_types, ..*providers };
7+
}
8+
9+
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
10+
match tcx.def_kind(def_id) {
11+
DefKind::Fn => {
12+
let sig = tcx.fn_sig(def_id);
13+
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
14+
liberated_sig.inputs_and_output
15+
}
16+
DefKind::AssocFn => {
17+
let sig = tcx.fn_sig(def_id);
18+
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
19+
let mut assumed_wf_types: Vec<_> =
20+
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
21+
assumed_wf_types.extend(liberated_sig.inputs_and_output);
22+
tcx.intern_type_list(&assumed_wf_types)
23+
}
24+
DefKind::Impl => match tcx.impl_trait_ref(def_id) {
25+
Some(trait_ref) => {
26+
let types: Vec<_> = trait_ref.substs.types().collect();
27+
tcx.intern_type_list(&types)
28+
}
29+
// Only the impl self type
30+
None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
31+
},
32+
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
33+
DefKind::Mod
34+
| DefKind::Struct
35+
| DefKind::Union
36+
| DefKind::Enum
37+
| DefKind::Variant
38+
| DefKind::Trait
39+
| DefKind::TyAlias
40+
| DefKind::ForeignTy
41+
| DefKind::TraitAlias
42+
| DefKind::TyParam
43+
| DefKind::Const
44+
| DefKind::ConstParam
45+
| DefKind::Static(_)
46+
| DefKind::Ctor(_, _)
47+
| DefKind::Macro(_)
48+
| DefKind::ExternCrate
49+
| DefKind::Use
50+
| DefKind::ForeignMod
51+
| DefKind::AnonConst
52+
| DefKind::InlineConst
53+
| DefKind::OpaqueTy
54+
| DefKind::Field
55+
| DefKind::LifetimeParam
56+
| DefKind::GlobalAsm
57+
| DefKind::Closure
58+
| DefKind::Generator => ty::List::empty(),
59+
}
60+
}

compiler/rustc_ty_utils/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_middle::ty::query::Providers;
2121
mod assoc;
2222
mod common_traits;
2323
mod consts;
24+
mod implied_bounds;
2425
pub mod instance;
2526
mod needs_drop;
2627
pub mod representability;
@@ -30,6 +31,7 @@ pub fn provide(providers: &mut Providers) {
3031
assoc::provide(providers);
3132
common_traits::provide(providers);
3233
consts::provide(providers);
34+
implied_bounds::provide(providers);
3335
needs_drop::provide(providers);
3436
ty::provide(providers);
3537
instance::provide(providers);

compiler/rustc_typeck/src/check/compare_method.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::potentially_plural_count;
22
use crate::check::regionck::OutlivesEnvironmentExt;
3-
use crate::check::wfcheck;
43
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
54
use rustc_data_structures::fx::FxHashSet;
65
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
@@ -1445,14 +1444,24 @@ pub fn check_type_bounds<'tcx>(
14451444
};
14461445
debug!(?normalize_param_env);
14471446

1447+
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
14481448
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
14491449
let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
14501450

14511451
tcx.infer_ctxt().enter(move |infcx| {
14521452
let ocx = ObligationCtxt::new(&infcx);
14531453

1454+
let assumed_wf_types = tcx.assumed_wf_types(impl_ty.def_id);
1455+
let mut implied_bounds = FxHashSet::default();
1456+
let cause = ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
1457+
for ty in assumed_wf_types {
1458+
implied_bounds.insert(ty);
1459+
let normalized = ocx.normalize(cause.clone(), param_env, ty);
1460+
implied_bounds.insert(normalized);
1461+
}
1462+
let implied_bounds = implied_bounds;
1463+
14541464
let mut selcx = traits::SelectionContext::new(&infcx);
1455-
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
14561465
let normalize_cause = ObligationCause::new(
14571466
impl_ty_span,
14581467
impl_ty_hir_id,
@@ -1508,15 +1517,6 @@ pub fn check_type_bounds<'tcx>(
15081517

15091518
// Finally, resolve all regions. This catches wily misuses of
15101519
// lifetime parameters.
1511-
let implied_bounds = match impl_ty.container {
1512-
ty::TraitContainer => FxHashSet::default(),
1513-
ty::ImplContainer => wfcheck::impl_implied_bounds(
1514-
tcx,
1515-
param_env,
1516-
container_id.expect_local(),
1517-
impl_ty_span,
1518-
),
1519-
};
15201520
let mut outlives_environment = OutlivesEnvironment::new(param_env);
15211521
outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
15221522
infcx.check_region_obligations_and_report_errors(

compiler/rustc_typeck/src/check/wfcheck.rs

+19-74
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use rustc_hir::ItemKind;
1010
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
1111
use rustc_infer::infer::outlives::obligations::TypeOutlives;
1212
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
13-
use rustc_infer::traits::Normalized;
1413
use rustc_middle::ty::query::Providers;
1514
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
1615
use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -24,8 +23,6 @@ use rustc_span::{Span, DUMMY_SP};
2423
use rustc_trait_selection::autoderef::Autoderef;
2524
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
2625
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
27-
use rustc_trait_selection::traits::query::normalize::AtExt;
28-
use rustc_trait_selection::traits::query::NoSolution;
2926
use rustc_trait_selection::traits::{
3027
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
3128
};
@@ -86,26 +83,37 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
8683
body_def_id: LocalDefId,
8784
f: F,
8885
) where
89-
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet<Ty<'tcx>>,
86+
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
9087
{
9188
let param_env = tcx.param_env(body_def_id);
9289
let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
9390
tcx.infer_ctxt().enter(|ref infcx| {
9491
let ocx = ObligationCtxt::new(infcx);
92+
93+
let assumed_wf_types = tcx.assumed_wf_types(body_def_id);
94+
let mut implied_bounds = FxHashSet::default();
95+
let cause = ObligationCause::misc(span, body_id);
96+
for ty in assumed_wf_types {
97+
implied_bounds.insert(ty);
98+
let normalized = ocx.normalize(cause.clone(), param_env, ty);
99+
implied_bounds.insert(normalized);
100+
}
101+
let implied_bounds = implied_bounds;
102+
95103
let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
96104

97105
if !tcx.features().trivial_bounds {
98106
wfcx.check_false_global_bounds()
99107
}
100-
let wf_tys = f(&mut wfcx);
108+
f(&mut wfcx);
101109
let errors = wfcx.select_all_or_error();
102110
if !errors.is_empty() {
103111
infcx.report_fulfillment_errors(&errors, None, false);
104112
return;
105113
}
106114

107115
let mut outlives_environment = OutlivesEnvironment::new(param_env);
108-
outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
116+
outlives_environment.add_implied_bounds(infcx, implied_bounds, body_id);
109117
infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
110118
})
111119
}
@@ -976,15 +984,9 @@ fn check_associated_item(
976984
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
977985
let item = tcx.associated_item(item_id);
978986

979-
let (mut implied_bounds, self_ty) = match item.container {
980-
ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param),
981-
ty::ImplContainer => {
982-
let def_id = item.container_id(tcx);
983-
(
984-
impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
985-
tcx.type_of(def_id),
986-
)
987-
}
987+
let self_ty = match item.container {
988+
ty::TraitContainer => tcx.types.self_param,
989+
ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
988990
};
989991

990992
match item.kind {
@@ -1002,7 +1004,6 @@ fn check_associated_item(
10021004
sig,
10031005
hir_sig.decl,
10041006
item.def_id.expect_local(),
1005-
&mut implied_bounds,
10061007
);
10071008
check_method_receiver(wfcx, hir_sig, item, self_ty);
10081009
}
@@ -1017,8 +1018,6 @@ fn check_associated_item(
10171018
}
10181019
}
10191020
}
1020-
1021-
implied_bounds
10221021
})
10231022
}
10241023

@@ -1118,9 +1117,6 @@ fn check_type_defn<'tcx, F>(
11181117
}
11191118

11201119
check_where_clauses(wfcx, item.span, item.def_id);
1121-
1122-
// No implied bounds in a struct definition.
1123-
FxHashSet::default()
11241120
});
11251121
}
11261122

@@ -1144,9 +1140,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
11441140
}
11451141

11461142
enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
1147-
check_where_clauses(wfcx, item.span, item.def_id);
1148-
1149-
FxHashSet::default()
1143+
check_where_clauses(wfcx, item.span, item.def_id)
11501144
});
11511145

11521146
// Only check traits, don't check trait aliases
@@ -1186,9 +1180,7 @@ fn check_item_fn(
11861180
) {
11871181
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
11881182
let sig = tcx.fn_sig(def_id);
1189-
let mut implied_bounds = FxHashSet::default();
1190-
check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds);
1191-
implied_bounds
1183+
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
11921184
})
11931185
}
11941186

@@ -1231,9 +1223,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
12311223
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
12321224
);
12331225
}
1234-
1235-
// No implied bounds in a const, etc.
1236-
FxHashSet::default()
12371226
});
12381227
}
12391228

@@ -1284,8 +1273,6 @@ fn check_impl<'tcx>(
12841273
}
12851274

12861275
check_where_clauses(wfcx, item.span, item.def_id);
1287-
1288-
impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span)
12891276
});
12901277
}
12911278

@@ -1479,7 +1466,6 @@ fn check_fn_or_method<'tcx>(
14791466
sig: ty::PolyFnSig<'tcx>,
14801467
hir_decl: &hir::FnDecl<'_>,
14811468
def_id: LocalDefId,
1482-
implied_bounds: &mut FxHashSet<Ty<'tcx>>,
14831469
) {
14841470
let tcx = wfcx.tcx();
14851471
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@@ -1521,15 +1507,8 @@ fn check_fn_or_method<'tcx>(
15211507
);
15221508
}
15231509

1524-
implied_bounds.extend(sig.inputs());
1525-
15261510
wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into());
15271511

1528-
// FIXME(#27579) return types should not be implied bounds
1529-
implied_bounds.insert(sig.output());
1530-
1531-
debug!(?implied_bounds);
1532-
15331512
check_where_clauses(wfcx, span, def_id);
15341513
}
15351514

@@ -1924,40 +1903,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
19241903
}
19251904
}
19261905

1927-
pub fn impl_implied_bounds<'tcx>(
1928-
tcx: TyCtxt<'tcx>,
1929-
param_env: ty::ParamEnv<'tcx>,
1930-
impl_def_id: LocalDefId,
1931-
span: Span,
1932-
) -> FxHashSet<Ty<'tcx>> {
1933-
// We completely ignore any obligations caused by normalizing the types
1934-
// we assume to be well formed. Considering that the user of the implied
1935-
// bounds will also normalize them, we leave it to them to emit errors
1936-
// which should result in better causes and spans.
1937-
tcx.infer_ctxt().enter(|infcx| {
1938-
let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id));
1939-
match tcx.impl_trait_ref(impl_def_id) {
1940-
Some(trait_ref) => {
1941-
// Trait impl: take implied bounds from all types that
1942-
// appear in the trait reference.
1943-
match infcx.at(&cause, param_env).normalize(trait_ref) {
1944-
Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(),
1945-
Err(NoSolution) => FxHashSet::default(),
1946-
}
1947-
}
1948-
1949-
None => {
1950-
// Inherent impl: take implied bounds from the `self` type.
1951-
let self_ty = tcx.type_of(impl_def_id);
1952-
match infcx.at(&cause, param_env).normalize(self_ty) {
1953-
Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]),
1954-
Err(NoSolution) => FxHashSet::default(),
1955-
}
1956-
}
1957-
}
1958-
})
1959-
}
1960-
19611906
fn error_392(
19621907
tcx: TyCtxt<'_>,
19631908
span: Span,

0 commit comments

Comments
 (0)