Skip to content

Commit 074fff2

Browse files
committed
Perform unconstrained param detection in explicit_predicates_of and taint the query result
1 parent d8b0864 commit 074fff2

File tree

11 files changed

+103
-61
lines changed

11 files changed

+103
-61
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use rustc_hir as hir;
66
use rustc_hir::def::DefKind;
77
use rustc_hir::def_id::{DefId, LocalDefId};
88
use rustc_middle::ty::{
9-
self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
9+
self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
10+
TypeVisitor, Upcast,
1011
};
1112
use rustc_middle::{bug, span_bug};
1213
use rustc_span::symbol::Ident;
@@ -107,6 +108,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
107108
return ty::GenericPredicates {
108109
parent: Some(tcx.parent(def_id.to_def_id())),
109110
predicates: tcx.arena.alloc_from_iter(predicates),
111+
errored_due_to_unconstrained_params: Ok(()),
110112
};
111113
}
112114

@@ -128,6 +130,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
128130
return ty::GenericPredicates {
129131
parent: Some(impl_def_id),
130132
predicates: tcx.arena.alloc_from_iter(impl_predicates),
133+
errored_due_to_unconstrained_params: trait_assoc_predicates
134+
.errored_due_to_unconstrained_params,
131135
};
132136
}
133137

@@ -153,6 +157,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
153157
// We use an `IndexSet` to preserve order of insertion.
154158
// Preserving the order of insertion is important here so as not to break UI tests.
155159
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
160+
let mut errored_due_to_unconstrained_params = Ok(());
156161

157162
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
158163
if let Node::Item(item) = node {
@@ -319,11 +324,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
319324
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
320325
let self_ty = tcx.type_of(def_id).instantiate_identity();
321326
let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
322-
cgp::setup_constraining_predicates(
323-
tcx,
324-
&mut predicates,
325-
trait_ref,
326-
&mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
327+
let mut input_parameters = cgp::parameters_for_impl(tcx, self_ty, trait_ref);
328+
cgp::setup_constraining_predicates(tcx, &mut predicates, trait_ref, &mut input_parameters);
329+
errored_due_to_unconstrained_params = errored_due_to_unconstrained_params.and(
330+
self_ty.error_reported().and(trait_ref.error_reported()).and_then(|()| {
331+
crate::impl_wf_check::enforce_impl_params_are_constrained(
332+
tcx,
333+
def_id,
334+
input_parameters,
335+
)
336+
}),
327337
);
328338
}
329339

@@ -338,6 +348,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
338348
ty::GenericPredicates {
339349
parent: generics.parent,
340350
predicates: tcx.arena.alloc_from_iter(predicates),
351+
errored_due_to_unconstrained_params,
341352
}
342353
}
343354

@@ -507,6 +518,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
507518
ty::GenericPredicates {
508519
parent: predicates_and_bounds.parent,
509520
predicates: tcx.arena.alloc_slice(&predicates),
521+
errored_due_to_unconstrained_params: predicates_and_bounds
522+
.errored_due_to_unconstrained_params,
510523
}
511524
}
512525
} else {
@@ -558,6 +571,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
558571
return GenericPredicates {
559572
parent: parent_preds.parent,
560573
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
574+
errored_due_to_unconstrained_params: parent_preds
575+
.errored_due_to_unconstrained_params,
561576
};
562577
}
563578
gather_explicit_predicates_of(tcx, def_id)

compiler/rustc_hir_analysis/src/delegation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ impl<'tcx> PredicatesBuilder<'tcx> {
278278
ty::GenericPredicates {
279279
parent: self.parent,
280280
predicates: self.tcx.arena.alloc_from_iter(preds),
281+
errored_due_to_unconstrained_params: Ok(()),
281282
}
282283
}
283284
}

compiler/rustc_hir_analysis/src/impl_wf_check.rs

+5-17
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
use std::assert_matches::debug_assert_matches;
1212

1313
use min_specialization::check_min_specialization;
14+
use rustc_data_structures::fx::FxHashSet;
1415
use rustc_errors::codes::*;
1516
use rustc_hir::def::DefKind;
1617
use rustc_hir::def_id::LocalDefId;
17-
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
18+
use rustc_middle::ty::{self, TyCtxt};
1819
use rustc_span::ErrorGuaranteed;
1920

