Skip to content

Commit 8c74a5d

Browse files
committedJun 14, 2023
Auto merge of #112625 - matthiaskrgr:rollup-jcobj3g, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #112584 (loongarch64-none*: Remove environment component from llvm target) - #112600 (Introduce a `Stable` trait to translate MIR to SMIR) - #112605 (Improve docs/clean up negative overlap functions) - #112611 (Error on unconstrained lifetime in RPITIT) - #112612 (Fix explicit-outlives-requirements lint span) - #112613 (Fix rustdoc-gui tests on Windows) - #112620 (Fix small typo) r? `@ghost` `@rustbot` modify labels: rollup
·
1.88.01.72.0
2 parents 0b475c7 + 3616388 commit 8c74a5d

25 files changed

+532
-407
lines changed
 

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@ pub(super) fn compare_impl_method<'tcx>(
4545
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
4646

4747
let _: Result<_, ErrorGuaranteed> = try {
48-
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
49-
compare_number_of_generics(tcx, impl_m, trait_m, false)?;
50-
compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
51-
compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
52-
compare_synthetic_generics(tcx, impl_m, trait_m)?;
53-
compare_asyncness(tcx, impl_m, trait_m)?;
48+
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
5449
compare_method_predicate_entailment(
5550
tcx,
5651
impl_m,
@@ -61,6 +56,26 @@ pub(super) fn compare_impl_method<'tcx>(
6156
};
6257
}
6358

59+
/// Checks a bunch of different properties of the impl/trait methods for
60+
/// compatibility, such as asyncness, number of argument, self receiver kind,
61+
/// and number of early- and late-bound generics.
62+
fn check_method_is_structurally_compatible<'tcx>(
63+
tcx: TyCtxt<'tcx>,
64+
impl_m: ty::AssocItem,
65+
trait_m: ty::AssocItem,
66+
impl_trait_ref: ty::TraitRef<'tcx>,
67+
delay: bool,
68+
) -> Result<(), ErrorGuaranteed> {
69+
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
70+
compare_number_of_generics(tcx, impl_m, trait_m, delay)?;
71+
compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
72+
compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
73+
compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
74+
compare_asyncness(tcx, impl_m, trait_m, delay)?;
75+
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
76+
Ok(())
77+
}
78+
6479
/// This function is best explained by example. Consider a trait with it's implementation:
6580
///
6681
/// ```rust
@@ -177,9 +192,6 @@ fn compare_method_predicate_entailment<'tcx>(
177192
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
178193
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
179194

180-
// Check region bounds.
181-
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?;
182-
183195
// Create obligations for each predicate declared by the impl
184196
// definition in the context of the trait's parameter
185197
// environment. We can't just use `impl_env.caller_bounds`,
@@ -534,6 +546,7 @@ fn compare_asyncness<'tcx>(
534546
tcx: TyCtxt<'tcx>,
535547
impl_m: ty::AssocItem,
536548
trait_m: ty::AssocItem,
549+
delay: bool,
537550
) -> Result<(), ErrorGuaranteed> {
538551
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
539552
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -544,11 +557,14 @@ fn compare_asyncness<'tcx>(
544557
// We don't know if it's ok, but at least it's already an error.
545558
}
546559
_ => {
547-
return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
548-
span: tcx.def_span(impl_m.def_id),
549-
method_name: trait_m.name,
550-
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
551-
}));
560+
return Err(tcx
561+
.sess
562+
.create_err(crate::errors::AsyncTraitImplShouldBeAsync {
563+
span: tcx.def_span(impl_m.def_id),
564+
method_name: trait_m.name,
565+
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
566+
})
567+
.emit_unless(delay));
552568
}
553569
};
554570
}
@@ -602,9 +618,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
602618

603619
// First, check a few of the same things as `compare_impl_method`,
604620
// just so we don't ICE during substitution later.
605-
compare_number_of_generics(tcx, impl_m, trait_m, true)?;
606-
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
607-
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
621+
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
608622

609623
let trait_to_impl_substs = impl_trait_ref.substs;
610624

@@ -1097,6 +1111,7 @@ fn compare_self_type<'tcx>(
10971111
impl_m: ty::AssocItem,
10981112
trait_m: ty::AssocItem,
10991113
impl_trait_ref: ty::TraitRef<'tcx>,
1114+
delay: bool,
11001115
) -> Result<(), ErrorGuaranteed> {
11011116
// Try to give more informative error messages about self typing
11021117
// mismatches. Note that any mismatch will also be detected
@@ -1145,7 +1160,7 @@ fn compare_self_type<'tcx>(
11451160
} else {
11461161
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
11471162
}
1148-
return Err(err.emit());
1163+
return Err(err.emit_unless(delay));
11491164
}
11501165

