Skip to content

Commit e7be356

Browse files
authored
Rollup merge of #126620 - oli-obk:taint_errors, r=fee1-dead
Actually taint InferCtxt when a fulfillment error is emitted And avoid checking the global error counter fixes #122044 fixes #123255 fixes #123276 fixes #125799
2 parents 3d5d7a2 + e4c9a8c commit e7be356

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+595
-238
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,7 @@ where
119119

120120
let errors = wfcx.select_all_or_error();
121121
if !errors.is_empty() {
122-
let err = infcx.err_ctxt().report_fulfillment_errors(errors);
123-
if tcx.dcx().has_errors().is_some() {
124-
return Err(err);
125-
} else {
126-
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs
127-
// causes an delayed bug during normalization, without reporting an error, so we need
128-
// to act as if no error happened, in order to let our callers continue and report an
129-
// error later in check_impl_items_against_trait.
130-
return Ok(());
131-
}
122+
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
132123
}
133124

134125
debug!(?assumed_wf_types);

compiler/rustc_hir_typeck/src/writeback.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
793793
}
794794

795795
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
796-
if let Some(guar) = self.fcx.dcx().has_errors() {
796+
if let Some(guar) = self.fcx.tainted_by_errors() {
797797
guar
798798
} else {
799799
self.fcx

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+103-85
Original file line numberDiff line numberDiff line change
@@ -2776,97 +2776,115 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27762776
let mut this = "this bound";
27772777
let mut note = None;
27782778
let mut help = None;
2779-
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
2780-
&& let ty::ClauseKind::Trait(trait_pred) = clause
2781-
{
2782-
let def_id = trait_pred.def_id();
2783-
let visible_item = if let Some(local) = def_id.as_local() {
2784-
// Check for local traits being reachable.
2785-
let vis = &tcx.resolutions(()).effective_visibilities;
2786-
// Account for non-`pub` traits in the root of the local crate.
2787-
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
2788-
vis.is_reachable(local) || is_locally_reachable
2789-
} else {
2790-
// Check for foreign traits being reachable.
2791-
tcx.visible_parent_map(()).get(&def_id).is_some()
2792-
};
2793-
if tcx.is_lang_item(def_id, LangItem::Sized) {
2794-
// Check if this is an implicit bound, even in foreign crates.
2795-
if tcx
2796-
.generics_of(item_def_id)
2797-
.own_params
2798-
.iter()
2799-
.any(|param| tcx.def_span(param.def_id) == span)
2800-
{
2801-
a = "an implicit `Sized`";
2802-
this = "the implicit `Sized` requirement on this type parameter";
2803-
}
2804-
if let Some(hir::Node::TraitItem(hir::TraitItem {
2805-
generics,
2806-
kind: hir::TraitItemKind::Type(bounds, None),
2807-
..
2808-
})) = tcx.hir().get_if_local(item_def_id)
2809-
// Do not suggest relaxing if there is an explicit `Sized` obligation.
2810-
&& !bounds.iter()
2811-
.filter_map(|bound| bound.trait_ref())
2812-
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
2813-
{
2814-
let (span, separator) = if let [.., last] = bounds {
2815-
(last.span().shrink_to_hi(), " +")
2779+
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
2780+
match clause {
2781+
ty::ClauseKind::Trait(trait_pred) => {
2782+
let def_id = trait_pred.def_id();
2783+
let visible_item = if let Some(local) = def_id.as_local() {
2784+
// Check for local traits being reachable.
2785+
let vis = &tcx.resolutions(()).effective_visibilities;
2786+
// Account for non-`pub` traits in the root of the local crate.
2787+
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
2788+
vis.is_reachable(local) || is_locally_reachable
28162789
} else {
2817-
(generics.span.shrink_to_hi(), ":")
2790+
// Check for foreign traits being reachable.
2791+
tcx.visible_parent_map(()).get(&def_id).is_some()
28182792
};
2819-
err.span_suggestion_verbose(
2820-
span,
2821-
"consider relaxing the implicit `Sized` restriction",
2822-
format!("{separator} ?Sized"),
2823-
Applicability::MachineApplicable,
2824-
);
2793+
if tcx.is_lang_item(def_id, LangItem::Sized) {
2794+
// Check if this is an implicit bound, even in foreign crates.
2795+
if tcx
2796+
.generics_of(item_def_id)
2797+
.own_params
2798+
.iter()
2799+
.any(|param| tcx.def_span(param.def_id) == span)
2800+
{
2801+
a = "an implicit `Sized`";
2802+
this =
2803+
"the implicit `Sized` requirement on this type parameter";
2804+
}
2805+
if let Some(hir::Node::TraitItem(hir::TraitItem {
2806+
generics,
2807+
kind: hir::TraitItemKind::Type(bounds, None),
2808+
..
2809+
})) = tcx.hir().get_if_local(item_def_id)
2810+
// Do not suggest relaxing if there is an explicit `Sized` obligation.
2811+
&& !bounds.iter()
2812+
.filter_map(|bound| bound.trait_ref())
2813+
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
2814+
{
2815+
let (span, separator) = if let [.., last] = bounds {
2816+
(last.span().shrink_to_hi(), " +")
2817+
} else {
2818+
(generics.span.shrink_to_hi(), ":")
2819+
};
2820+
err.span_suggestion_verbose(
2821+
span,
2822+
"consider relaxing the implicit `Sized` restriction",
2823+
format!("{separator} ?Sized"),
2824+
Applicability::MachineApplicable,
2825+
);
2826+
}
2827+
}
2828+
if let DefKind::Trait = tcx.def_kind(item_def_id)
2829+
&& !visible_item
2830+
{
2831+
note = Some(format!(
2832+
"`{short_item_name}` is a \"sealed trait\", because to implement it \
2833+
you also need to implement `{}`, which is not accessible; this is \
2834+
usually done to force you to use one of the provided types that \
2835+
already implement it",
2836+
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
2837+
));
2838+
let impls_of = tcx.trait_impls_of(def_id);
2839+
let impls = impls_of
2840+
.non_blanket_impls()
2841+
.values()
2842+
.flatten()
2843+
.chain(impls_of.blanket_impls().iter())
2844+
.collect::<Vec<_>>();
2845+
if !impls.is_empty() {
2846+
let len = impls.len();
2847+
let mut types = impls
2848+
.iter()
2849+
.map(|t| {
2850+
with_no_trimmed_paths!(format!(
2851+
" {}",
2852+
tcx.type_of(*t).instantiate_identity(),
2853+
))
2854+
})
2855+
.collect::<Vec<_>>();
2856+
let post = if types.len() > 9 {
2857+
types.truncate(8);
2858+
format!("\nand {} others", len - 8)
2859+
} else {
2860+
String::new()
2861+
};
2862+
help = Some(format!(
2863+
"the following type{} implement{} the trait:\n{}{post}",
2864+
pluralize!(len),
2865+
if len == 1 { "s" } else { "" },
2866+
types.join("\n"),
2867+
));
2868+
}
2869+
}
28252870
}
2826-
}
2827-
if let DefKind::Trait = tcx.def_kind(item_def_id)
2828-
&& !visible_item
2829-
{
2830-
note = Some(format!(
2831-
"`{short_item_name}` is a \"sealed trait\", because to implement it \
2832-
you also need to implement `{}`, which is not accessible; this is \
2833-
usually done to force you to use one of the provided types that \
2834-
already implement it",
2835-
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
2836-
));
2837-
let impls_of = tcx.trait_impls_of(def_id);
2838-
let impls = impls_of
2839-
.non_blanket_impls()
2840-
.values()
2841-
.flatten()
2842-
.chain(impls_of.blanket_impls().iter())
2843-
.collect::<Vec<_>>();
2844-
if !impls.is_empty() {
2845-
let len = impls.len();
2846-
let mut types = impls
2847-
.iter()
2848-
.map(|t| {
2849-
with_no_trimmed_paths!(format!(
2850-
" {}",
2851-
tcx.type_of(*t).instantiate_identity(),
2852-
))
2853-
})
2854-
.collect::<Vec<_>>();
2855-
let post = if types.len() > 9 {
2856-
types.truncate(8);
2857-
format!("\nand {} others", len - 8)
2871+
ty::ClauseKind::ConstArgHasType(..) => {
2872+
let descr =
2873+
format!("required by a const generic parameter in `{item_name}`");
2874+
if span.is_visible(sm) {
2875+
let msg = format!(
2876+
"required by this const generic parameter in `{short_item_name}`"
2877+
);
2878+
multispan.push_span_label(span, msg);
2879+
err.span_note(multispan, descr);
28582880
} else {
2859-
String::new()
2860-
};
2861-
help = Some(format!(
2862-
"the following type{} implement{} the trait:\n{}{post}",
2863-
pluralize!(len),
2864-
if len == 1 { "s" } else { "" },
2865-
types.join("\n"),
2866-
));
2881+
err.span_note(tcx.def_span(item_def_id), descr);
2882+
}
2883+
return;
28672884
}
2885+
_ => (),
28682886
}
2869-
};
2887+
}
28702888
let descr = format!("required by {a} bound in `{item_name}`");
28712889
if span.is_visible(sm) {
28722890
let msg = format!("required by {this} in `{short_item_name}`");

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+8-15
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
179179
for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
180180
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
181181
let guar = self.report_fulfillment_error(error);
182+
self.infcx.set_tainted_by_errors(guar);
182183
reported = Some(guar);
183184
// We want to ignore desugarings here: spans are equivalent even
184185
// if one is the result of a desugaring and the other is not.
@@ -2686,22 +2687,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
26862687
}
26872688
}
26882689

2689-
// Given some `ConstArgHasType(?x, usize)`, we should not emit an error such as
2690-
// "type annotations needed: cannot satisfy the constant `_` has type `usize`"
2691-
// Instead we should emit a normal error suggesting the user to turbofish the
2692-
// const parameter that is currently being inferred. Unfortunately we cannot
2693-
// nicely emit such an error so we delay an ICE incase nobody else reports it
2694-
// for us.
2695-
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
2696-
return self.tcx.sess.dcx().span_delayed_bug(
2690+
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
2691+
.emit_inference_failure_err(
2692+
obligation.cause.body_id,
26972693
span,
2698-
format!(
2699-
"`ambiguous ConstArgHasType({:?}, {:?}) unaccompanied by inference error`",
2700-
ct, ty
2701-
),
2702-
);
2703-
}
2704-
2694+
ct.into(),
2695+
ErrorCode::E0284,
2696+
true,
2697+
),
27052698
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
27062699
if term.is_infer() =>
27072700
{

tests/crashes/122044.rs

-38
This file was deleted.

tests/crashes/123255.rs

-13
This file was deleted.

tests/incremental/const-generics/issue-64087.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ fn combinator<T, const S: usize>() -> [T; S] {}
66
fn main() {
77
combinator().into_iter();
88
//[cfail1]~^ ERROR type annotations needed
9+
//[cfail1]~| ERROR type annotations needed
10+
//[cfail1]~| ERROR type annotations needed
911
}

tests/ui/const-generics/defaults/doesnt_infer.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ fn main() {
1212
let foo = Foo::<1>::foo();
1313
let foo = Foo::foo();
1414
//~^ ERROR type annotations needed for `Foo<_>`
15+
//~| ERROR type annotations needed
1516
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
1-
error[E0282]: type annotations needed for `Foo<_>`
1+
error[E0284]: type annotations needed for `Foo<_>`
22
--> $DIR/doesnt_infer.rs:13:9
33
|
44
LL | let foo = Foo::foo();
5-
| ^^^
5+
| ^^^ ---------- type must be known at this point
66
|
7+
note: required by a const generic parameter in `Foo::<N>::foo`
8+
--> $DIR/doesnt_infer.rs:5:6
9+
|
10+
LL | impl<const N: u32> Foo<N> {
11+
| ^^^^^^^^^^^^ required by this const generic parameter in `Foo::<N>::foo`
12+
LL | fn foo() -> Self {
13+
| --- required by a bound in this associated function
14+
help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
15+
|
16+
LL | let foo: Foo<N> = Foo::foo();
17+
| ++++++++
18+
19+
error[E0284]: type annotations needed for `Foo<_>`
20+
--> $DIR/doesnt_infer.rs:13:9
21+
|
22+
LL | let foo = Foo::foo();
23+
| ^^^ --- type must be known at this point
24+
|
25+
note: required by a const generic parameter in `Foo`
26+
--> $DIR/doesnt_infer.rs:3:12
27+
|
28+
LL | struct Foo<const N: u32 = 2>;
29+
| ^^^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
730
help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
831
|
932
LL | let foo: Foo<N> = Foo::foo();
1033
| ++++++++
1134

12-
error: aborting due to 1 previous error
35+
error: aborting due to 2 previous errors
1336

14-
For more information about this error, try `rustc --explain E0282`.
37+
For more information about this error, try `rustc --explain E0284`.

tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr

+7-2
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,23 @@ LL | 1_u64
3131
|
3232
= help: the trait `Traitor<1, 2>` is implemented for `u64`
3333

34-
error[E0282]: type annotations needed
34+
error[E0284]: type annotations needed
3535
--> $DIR/rp_impl_trait_fail.rs:28:5
3636
|
3737
LL | uwu();
3838
| ^^^ cannot infer the value of the const parameter `N` declared on the function `uwu`
3939
|
40+
note: required by a const generic parameter in `uwu`
41+
--> $DIR/rp_impl_trait_fail.rs:16:8
42+
|
43+
LL | fn uwu<const N: u8>() -> impl Traitor<N> {
44+
| ^^^^^^^^^^^ required by this const generic parameter in `uwu`
4045
help: consider specifying the generic argument
4146
|
4247
LL | uwu::<N>();
4348
| +++++
4449

4550
error: aborting due to 4 previous errors
4651

47-
Some errors have detailed explanations: E0277, E0282.
52+
Some errors have detailed explanations: E0277, E0284.
4853
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)