Skip to content

Commit 5229b23

Browse files
committed
Taint projection selection in the presence of unconstrained parameters on selected impls
1 parent 3dcdbcd commit 5229b23

21 files changed

+128
-221
lines changed

Diff for: compiler/rustc_middle/src/traits/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::ty::GenericArgsRef;
1414
use crate::ty::{self, AdtKind, Ty};
1515

1616
use rustc_data_structures::sync::Lrc;
17-
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
17+
use rustc_errors::{Applicability, Diag, EmissionGuarantee, ErrorGuaranteed};
1818
use rustc_hir as hir;
1919
use rustc_hir::def_id::DefId;
2020
use rustc_hir::HirId;
@@ -572,6 +572,12 @@ pub enum SelectionError<'tcx> {
572572
ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
573573
}
574574

575+
impl From<ErrorGuaranteed> for SelectionError<'_> {
576+
fn from(guar: ErrorGuaranteed) -> Self {
577+
Self::Overflow(guar.into())
578+
}
579+
}
580+
575581
#[derive(Clone, Debug, TypeVisitable)]
576582
pub struct SignatureMismatchData<'tcx> {
577583
pub found_trait_ref: ty::TraitRef<'tcx>,

Diff for: compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_middle::ty::{
2020
};
2121
use rustc_middle::{bug, span_bug};
2222
use rustc_span::def_id::DefId;
23+
use rustc_span::ErrorGuaranteed;
2324

2425
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
2526
use crate::traits::util::{self, closure_trait_ref_and_return_type};
@@ -61,7 +62,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
6162
}
6263

6364
ImplCandidate(impl_def_id) => {
64-
ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
65+
ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id)?)
6566
}
6667

6768
AutoImplCandidate => {
@@ -116,7 +117,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
116117
}
117118

118119
TraitAliasCandidate => {
119-
let data = self.confirm_trait_alias_candidate(obligation);
120+
let data = self.confirm_trait_alias_candidate(obligation)?;
120121
ImplSource::Builtin(BuiltinImplSource::Misc, data)
121122
}
122123

@@ -421,7 +422,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
421422

422423
let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
423424
let types = self.constituent_types_for_ty(self_ty)?;
424-
Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
425+
Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)?)
425426
}
426427

427428
/// See `confirm_auto_impl_candidate`.
@@ -430,21 +431,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
430431
obligation: &PolyTraitObligation<'tcx>,
431432
trait_def_id: DefId,
432433
nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
433-
) -> Vec<PredicateObligation<'tcx>> {
434+
) -> Result<Vec<PredicateObligation<'tcx>>, ErrorGuaranteed> {
434435
debug!(?nested, "vtable_auto_impl");
435436
ensure_sufficient_stack(|| {
436437
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
437438

438439
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
439440
let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref);
440-
let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
441+
let trait_obligations = self.impl_or_trait_obligations(
441442
&cause,
442443
obligation.recursion_depth + 1,
443444
obligation.param_env,
444445
trait_def_id,
445446
trait_ref.args,
446447
obligation.predicate,
447-
);
448+
)?;
448449

449450
let mut obligations = self.collect_predicates_for_types(
450451
obligation.param_env,
@@ -460,15 +461,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
460461

461462
debug!(?obligations, "vtable_auto_impl");
462463

463-
obligations
464+
Ok(obligations)
464465
})
465466
}
466467

467468
fn confirm_impl_candidate(
468469
&mut self,
469470
obligation: &PolyTraitObligation<'tcx>,
470471
impl_def_id: DefId,
471-
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
472+
) -> Result<ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, ErrorGuaranteed> {
472473
debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
473474

474475
// First, create the generic parameters by matching the impl again,
@@ -495,7 +496,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
495496
recursion_depth: usize,
496497
param_env: ty::ParamEnv<'tcx>,
497498
parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
498-
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
499+
) -> Result<ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, ErrorGuaranteed> {
499500
debug!(?impl_def_id, ?args, ?recursion_depth, "vtable_impl");
500501

501502
let mut impl_obligations = self.impl_or_trait_obligations(
@@ -505,7 +506,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
505506
impl_def_id,
506507
args.value,
507508
parent_trait_pred,
508-
);
509+
)?;
509510