11511166
(true, false) => {
@@ -1166,7 +1181,7 @@ fn compare_self_type<'tcx>(
11661181
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
11671182
}
11681183

1169-
return Err(err.emit());
1184+
return Err(err.emit_unless(delay));
11701185
}
11711186
}
11721187

@@ -1352,6 +1367,7 @@ fn compare_number_of_method_arguments<'tcx>(
13521367
tcx: TyCtxt<'tcx>,
13531368
impl_m: ty::AssocItem,
13541369
trait_m: ty::AssocItem,
1370+
delay: bool,
13551371
) -> Result<(), ErrorGuaranteed> {
13561372
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
13571373
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1422,7 +1438,7 @@ fn compare_number_of_method_arguments<'tcx>(
14221438
),
14231439
);
14241440

1425-
return Err(err.emit());
1441+
return Err(err.emit_unless(delay));
14261442
}
14271443

14281444
Ok(())
@@ -1432,6 +1448,7 @@ fn compare_synthetic_generics<'tcx>(
14321448
tcx: TyCtxt<'tcx>,
14331449
impl_m: ty::AssocItem,
14341450
trait_m: ty::AssocItem,
1451+
delay: bool,
14351452
) -> Result<(), ErrorGuaranteed> {
14361453
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
14371454
// 1. Better messages for the span labels
@@ -1551,7 +1568,7 @@ fn compare_synthetic_generics<'tcx>(
15511568
}
15521569
_ => unreachable!(),
15531570
}
1554-
error_found = Some(err.emit());
1571+
error_found = Some(err.emit_unless(delay));
15551572
}
15561573
}
15571574
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }

‎compiler/rustc_hir_analysis/src/impl_wf_check.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,23 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
106106
if item.defaultness(tcx).has_value() {
107107
cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
108108
} else {
109-
Vec::new()
109+
vec![]
110110
}
111111
}
112-
ty::AssocKind::Fn | ty::AssocKind::Const => Vec::new(),
112+
ty::AssocKind::Fn => {
113+
if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
114+
&& item.defaultness(tcx).has_value()
115+
&& tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
116+
&& let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
117+
{
118+
table.values().copied().flat_map(|ty| {
119+
cgp::parameters_for(&ty.subst_identity(), true)
120+
}).collect()
121+
} else {
122+
vec![]
123+
}
124+
}
125+
ty::AssocKind::Const => vec![],
113126
}
114127
})
115128
.collect();

‎compiler/rustc_lint/src/builtin.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,12 +2124,16 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
21242124
}
21252125

21262126
let ty_generics = cx.tcx.generics_of(def_id);
2127+
let num_where_predicates = hir_generics
2128+
.predicates
2129+
.iter()
2130+
.filter(|predicate| predicate.in_where_clause())
2131+
.count();
21272132