2021
use crate::constrained_generic_params as cgp;
@@ -59,34 +60,21 @@ pub(crate) fn check_impl_wf(
5960
let min_specialization = tcx.features().min_specialization();
6061
let mut res = Ok(());
6162
debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
62-
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
63+
res = res.and(tcx.explicit_predicates_of(impl_def_id).errored_due_to_unconstrained_params);
6364
if min_specialization {
6465
res = res.and(check_min_specialization(tcx, impl_def_id));
6566
}
6667

6768
res
6869
}
6970

70-
fn enforce_impl_params_are_constrained(
71+
pub(crate) fn enforce_impl_params_are_constrained(
7172
tcx: TyCtxt<'_>,
7273
impl_def_id: LocalDefId,
74+
input_parameters: FxHashSet<cgp::Parameter>,
7375
) -> Result<(), ErrorGuaranteed> {
7476
// Every lifetime used in an associated type must be constrained.
75-
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
76-
impl_self_ty.error_reported()?;
7777
let impl_generics = tcx.generics_of(impl_def_id);
78-
let impl_predicates = tcx.predicates_of(impl_def_id);
79-
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
80-
81-
impl_trait_ref.error_reported()?;
82-
83-
let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
84-
cgp::identify_constrained_generic_params(
85-
tcx,
86-
impl_predicates,
87-
impl_trait_ref,
88-
&mut input_parameters,
89-
);
9078

9179
let mut res = Ok(());
9280
for param in &impl_generics.own_params {

compiler/rustc_middle/src/ty/generics.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_ast as ast;
22
use rustc_data_structures::fx::FxHashMap;
33
use rustc_hir::def_id::DefId;
44
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
5-
use rustc_span::Span;
5+
use rustc_span::{ErrorGuaranteed, Span};
66
use rustc_span::symbol::{Symbol, kw};
77
use tracing::instrument;
88

@@ -356,10 +356,11 @@ impl<'tcx> Generics {
356356
}
357357

358358
/// Bounds on generics.
359-
#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
359+
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
360360
pub struct GenericPredicates<'tcx> {
361361
pub parent: Option<DefId>,
362362
pub predicates: &'tcx [(Clause<'tcx>, Span)],
363+
pub errored_due_to_unconstrained_params: Result<(), ErrorGuaranteed>,
363364
}
364365

