Skip to content

Commit f4e04a9

Browse files
committed
Use deep reject again
1 parent 9961747 commit f4e04a9

File tree

7 files changed

+82
-160
lines changed

7 files changed

+82
-160
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -380,54 +380,44 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
380380
assert!(!self_ty.has_infer());
381381

382382
// We don't just call the normal normalization routine here as we can't provide the
383-
// correct `ParamEnv` and it seems dubious to invoke arbitrary trait solving under
383+
// correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
384384
// the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
385385
// this just to make resolution a little bit smarter.
386386
let self_ty = self.tcx.expand_free_alias_tys(self_ty);
387387
debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
388388

389-
// We make an infcx and replace any escaping vars with placeholders so that IAT res
390-
// with type/const bound vars in arguments is slightly smarter. `for<T> <Foo<T>>::IAT`
391-
// would otherwise unify with `impl Foo<u8>` when ideally we would not.
392-
let infcx = self.tcx().infer_ctxt().build(TypingMode::non_body_analysis());
393-
let mut universes = if self_ty.has_escaping_bound_vars() {
394-
vec![None; self_ty.outer_exclusive_binder().as_usize()]
395-
} else {
396-
vec![]
397-
};
398-
let candidates =
399-
rustc_trait_selection::traits::with_replaced_escaping_bound_vars(
400-
&infcx,
401-
&mut universes,
402-
self_ty,
403-
|self_ty| {
404-
candidates
405-
.into_iter()
406-
.filter(|&InherentAssocCandidate { impl_, .. }| {
407-
let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
408-
409-
// See comment on doing this operation for `self_ty`
410-
let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
411-
debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
412-
413-
// We treat parameters in the self ty as rigid and parameters in the impl ty as infers
414-
// because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
415-
// `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
416-
//
417-
// We don't really care about a depth limit here because we're only working with user-written
418-
// types and if they wrote a type that would take hours to walk then that's kind of on them. On
419-
// the other hand the default depth limit is relatively low and could realistically be hit by
420-
// users in normal cases.
421-
//
422-
// `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
423-
// where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
424-
// be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
425-
ty::DeepRejectCtxt::relate_rigid_infer(self.tcx)
426-
.types_may_unify_with_depth(self_ty, impl_ty, usize::MAX)
427-
})
428-
.collect()
429-
},
430-
);
389+
let candidates = candidates
390+
.into_iter()
391+
.filter(|&InherentAssocCandidate { impl_, .. }| {
392+
let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
393+
394+
// See comment on doing this operation for `self_ty`
395+
let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
396+
debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
397+
398+
// We treat parameters in the self ty as rigid and parameters in the impl ty as infers
399+
// because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
400+
// `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
401+
//
402+
// We don't really care about a depth limit here because we're only working with user-written
403+
// types and if they wrote a type that would take hours to walk then that's kind of on them. On
404+
// the other hand the default depth limit is relatively low and could realistically be hit by
405+
// users in normal cases.
406+
//
407+
// `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
408+
// where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
409+
// be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
410+
//
411+
// Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
412+
// resolution, but it probably won't come up in practice and it would be backwards compatible
413+
// to switch over to doing that.
414+
ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
415+
self_ty,
416+
impl_ty,
417+
usize::MAX,
418+
)
419+
})
420+
.collect();
431421

432422
(candidates, vec![])
433423
}

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -322,59 +322,52 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
322322
) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
323323
let tcx = self.tcx();
324324
let infcx = &self.infcx;
325+
let mut fulfillment_errors = vec![];
326+
327+
let mut filter_iat_candidate = |self_ty, impl_| {
328+
let ocx = ObligationCtxt::new_with_diagnostics(self);
329+
let self_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, self_ty);
330+
331+
let impl_args = infcx.fresh_args_for_item(span, impl_);
332+
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
333+
let impl_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_ty);
334+
335+
// Check that the self types can be related.
336+
if ocx.eq(&ObligationCause::dummy(), self.param_env, impl_ty, self_ty).is_err() {
337+
return false;
338+
}
339+
340+
// Check whether the impl imposes obligations we have to worry about.
341+
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
342+
let impl_bounds = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_bounds);
343+
let impl_obligations = traits::predicates_for_generics(
344+
|_, _| ObligationCause::dummy(),
345+
self.param_env,
346+
impl_bounds,
347+
);
348+
ocx.register_obligations(impl_obligations);
349+
350+
let mut errors = ocx.select_where_possible();
351+
if !errors.is_empty() {
352+
fulfillment_errors.append(&mut errors);
353+
return false;
354+
}
355+
356+
true
357+
};
325358

326359
let mut universes = if self_ty.has_escaping_bound_vars() {
327360
vec![None; self_ty.outer_exclusive_binder().as_usize()]
328361
} else {
329362
vec![]
330363
};
331364