21282133
let mut bound_count = 0;
21292134
let mut lint_spans = Vec::new();
21302135
let mut where_lint_spans = Vec::new();
2131-
let mut dropped_predicate_count = 0;
2132-
let num_predicates = hir_generics.predicates.len();
2136+
let mut dropped_where_predicate_count = 0;
21332137
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
21342138
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
21352139
match where_predicate {
@@ -2186,8 +2190,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
21862190
bound_count += bound_spans.len();
21872191

21882192
let drop_predicate = bound_spans.len() == bounds.len();
2189-
if drop_predicate {
2190-
dropped_predicate_count += 1;
2193+
if drop_predicate && in_where_clause {
2194+
dropped_where_predicate_count += 1;
21912195
}
21922196

21932197
if drop_predicate {
@@ -2196,7 +2200,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
21962200
} else if predicate_span.from_expansion() {
21972201
// Don't try to extend the span if it comes from a macro expansion.
21982202
where_lint_spans.push(predicate_span);
2199-
} else if i + 1 < num_predicates {
2203+
} else if i + 1 < num_where_predicates {
22002204
// If all the bounds on a predicate were inferable and there are
22012205
// further predicates, we want to eat the trailing comma.
22022206
let next_predicate_span = hir_generics.predicates[i + 1].span();
@@ -2224,9 +2228,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22242228
}
22252229
}
22262230

2227-
// If all predicates are inferable, drop the entire clause
2231+
// If all predicates in where clause are inferable, drop the entire clause
22282232
// (including the `where`)
2229-
if hir_generics.has_where_clause_predicates && dropped_predicate_count == num_predicates
2233+
if hir_generics.has_where_clause_predicates
2234+
&& dropped_where_predicate_count == num_where_predicates
22302235
{
22312236
let where_span = hir_generics.where_clause_span;
22322237
// Extend the where clause back to the closing `>` of the

‎compiler/rustc_smir/src/rustc_smir/mod.rs

Lines changed: 203 additions & 194 deletions
Large diffs are not rendered by default.

‎compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use super::{Target, TargetOptions};
33

44
pub fn target() -> Target {
55
Target {
6-
llvm_target: "loongarch64-unknown-none-softfloat".into(),
6+
llvm_target: "loongarch64-unknown-none".into(),
77
pointer_width: 64,
88
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
99
arch: "loongarch64".into(),

‎compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
2323
use rustc_middle::traits::DefiningAnchor;
2424
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
2525
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
26-
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
26+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
2727
use rustc_span::symbol::sym;
2828
use rustc_span::DUMMY_SP;
2929
use std::fmt::Debug;
@@ -170,8 +170,8 @@ fn overlap<'tcx>(
170170
overlap_mode: OverlapMode,
171171
) -> Option<OverlapResult<'tcx>> {
172172
if overlap_mode.use_negative_impl() {
173-
if negative_impl(tcx, impl1_def_id, impl2_def_id)
174-
|| negative_impl(tcx, impl2_def_id, impl1_def_id)
173+
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id)
174+
|| impl_intersection_has_negative_obligation(tcx, impl2_def_id, impl1_def_id)
175175
{
176176
return None;
177177
}
@@ -198,13 +198,21 @@ fn overlap<'tcx>(
198198
let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id);
199199
let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id);
200200

201-
let obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
201+
// Equate the headers to find their intersection (the general type, with infer vars,
202+
// that may apply both impls).
203+
let equate_obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
202204
debug!("overlap: unification check succeeded");
203205

204-
if overlap_mode.use_implicit_negative() {
205-
if implicit_negative(selcx, param_env, &impl1_header, impl2_header, obligations) {
206-
return None;
207-
}
206+
if overlap_mode.use_implicit_negative()
207+
&& impl_intersection_has_impossible_obligation(
208+
selcx,
209+
param_env,
210+
&impl1_header,
211+
impl2_header,
212+
equate_obligations,
213+
)
214+
{
215+
return None;
208216
}
209217

210218
// We toggle the `leak_check` by using `skip_leak_check` when constructing the
@@ -250,52 +258,38 @@ fn equate_impl_headers<'tcx>(
250258
result.map(|infer_ok| infer_ok.obligations).ok()
251259
}
252260

253-
/// Given impl1 and impl2 check if both impls can be satisfied by a common type (including
254-
/// where-clauses) If so, return false, otherwise return true, they are disjoint.
255-
fn implicit_negative<'cx, 'tcx>(
261+
/// Check if both impls can be satisfied by a common type by considering whether
262+
/// any of either impl's obligations is not known to hold.
263+
///
264+
/// For example, given these two impls:
265+
/// `impl From<MyLocalType> for Box<dyn Error>` (in my crate)
266+
/// `impl<E> From<E> for Box<dyn Error> where E: Error` (in libstd)
267+
///
268+
/// After replacing both impl headers with inference vars (which happens before
269+
/// this function is called), we get:
270+
/// `Box<dyn Error>: From<MyLocalType>`
271+
/// `Box<dyn Error>: From<?E>`
272+
///
273+
/// This gives us `?E = MyLocalType`. We then certainly know that `MyLocalType: Error`
274+
/// never holds in intercrate mode since a local impl does not exist, and a
275+
/// downstream impl cannot be added -- therefore can consider the intersection
276+
/// of the two impls above to be empty.
277+
///
278+
/// Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
279+
fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
256280
selcx: &mut SelectionContext<'cx, 'tcx>,
257281
param_env: ty::ParamEnv<'tcx>,
258282
impl1_header: &ty::ImplHeader<'tcx>,
259283
impl2_header: ty::ImplHeader<'tcx>,
260284
obligations: PredicateObligations<'tcx>,
261285
) -> bool {
262-
// There's no overlap if obligations are unsatisfiable or if the obligation negated is
263-
// satisfied.
264-
//
265-
// For example, given these two impl headers:
266-
//
267-
// `impl<'a> From<&'a str> for Box<dyn Error>`
268-
// `impl<E> From<E> for Box<dyn Error> where E: Error`
269-
//
270-
// So we have:
271-
//
272-
// `Box<dyn Error>: From<&'?a str>`
273-
// `Box<dyn Error>: From<?E>`
274-
//
275-
// After equating the two headers:
276-
//
277-
// `Box<dyn Error> = Box<dyn Error>`
278-
// So, `?E = &'?a str` and then given the where clause `&'?a str: Error`.
279-
//
280-
// If the obligation `&'?a str: Error` holds, it means that there's overlap. If that doesn't
281-
// hold we need to check if `&'?a str: !Error` holds, if doesn't hold there's overlap because
282-
// at some point an impl for `&'?a str: Error` could be added.
283-
debug!(
284-
"implicit_negative(impl1_header={:?}, impl2_header={:?}, obligations={:?})",
285-
impl1_header, impl2_header, obligations
286-
);
287286
let infcx = selcx.infcx;
288-
let opt_failing_obligation = impl1_header
289-
.predicates
290-
.iter()
291-
.copied()
292-
.chain(impl2_header.predicates)
293-
.map(|p| infcx.resolve_vars_if_possible(p))
294-
.map(|p| Obligation {
295-
cause: ObligationCause::dummy(),
296-
param_env,
297-
recursion_depth: 0,
298-
predicate: p,
287+
288+
let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates]
289+
.into_iter()
290+
.flatten()
291+
.map(|&predicate| {
292+
Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
299293
})
300294
.chain(obligations)
301295
.find(|o| !selcx.predicate_may_hold_fatal(o));
@@ -308,9 +302,27 @@ fn implicit_negative<'cx, 'tcx>(
308302
}
309303
}
310304

311-
/// Given impl1 and impl2 check if both impls are never satisfied by a common type (including
312-
/// where-clauses) If so, return true, they are disjoint and false otherwise.
313-
fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool {
305+
/// Check if both impls can be satisfied by a common type by considering whether
306+
/// any of first impl's obligations is known not to hold *via a negative predicate*.
307+
///
308+
/// For example, given these two impls:
309+
/// `struct MyCustomBox<T: ?Sized>(Box<T>);`
310+
/// `impl From<&str> for MyCustomBox<dyn Error>` (in my crate)
311+
/// `impl<E> From<E> for MyCustomBox<dyn Error> where E: Error` (in my crate)
312+
///
313+
/// After replacing the second impl's header with inference vars, we get:
314+
/// `MyCustomBox<dyn Error>: From<&str>`
315+
/// `MyCustomBox<dyn Error>: From<?E>`
316+
///
317+
/// This gives us `?E = &str`. We then try to prove the first impl's predicates
318+
/// after negating, giving us `&str: !Error`. This is a negative impl provided by
319+
/// libstd, and therefore we can guarantee for certain that libstd will never add
320+
/// a positive impl for `&str: Error` (without it being a breaking change).
321+
fn impl_intersection_has_negative_obligation(
322+
tcx: TyCtxt<'_>,
323+
impl1_def_id: DefId,
324+
impl2_def_id: DefId,
325+
) -> bool {
314326
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
315327

316328
// Create an infcx, taking the predicates of impl1 as assumptions:
@@ -336,57 +348,45 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b
336348
// Attempt to prove that impl2 applies, given all of the above.
337349
let selcx = &mut SelectionContext::new(&infcx);
338350
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
339-
let (subject2, obligations) =
351+
let (subject2, normalization_obligations) =
340352
impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs, |_, _| {
341353
ObligationCause::dummy()
342354
});
343355

344-
!equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
345-
}
346-
347-
fn equate<'tcx>(
348-
infcx: &InferCtxt<'tcx>,
349-
impl_env: ty::ParamEnv<'tcx>,
350-
subject1: ImplSubject<'tcx>,
351-
subject2: ImplSubject<'tcx>,
352-
obligations: impl Iterator<Item = PredicateObligation<'tcx>>,
353-
body_def_id: DefId,
354-
) -> bool {
355-
// do the impls unify? If not, not disjoint.
356-
let Ok(InferOk { obligations: more_obligations, .. }) =
356+
// do the impls unify? If not, then it's not currently possible to prove any
357+
// obligations about their intersection.
358+
let Ok(InferOk { obligations: equate_obligations, .. }) =
357359
infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2)
358360
else {
359361
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
360-
return true;
362+
return false;
361363
};
362364

363-
let opt_failing_obligation = obligations
364-
.into_iter()
365-
.chain(more_obligations)
366-
.find(|o| negative_impl_exists(infcx, o, body_def_id));
367-
368-
if let Some(failing_obligation) = opt_failing_obligation {
369-
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
370-
false
371-
} else {
372-
true
365+
for obligation in normalization_obligations.into_iter().chain(equate_obligations) {
366+
if negative_impl_exists(&infcx, &obligation, impl1_def_id) {
367+
debug!("overlap: obligation unsatisfiable {:?}", obligation);
368+
return true;
369+
}
373370
}
371+
372+
false
374373
}
375374

376-
/// Try to prove that a negative impl exist for the given obligation and its super predicates.
375+
/// Try to prove that a negative impl exist for the obligation or its supertraits.
376+
///
377+
/// If such a negative impl exists, then the obligation definitely must not hold
378+
/// due to coherence, even if it's not necessarily "knowable" in this crate. Any
379+
/// valid impl downstream would not be able to exist due to the overlapping
380+
/// negative impl.
377381
#[instrument(level = "debug", skip(infcx))]
378382
fn negative_impl_exists<'tcx>(
379383
infcx: &InferCtxt<'tcx>,
380384
o: &PredicateObligation<'tcx>,
381385
body_def_id: DefId,
382386
) -> bool {
383-
if resolve_negative_obligation(infcx.fork(), o, body_def_id) {
384-
return true;
385-
}
386-
387387
// Try to prove a negative obligation exists for super predicates
388388
for pred in util::elaborate(infcx.tcx, iter::once(o.predicate)) {
389-
if resolve_negative_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
389+
if prove_negated_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
390390
return true;
391391
}
392392
}
@@ -395,7 +395,7 @@ fn negative_impl_exists<'tcx>(
395395
}
396396