365366
impl<'tcx> GenericPredicates<'tcx> {

compiler/rustc_smir/src/rustc_smir/context.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
175175
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
176176
let mut tables = self.0.borrow_mut();
177177
let def_id = tables[def_id];
178-
let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
178+
let GenericPredicates { parent, predicates, errored_due_to_unconstrained_params: _ } =
179+
tables.tcx.predicates_of(def_id);
179180
stable_mir::ty::GenericPredicates {
180181
parent: parent.map(|did| tables.trait_def(did)),
181182
predicates: predicates
@@ -196,7 +197,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
196197
) -> stable_mir::ty::GenericPredicates {
197198
let mut tables = self.0.borrow_mut();
198199
let def_id = tables[def_id];
199-
let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id);
200+
let GenericPredicates { parent, predicates, errored_due_to_unconstrained_params: _ } =
201+
tables.tcx.explicit_predicates_of(def_id);
200202
stable_mir::ty::GenericPredicates {
201203
parent: parent.map(|did| tables.trait_def(did)),
202204
predicates: predicates

src/librustdoc/clean/auto_trait.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,12 @@ fn synthesize_auto_trait_impl<'tcx>(
105105
let mut generics = clean_ty_generics(
106106
cx,
107107
tcx.generics_of(item_def_id),
108-
ty::GenericPredicates::default(),
108+
ty::GenericPredicates {
109+
parent: None,
110+
predicates: &[],
111+
effects_min_tys: ty::List::empty(),
112+
errored_due_to_unconstrained_params: Ok(()),
113+
},
109114
);
110115
generics.where_predicates.clear();
111116

src/librustdoc/clean/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
14041404
clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), ty::GenericPredicates {
14051405
parent: None,
14061406
predicates,
1407+
errored_due_to_unconstrained_params: Ok(()),
14071408
});
14081409
simplify::move_bounds_to_generic_parameters(&mut generics);
14091410

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! This test used to ICE when trying to resolve the method call in the `test` function.
2+
3+
mod foo {
4+
pub trait Callable {
5+
type Output;
6+
fn call() -> Self::Output;
7+
}
8+
9+
impl<'a, V: ?Sized> Callable for &'a () {
10+
//~^ ERROR: `V` is not constrained
11+
type Output = ();
12+
}
13+
}
14+
use foo::*;
15+
16+
fn test<'a>() -> impl Sized {
17+
<&'a () as Callable>::call()
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/missing_method_in_impl_with_unconstrained_type_param.rs:9:14
3+
|
4+
LL | impl<'a, V: ?Sized> Callable for &'a () {
5+
| ^ unconstrained type parameter
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0207`.

tests/ui/dropck/unconstrained_const_param_on_drop.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained_const_param_on_drop.rs:3:6
3+
|
4+
LL | impl<const UNUSED: usize> Drop for Foo {}
5+
| ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter
6+
|
7+
= note: expressions using a const parameter must map each value to a distinct output value
8+
= note: proving the result of expressions other than the parameter are unique is not supported
9+
110
error[E0367]: `Drop` impl requires `the constant `_` has type `usize`` but the struct it is implemented for does not
211
--> $DIR/unconstrained_const_param_on_drop.rs:3:6
312
|
@@ -10,15 +19,6 @@ note: the implementor must specify the same requirement
1019
LL | struct Foo {}
1120
| ^^^^^^^^^^
1221

13-
error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates
14-
--> $DIR/unconstrained_const_param_on_drop.rs:3:6
15-
|
16-
LL | impl<const UNUSED: usize> Drop for Foo {}
17-
| ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter
18-
|
19-
= note: expressions using a const parameter must map each value to a distinct output value
20-
= note: proving the result of expressions other than the parameter are unique is not supported
21-
2222
error: aborting due to 2 previous errors
2323

2424
Some errors have detailed explanations: E0207, E0367.

tests/ui/impl-unused-tps.stderr

+24-24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/impl-unused-tps.rs:49:9
3+
|
4+
LL | impl<T, U, V> Foo<T> for T
5+
| ^ unconstrained type parameter
6+
7+
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
8+
--> $DIR/impl-unused-tps.rs:49:12
9+
|
10+
LL | impl<T, U, V> Foo<T> for T
11+
| ^ unconstrained type parameter
12+
13+
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
14+
--> $DIR/impl-unused-tps.rs:32:9
15+
|
16+
LL | impl<T, U> Bar for T {
17+
| ^ unconstrained type parameter
18+
19+
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
20+
--> $DIR/impl-unused-tps.rs:40:9
21+
|
22+
LL | impl<T, U> Bar for T
23+
| ^ unconstrained type parameter
24+
125
error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
226
--> $DIR/impl-unused-tps.rs:28:1
327
|
@@ -46,30 +70,6 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
4670
LL | impl<T, U> Foo<T> for [isize; 1] {
4771
| ^ unconstrained type parameter
4872

49-
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
50-
--> $DIR/impl-unused-tps.rs:32:9
51-
|
52-
LL | impl<T, U> Bar for T {
53-
| ^ unconstrained type parameter
54-
55-
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
56-
--> $DIR/impl-unused-tps.rs:40:9
57-
|
58-
LL | impl<T, U> Bar for T
59-
| ^ unconstrained type parameter
60-
61-
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
62-
--> $DIR/impl-unused-tps.rs:49:9
63-
|
64-
LL | impl<T, U, V> Foo<T> for T
65-
| ^ unconstrained type parameter
66-
67-
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
68-
--> $DIR/impl-unused-tps.rs:49:12
69-
|
70-
LL | impl<T, U, V> Foo<T> for T
71-
| ^ unconstrained type parameter
72-
7373
error: aborting due to 9 previous errors
7474

7575
Some errors have detailed explanations: E0119, E0207.

0 commit comments

Comments
 (0)