510511
debug!(?impl_obligations, "vtable_impl");
511512

@@ -516,7 +517,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
516517
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
517518
impl_obligations.extend(args.obligations);
518519

519-
ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations }
520+
Ok(ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations })
520521
}
521522

522523
fn confirm_object_candidate(
@@ -737,7 +738,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
737738
fn confirm_trait_alias_candidate(
738739
&mut self,
739740
obligation: &PolyTraitObligation<'tcx>,
740-
) -> Vec<PredicateObligation<'tcx>> {
741+
) -> Result<Vec<PredicateObligation<'tcx>>, ErrorGuaranteed> {
741742
debug!(?obligation, "confirm_trait_alias_candidate");
742743

743744
let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
@@ -1377,7 +1378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13771378
new_obligation.param_env,
13781379
obligation.predicate,
13791380
)
1380-
});
1381+
})?;
13811382
nested.extend(obligations.nested);
13821383
}
13831384

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use rustc_middle::ty::GenericArgsRef;
4949
use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast};
5050
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
5151
use rustc_span::symbol::sym;
52+
use rustc_span::ErrorGuaranteed;
5253
use rustc_span::Symbol;
5354

5455
use std::cell::{Cell, RefCell};
@@ -2737,7 +2738,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
27372738
def_id: DefId, // of impl or trait
27382739
args: GenericArgsRef<'tcx>, // for impl or trait
27392740
parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
2740-
) -> Vec<PredicateObligation<'tcx>> {
2741+
) -> Result<Vec<PredicateObligation<'tcx>>, ErrorGuaranteed> {
27412742
let tcx = self.tcx();
27422743

27432744
// To allow for one-pass evaluation of the nested obligation,
@@ -2755,6 +2756,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
27552756
// `$1: Copy`, so we must ensure the obligations are emitted in
27562757
// that order.
27572758
let predicates = tcx.predicates_of(def_id);
2759+
predicates.errored_due_to_unconstrained_params?;
27582760
assert_eq!(predicates.parent, None);
27592761
let predicates = predicates.instantiate_own(tcx, args);
27602762
let mut obligations = Vec::with_capacity(predicates.len());
@@ -2787,7 +2789,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
27872789
});
27882790
}
27892791

2790-
obligations
2792+
Ok(obligations)
27912793
}
27922794
}
27932795

Diff for: tests/crashes/123141.rs

-23
This file was deleted.

Diff for: tests/crashes/125874.rs

-22
This file was deleted.

Diff for: tests/crashes/126942.rs

-11
This file was deleted.