397397
#[instrument(level = "debug", skip(infcx))]
398-
fn resolve_negative_obligation<'tcx>(
398+
fn prove_negated_obligation<'tcx>(
399399
infcx: InferCtxt<'tcx>,
400400
o: &PredicateObligation<'tcx>,
401401
body_def_id: DefId,

‎compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
365365
}
366366

367367
if !candidate_set.ambiguous && no_candidates_apply {
368-
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
368+
let trait_ref = self.infcx.resolve_vars_if_possible(
369+
stack.obligation.predicate.skip_binder().trait_ref,
370+
);
369371
if !trait_ref.references_error() {
370372
let self_ty = trait_ref.self_ty();
371373
let (trait_desc, self_desc) = with_no_trimmed_paths!({

‎library/core/src/iter/sources/successors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ where
2222
Successors { next: first, succ }
2323
}
2424

25-
/// An new iterator where each successive item is computed based on the preceding one.
25+
/// A new iterator where each successive item is computed based on the preceding one.
2626
///
2727
/// This `struct` is created by the [`iter::successors()`] function.
2828
/// See its documentation for more.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.16.6
1+
0.16.7

‎src/tools/rustdoc-gui/tester.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ async function main(argv) {
201201
try {
202202
// This is more convenient that setting fields one by one.
203203
const args = [
204-
"--variable", "DOC_PATH", opts["doc_folder"], "--enable-fail-on-js-error",
205-
"--allow-file-access-from-files",
204+
"--variable", "DOC_PATH", opts["doc_folder"].split("\\").join("/"),
205+
"--enable-fail-on-js-error", "--allow-file-access-from-files",
206206
];
207207
if (opts["debug"]) {
208208
debug = true;

‎tests/rustdoc-gui/shortcuts.goml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ press-key: "Escape"
1313
assert-css: ("#help-button .popover", {"display": "none"})
1414
// Checking doc collapse and expand.
1515
// It should be displaying a "-":
16-
assert-text: ("#toggle-all-docs", "[\u2212]")
16+
assert-text: ("#toggle-all-docs", "[]")
1717
press-key: "-"
1818
wait-for-text: ("#toggle-all-docs", "[+]")
1919
assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
@@ -23,9 +23,9 @@ assert-text: ("#toggle-all-docs", "[+]")
2323
assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
2424
// Expanding now.
2525
press-key: "+"
26-
wait-for-text: ("#toggle-all-docs", "[\u2212]")
26+
wait-for-text: ("#toggle-all-docs", "[]")
2727
assert-attribute: ("#toggle-all-docs", {"class": ""})
2828
// Pressing it again shouldn't do anything.
2929
press-key: "+"
30-
assert-text: ("#toggle-all-docs", "[\u2212]")
30+
assert-text: ("#toggle-all-docs", "[]")
3131
assert-attribute: ("#toggle-all-docs", {"class": ""})

‎tests/rustdoc-gui/source-code-page.goml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,23 @@ call-function: ("check-colors", {
6464
compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y"))
6565
// Check the `href` property so that users can treat anchors as links.
6666
assert-property: (".src-line-numbers > a:nth-child(1)", {
67-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#1"
68-
})
67+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#1"
68+
}, ENDS_WITH)
6969
assert-property: (".src-line-numbers > a:nth-child(2)", {
70-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#2"
71-
})
70+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#2"
71+
}, ENDS_WITH)
7272
assert-property: (".src-line-numbers > a:nth-child(3)", {
73-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#3"
74-
})
73+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#3"
74+
}, ENDS_WITH)
7575
assert-property: (".src-line-numbers > a:nth-child(4)", {
76-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4"
77-
})
76+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#4"
77+
}, ENDS_WITH)
7878
assert-property: (".src-line-numbers > a:nth-child(5)", {
79-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#5"
80-
})
79+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#5"
80+
}, ENDS_WITH)
8181
assert-property: (".src-line-numbers > a:nth-child(6)", {
82-
"href": "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#6"
83-
})
82+
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#6"
83+
}, ENDS_WITH)
8484