332-
let mut fulfillment_errors = vec![];
333365
let candidates =
334366
traits::with_replaced_escaping_bound_vars(infcx, &mut universes, self_ty, |self_ty| {
335367
candidates
336368
.into_iter()
337369
.filter(|&InherentAssocCandidate { impl_, .. }| {
338-
infcx.probe(|_| {
339-
let ocx = ObligationCtxt::new_with_diagnostics(self);
340-
let self_ty =
341-
ocx.normalize(&ObligationCause::dummy(), self.param_env, self_ty);
342-
343-
let impl_args = infcx.fresh_args_for_item(span, impl_);
344-
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
345-
let impl_ty =
346-
ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_ty);
347-
348-
// Check that the self types can be related.
349-
if ocx
350-
.eq(&ObligationCause::dummy(), self.param_env, impl_ty, self_ty)
351-
.is_err()
352-
{
353-
return false;
354-
}
355-
356-
// Check whether the impl imposes obligations we have to worry about.
357-
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
358-
let impl_bounds = ocx.normalize(
359-
&ObligationCause::dummy(),
360-
self.param_env,
361-
impl_bounds,
362-
);
363-
let impl_obligations = traits::predicates_for_generics(
364-
|_, _| ObligationCause::dummy(),
365-
self.param_env,
366-
impl_bounds,
367-
);
368-
ocx.register_obligations(impl_obligations);
369-
370-
let mut errors = ocx.select_where_possible();
371-
if !errors.is_empty() {
372-
fulfillment_errors.append(&mut errors);
373-
return false;
374-
}
375-
376-
true
377-
})
370+
infcx.probe(|_| filter_iat_candidate(self_ty, impl_))
378371
})
379372
.collect()
380373
});

tests/crashes/138131.rs

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/ui/associated-inherent-types/bound_vars_in_args.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ impl<T: Sized> Foo<T> {
1515
}
1616

1717
struct Bar
18-
//~^ ERROR: the size for values of type `T` cannot be known at compilation time
19-
//~| ERROR: the size for values of type `T` cannot be known at compilation time
2018
where
2119
for<T> Foo<T>::IAT: Sized;
20+
//~^ ERROR: multiple applicable items in scope
2221

2322
fn main() {}
Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,20 @@
1-
error[E0277]: the size for values of type `T` cannot be known at compilation time
2-
--> $DIR/bound_vars_in_args.rs:17:1
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/bound_vars_in_args.rs:19:20
33
|
4-
LL | struct Bar
5-
| ^^^^^^^^^^ doesn't have a size known at compile-time
4+
LL | for<T> Foo<T>::IAT: Sized;
5+
| ^^^ multiple `IAT` found
66
|
7-
= help: the trait `Sized` is not implemented for `T`
8-
note: required by a bound in `Foo<T>::IAT`
9-
--> $DIR/bound_vars_in_args.rs:13:9
7+
note: candidate #1 is defined in an impl for the type `Foo<[u8]>`
8+
--> $DIR/bound_vars_in_args.rs:10:5
109
|
11-
LL | impl<T: Sized> Foo<T> {
12-
| ^^^^^ required by this bound in `Foo<T>::IAT`
1310
LL | type IAT = u8;
14-
| --- required by a bound in this associated type
15-
16-
error[E0277]: the size for values of type `T` cannot be known at compilation time
17-
--> $DIR/bound_vars_in_args.rs:17:1
18-
|
19-
LL | / struct Bar
20-
LL | |
21-
LL | |
22-
LL | | where
23-
LL | | for<T> Foo<T>::IAT: Sized;
24-
| |______________________________^ doesn't have a size known at compile-time
25-
|
26-
= help: the trait `Sized` is not implemented for `T`
27-
note: required by a bound in `Foo<T>::IAT`
28-
--> $DIR/bound_vars_in_args.rs:13:9
11+
| ^^^^^^^^
12+
note: candidate #2 is defined in an impl for the type `Foo<T>`
13+
--> $DIR/bound_vars_in_args.rs:14:5
2914
|
30-
LL | impl<T: Sized> Foo<T> {
31-
| ^^^^^ required by this bound in `Foo<T>::IAT`
3215
LL | type IAT = u8;
33-
| --- required by a bound in this associated type
16+
| ^^^^^^^^
3417

35-
error: aborting due to 2 previous errors
18+
error: aborting due to 1 previous error
3619

37-
For more information about this error, try `rustc --explain E0277`.
20+
For more information about this error, try `rustc --explain E0034`.

tests/ui/associated-inherent-types/issue-109299-1.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ impl Lexer<i32> {
88
}
99

1010
type X = impl for<T> Fn() -> Lexer<T>::Cursor;
11-
//~^ ERROR associated type `Cursor` not found for `Lexer<T>` in the current scope
12-
//~| ERROR associated type `Cursor` not found for `Lexer<T>` in the current scope
13-
//~| ERROR: unconstrained opaque type
11+
//~^ ERROR: unconstrained opaque type
1412

1513
fn main() {}

tests/ui/associated-inherent-types/issue-109299-1.stderr

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,5 @@ LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
66
|
77
= note: `X` must be used in combination with a concrete type within the same crate
88

9-
error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current scope
10-
--> $DIR/issue-109299-1.rs:10:40
11-
|
12-
LL | struct Lexer<T>(T);
13-
| --------------- associated type `Cursor` not found for this struct
14-
...
15-
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
16-
| ^^^^^^ associated item not found in `Lexer<T>`
17-
|
18-
= note: the associated type was found for
19-
- `Lexer<i32>`
20-
21-
error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current scope
22-
--> $DIR/issue-109299-1.rs:10:40
23-
|
24-
LL | struct Lexer<T>(T);
25-
| --------------- associated type `Cursor` not found for this struct
26-
...
27-
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
28-
| ^^^^^^ associated item not found in `Lexer<T>`
29-
|
30-
= note: the associated type was found for
31-
- `Lexer<i32>`
32-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
33-
34-
error: aborting due to 3 previous errors
9+
error: aborting due to 1 previous error
3510

36-
For more information about this error, try `rustc --explain E0220`.

0 commit comments

Comments
 (0)