Diff for: tests/ui/associated-item/unconstrained_impl_param.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//! This test used to ICE during the normalization of
2+
//! `I`'s type, because of the mismatch of generic parameters
3+
//! on the impl with the generic parameters the projection can
4+
//! fulfill.
5+
6+
struct Thing;
7+
8+
pub trait Every {
9+
type Assoc;
10+
}
11+
impl<T: ?Sized> Every for Thing {
12+
//~^ ERROR: `T` is not constrained
13+
type Assoc = T;
14+
}
15+
16+
static I: <Thing as Every>::Assoc = 3;
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained_impl_param.rs:11:6
3+
|
4+
LL | impl<T: ?Sized> Every for Thing {
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`.

Diff for: tests/ui/generic-associated-types/bugs/issue-87735.stderr

+16-62
Original file line numberDiff line numberDiff line change
@@ -22,73 +22,27 @@ help: consider adding an explicit lifetime bound
2222
LL | type Output<'a> = FooRef<'a, U> where Self: 'a, U: 'a;
2323
| +++++++
2424

25-
error[E0309]: the parameter type `T` may not live long enough
26-
--> $DIR/issue-87735.rs:31:15
25+
error[E0599]: no method named `as_ref2` found for struct `Foo` in the current scope
26+
--> $DIR/issue-87735.rs:43:14
2727
|
28-
LL | impl<'b, T, U> AsRef2 for Foo<T>
29-
| -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
30-
...
31-
LL | T: AsRef2<Output<'b> = &'b [U]>,
32-
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
33-
|
34-
note: ...that is required by this bound
35-
--> $DIR/issue-87735.rs:7:31
36-
|
37-
LL | type Output<'a> where Self: 'a;
38-
| ^^
39-
help: consider adding an explicit lifetime bound
40-
|
41-
LL | T: AsRef2<Output<'b> = &'b [U]> + 'b,
42-
| ++++
43-
44-
error[E0309]: the parameter type `T` may not live long enough
45-
--> $DIR/issue-87735.rs:36:31
46-
|
47-
LL | impl<'b, T, U> AsRef2 for Foo<T>
48-
| -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
28+
LL | struct Foo<T>(T);
29+
| ------------- method `as_ref2` not found for this struct
4930
...
50-
LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
51-
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
31+
LL | dbg!(foo.as_ref2());
32+
| ^^^^^^^ method not found in `Foo<Vec<{integer}>>`
5233
|
53-
note: ...that is required by this bound
54-
--> $DIR/issue-87735.rs:7:31
34+
= help: items from traits can only be used if the trait is implemented and in scope
35+
note: `AsRef2` defines an item `as_ref2`, perhaps you need to implement it
36+
--> $DIR/issue-87735.rs:6:1
5537
|
56-
LL | type Output<'a> where Self: 'a;
57-
| ^^
58-
help: consider adding an explicit lifetime bound
38+
LL | pub trait AsRef2 {
39+
| ^^^^^^^^^^^^^^^^
40+
help: one of the expressions' fields has a method of the same name
5941
|
60-
LL | T: AsRef2<Output<'b> = &'b [U]> + 'b,
61-
| ++++
62-
63-
error: lifetime may not live long enough
64-
--> $DIR/issue-87735.rs:37:5
65-
|
66-
LL | impl<'b, T, U> AsRef2 for Foo<T>
67-
| -- lifetime `'b` defined here
68-
...
69-
LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
70-
| -- lifetime `'a` defined here
71-
LL | FooRef(self.0.as_ref2())
72-
| ^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
73-
|
74-
= help: consider adding the following bound: `'b: 'a`
75-
76-
error: lifetime may not live long enough
77-
--> $DIR/issue-87735.rs:37:12
78-
|
79-
LL | impl<'b, T, U> AsRef2 for Foo<T>
80-
| -- lifetime `'b` defined here
81-
...
82-
LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
83-
| -- lifetime `'a` defined here
84-
LL | FooRef(self.0.as_ref2())
85-
| ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
86-
|
87-
= help: consider adding the following bound: `'a: 'b`
88-
89-
help: `'b` and `'a` must be the same: replace one with the other
42+
LL | dbg!(foo.0.as_ref2());
43+
| ++
9044

91-
error: aborting due to 6 previous errors
45+
error: aborting due to 3 previous errors
9246

93-
Some errors have detailed explanations: E0207, E0309.
47+
Some errors have detailed explanations: E0207, E0309, E0599.
9448
For more information about an error, try `rustc --explain E0207`.

Diff for: tests/ui/impl-trait/in-trait/refine-resolution-errors.rs

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ impl<T: ?Sized> Mirror for () {
1313

1414
pub trait First {
1515
async fn first() -> <() as Mirror>::Assoc;
16-
//~^ ERROR type annotations needed
1716
}
1817

1918
impl First for () {

Diff for: tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr

+2-9
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
44
LL | impl<T: ?Sized> Mirror for () {
55
| ^ unconstrained type parameter
66

7-
error[E0282]: type annotations needed
8-
--> $DIR/refine-resolution-errors.rs:15:5
9-
|
10-
LL | async fn first() -> <() as Mirror>::Assoc;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to 1 previous error
148

15-
Some errors have detailed explanations: E0207, E0282.
16-
For more information about an error, try `rustc --explain E0207`.
9+
For more information about this error, try `rustc --explain E0207`.

Diff for: tests/ui/impl-trait/issues/issue-87340.rs

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ impl<T> X for () {
99
//~^ ERROR `T` is not constrained by the impl trait, self type, or predicates
1010
type I = impl Sized;
1111
fn f() -> Self::I {}
12-
//~^ ERROR type annotations needed
13-
//~| ERROR type annotations needed
1412
}
1513

1614
fn main() {}

0 commit comments

Comments
 (0)