8585
// Assert that the line numbers text is aligned to the right.
8686
assert-css: (".src-line-numbers", {"text-align": "right"})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0053]: method `early` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:58:27
3+
|
4+
LL | fn early<'late, T>(_: &'late ()) {}
5+
| - ^^^^^^^^^
6+
| | |
7+
| | expected type parameter `T`, found `()`
8+
| | help: change the parameter type to match the trait: `&'early T`
9+
| this type parameter
10+
|
11+
note: type in trait
12+
--> $DIR/method-signature-matches.rs:53:28
13+
|
14+
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
15+
| ^^^^^^^^^
16+
= note: expected signature `fn(&'early T)`
17+
found signature `fn(&())`
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0053`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0053]: method `owo` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:14:15
3+
|
4+
LL | fn owo(_: u8) {}
5+
| ^^
6+
| |
7+
| expected `()`, found `u8`
8+
| help: change the parameter type to match the trait: `()`
9+
|
10+
note: type in trait
11+
--> $DIR/method-signature-matches.rs:9:15
12+
|
13+
LL | fn owo(x: ()) -> impl Sized;
14+
| ^^
15+
= note: expected signature `fn(())`
16+
found signature `fn(u8)`
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0053`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0053]: method `owo` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:25:21
3+
|
4+
LL | async fn owo(_: u8) {}
5+
| ^^
6+
| |
7+
| expected `()`, found `u8`
8+
| help: change the parameter type to match the trait: `()`
9+
|
10+
note: type in trait
11+
--> $DIR/method-signature-matches.rs:20:21
12+
|
13+
LL | async fn owo(x: ()) {}
14+
| ^^
15+
= note: expected signature `fn(()) -> _`
16+
found signature `fn(u8) -> _`
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0053`.
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,62 @@
11
// edition: 2021
2+
// revisions: mismatch mismatch_async too_many too_few lt
23

34
#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
45
#![allow(incomplete_features)]
56

7+
#[cfg(mismatch)]
68
trait Uwu {
79
fn owo(x: ()) -> impl Sized;
810
}
911

12+
#[cfg(mismatch)]
1013
impl Uwu for () {
1114
fn owo(_: u8) {}
12-
//~^ ERROR method `owo` has an incompatible type for trait
15+
//[mismatch]~^ ERROR method `owo` has an incompatible type for trait
1316
}
1417

18+
#[cfg(mismatch_async)]
1519
trait AsyncUwu {
1620
async fn owo(x: ()) {}
1721
}
1822

23+
#[cfg(mismatch_async)]
1924
impl AsyncUwu for () {
2025
async fn owo(_: u8) {}
21-
//~^ ERROR method `owo` has an incompatible type for trait
26+
//[mismatch_async]~^ ERROR method `owo` has an incompatible type for trait
2227
}
2328

29+
#[cfg(too_many)]
2430
trait TooMuch {
2531
fn calm_down_please() -> impl Sized;
2632
}
2733

34+
#[cfg(too_many)]
2835
impl TooMuch for () {
2936
fn calm_down_please(_: (), _: (), _: ()) {}
30-
//~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
37+
//[too_many]~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
3138
}
3239

40+
#[cfg(too_few)]
3341
trait TooLittle {
3442
fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
3543
}
3644

45+
#[cfg(too_few)]
3746
impl TooLittle for () {
3847
fn come_on_a_little_more_effort() {}
39-
//~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
48+
//[too_few]~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
4049
}
4150

51+
#[cfg(lt)]
4252
trait Lifetimes {
4353
fn early<'early, T>(x: &'early T) -> impl Sized;
4454
}
4555

56+
#[cfg(lt)]
4657
impl Lifetimes for () {
4758
fn early<'late, T>(_: &'late ()) {}
48-
//~^ ERROR method `early` has an incompatible type for trait
59+
//[lt]~^ ERROR method `early` has an incompatible type for trait
4960
}
5061

5162
fn main() {}

‎tests/ui/impl-trait/in-trait/method-signature-matches.stderr

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
2+
--> $DIR/method-signature-matches.rs:47:5
3+
|
4+
LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
5+
| ---------------- trait requires 3 parameters
6+
...
7+
LL | fn come_on_a_little_more_effort() {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0050`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
2+
--> $DIR/method-signature-matches.rs:36:28
3+
|
4+
LL | fn calm_down_please() -> impl Sized;
5+
| ------------------------------------ trait requires 0 parameters
6+
...
7+
LL | fn calm_down_please(_: (), _: (), _: ()) {}
8+
| ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0050`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained-lt.rs:10:6
3+
|
4+
LL | impl<'a, T> Foo for T {
5+
| ^^ unconstrained lifetime parameter
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0207`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained-lt.rs:10:6
3+
|
4+
LL | impl<'a, T> Foo for T {
5+
| ^^ unconstrained lifetime parameter
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0207`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
2+
// revisions: current next
3+
4+
#![feature(return_position_impl_trait_in_trait)]
5+
6+
trait Foo {
7+
fn test() -> impl Sized;
8+
}
9+
10+
impl<'a, T> Foo for T {
11+
//~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
12+
13+
fn test() -> &'a () { &() }
14+
}
15+
16+
fn main() {}

‎tests/ui/rust-2018/edition-lint-infer-outlives.fixed

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,4 +801,10 @@ where
801801
yoo: &'a U
802802
}
803803

804+
// https://github.com/rust-lang/rust/issues/105150
805+
struct InferredWhereBoundWithInlineBound<'a, T: ?Sized>
806+
{
807+
data: &'a T,
808+
}
809+
804810
fn main() {}

‎tests/ui/rust-2018/edition-lint-infer-outlives.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,4 +801,12 @@ where
801801
yoo: &'a U
802802
}
803803

804+
// https://github.com/rust-lang/rust/issues/105150
805+
struct InferredWhereBoundWithInlineBound<'a, T: ?Sized>
806+
//~^ ERROR outlives requirements can be inferred
807+
where T: 'a,
808+
{
809+
data: &'a T,
810+
}
811+
804812
fn main() {}

‎tests/ui/rust-2018/edition-lint-infer-outlives.stderr

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ note: the lint level is defined here
1010
LL | #![deny(explicit_outlives_requirements)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13+
error: outlives requirements can be inferred
14+
--> $DIR/edition-lint-infer-outlives.rs:805:56
15+
|
16+
LL | struct InferredWhereBoundWithInlineBound<'a, T: ?Sized>
17+
| ________________________________________________________^
18+
LL | |
19+
LL | | where T: 'a,
20+
| |________________^ help: remove this bound
21+
1322
error: outlives requirements can be inferred
1423
--> $DIR/edition-lint-infer-outlives.rs:26:31
1524
|
@@ -922,5 +931,5 @@ error: outlives requirements can be inferred
922931
LL | union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug {
923932
| ^^^^^^^^ help: remove this bound
924933

925-
error: aborting due to 153 previous errors
934+
error: aborting due to 154 previous errors
926935

0 commit comments

Comments
 (0)
Please sign in to comment.