Skip to content

Commit 3d78974

Browse files
committed
Auto merge of #91080 - matthiaskrgr:rollup-znh88cy, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #90575 (Improve suggestions for compatible variants on type mismatch.) - #90628 (Clarify error messages caused by re-exporting `pub(crate)` visibility to outside) - #90930 (Fix `non-constant value` ICE (#90878)) - #90983 (Make scrollbar in the sidebar always visible for visual consistency) - #91021 (Elaborate `Future::Output` when printing opaque `impl Future` type) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6d48ee9 + 3379721 commit 3d78974

File tree

67 files changed

+891
-172
lines changed

Some content is hidden

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

67 files changed

+891
-172
lines changed

compiler/rustc_middle/src/ty/print/pretty.rs

+55-11
Original file line numberDiff line numberDiff line change
@@ -649,30 +649,74 @@ pub trait PrettyPrinter<'tcx>:
649649

650650
let mut first = true;
651651
let mut is_sized = false;
652+
let mut is_future = false;
653+
let mut future_output_ty = None;
654+
652655
p!("impl");
653656
for (predicate, _) in bounds {
654657
let predicate = predicate.subst(self.tcx(), substs);
655658
let bound_predicate = predicate.kind();
656-
if let ty::PredicateKind::Trait(pred) = bound_predicate.skip_binder() {
657-
let trait_ref = bound_predicate.rebind(pred.trait_ref);
658-
// Don't print +Sized, but rather +?Sized if absent.
659-
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
660-
is_sized = true;
661-
continue;
659+
660+
match bound_predicate.skip_binder() {
661+
ty::PredicateKind::Projection(projection_predicate) => {
662+
let Some(future_trait) = self.tcx().lang_items().future_trait() else { continue };
663+
let future_output_def_id =
664+
self.tcx().associated_item_def_ids(future_trait)[0];
665+
666+
if projection_predicate.projection_ty.item_def_id
667+
== future_output_def_id
668+
{
669+
// We don't account for multiple `Future::Output = Ty` contraints.
670+
is_future = true;
671+
future_output_ty = Some(projection_predicate.ty);
672+
}
662673
}
674+
ty::PredicateKind::Trait(pred) => {
675+
let trait_ref = bound_predicate.rebind(pred.trait_ref);
676+
// Don't print +Sized, but rather +?Sized if absent.
677+
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait()
678+
{
679+
is_sized = true;
680+
continue;
681+
}
663682

664-
p!(
665-
write("{}", if first { " " } else { "+" }),
666-
print(trait_ref.print_only_trait_path())
667-
);
668-
first = false;
683+
if Some(trait_ref.def_id())
684+
== self.tcx().lang_items().future_trait()
685+
{
686+
is_future = true;
687+
continue;
688+
}
689+
690+
p!(
691+
write("{}", if first { " " } else { "+" }),
692+
print(trait_ref.print_only_trait_path())
693+
);
694+
695+
first = false;
696+
}
697+
_ => {}
669698
}
670699
}
700+
701+
if is_future {
702+
p!(write("{}Future", if first { " " } else { "+" }));
703+
first = false;
704+
705+
if let Some(future_output_ty) = future_output_ty {
706+
// Don't print projection types, which we (unfortunately) see often
707+
// in the error outputs involving async blocks.
708+
if !matches!(future_output_ty.kind(), ty::Projection(_)) {
709+
p!("<Output = ", print(future_output_ty), ">");
710+
}
711+
}
712+
}
713+
671714
if !is_sized {
672715
p!(write("{}?Sized", if first { " " } else { "+" }));
673716
} else if first {
674717
p!(" Sized");
675718
}
719+
676720
Ok(self)
677721
});
678722
}

compiler/rustc_resolve/src/diagnostics.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -450,12 +450,24 @@ impl<'a> Resolver<'a> {
450450
// let foo =...
451451
// ^^^ given this Span
452452
// ------- get this Span to have an applicable suggestion
453+
454+
// edit:
455+
// only do this if the const and usage of the non-constant value are on the same line
456+
// the further the two are apart, the higher the chance of the suggestion being wrong
457+
// also make sure that the pos for the suggestion is not 0 (ICE #90878)
458+
453459
let sp =
454460
self.session.source_map().span_extend_to_prev_str(ident.span, current, true);
455-
if sp.lo().0 == 0 {
461+
462+
let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32);
463+
464+
if sp.lo().0 == 0
465+
|| pos_for_suggestion == 0
466+
|| self.session.source_map().is_multiline(sp)
467+
{
456468
err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
457469
} else {
458-
let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32));
470+
let sp = sp.with_lo(BytePos(pos_for_suggestion));
459471
err.span_suggestion(
460472
sp,
461473
&format!("consider using `{}` instead of `{}`", sugg, current),

compiler/rustc_resolve/src/imports.rs

+33-17
Original file line numberDiff line numberDiff line change
@@ -1180,11 +1180,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
11801180

11811181
let mut reexport_error = None;
11821182
let mut any_successful_reexport = false;
1183+
let mut crate_private_reexport = false;
11831184
self.r.per_ns(|this, ns| {
11841185
if let Ok(binding) = source_bindings[ns].get() {
11851186
let vis = import.vis.get();
11861187
if !binding.vis.is_at_least(vis, &*this) {
11871188
reexport_error = Some((ns, binding));
1189+
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
1190+
if binding_def_id.is_top_level_module() {
1191+
crate_private_reexport = true;
1192+
}
1193+
}
11881194
} else {
11891195
any_successful_reexport = true;
11901196
}
@@ -1207,24 +1213,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
12071213
import.span,
12081214
&msg,
12091215
);
1210-
} else if ns == TypeNS {
1211-
struct_span_err!(
1212-
self.r.session,
1213-
import.span,
1214-
E0365,
1215-
"`{}` is private, and cannot be re-exported",
1216-
ident
1217-
)
1218-
.span_label(import.span, format!("re-export of private `{}`", ident))
1219-
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
1220-
.emit();
12211216
} else {
1222-
let msg = format!("`{}` is private, and cannot be re-exported", ident);
1223-
let note_msg =
1224-
format!("consider marking `{}` as `pub` in the imported module", ident,);
1225-
struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
1226-
.span_note(import.span, &note_msg)
1227-
.emit();
1217+
let error_msg = if crate_private_reexport {
1218+
format!(
1219+
"`{}` is only public within the crate, and cannot be re-exported outside",
1220+
ident
1221+
)
1222+
} else {
1223+
format!("`{}` is private, and cannot be re-exported", ident)
1224+
};
1225+
1226+
if ns == TypeNS {
1227+
let label_msg = if crate_private_reexport {
1228+
format!("re-export of crate public `{}`", ident)
1229+
} else {
1230+
format!("re-export of private `{}`", ident)
1231+
};
1232+
1233+
struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg)
1234+
.span_label(import.span, label_msg)
1235+
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
1236+
.emit();
1237+
} else {
1238+
let note_msg =
1239+
format!("consider marking `{}` as `pub` in the imported module", ident);
1240+
struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg)
1241+
.span_note(import.span, &note_msg)
1242+
.emit();
1243+
}
12281244
}
12291245
}
12301246

compiler/rustc_span/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,7 @@ pub struct Loc {
19351935
#[derive(Debug)]
19361936
pub struct SourceFileAndLine {
19371937
pub sf: Lrc<SourceFile>,
1938+
/// Index of line, starting from 0.
19381939
pub line: usize,
19391940
}
19401941
#[derive(Debug)]

compiler/rustc_span/src/source_map.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -593,14 +593,19 @@ impl SourceMap {
593593
}
594594

595595
pub fn span_to_margin(&self, sp: Span) -> Option<usize> {
596-
match self.span_to_prev_source(sp) {
597-
Err(_) => None,
598-
Ok(source) => {
599-
let last_line = source.rsplit_once('\n').unwrap_or(("", &source)).1;
596+
Some(self.indentation_before(sp)?.len())
597+
}
600598

601-
Some(last_line.len() - last_line.trim_start().len())
602-
}
603-
}
599+
pub fn indentation_before(&self, sp: Span) -> Option<String> {
600+
self.span_to_source(sp, |src, start_index, _| {
601+
let before = &src[..start_index];
602+
let last_line = before.rsplit_once('\n').map_or(before, |(_, last)| last);
603+
Ok(last_line
604+
.split_once(|c: char| !c.is_whitespace())
605+
.map_or(last_line, |(indent, _)| indent)
606+
.to_string())
607+
})
608+
.ok()
604609
}
605610

606611
/// Returns the source snippet as `String` before the given `Span`.

compiler/rustc_typeck/src/check/demand.rs

+70-13
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
199199
return;
200200
}
201201

202-
let mut compatible_variants = expected_adt
202+
// If the expression is of type () and it's the return expression of a block,
203+
// we suggest adding a separate return expression instead.
204+
// (To avoid things like suggesting `Ok(while .. { .. })`.)
205+
if expr_ty.is_unit() {
206+
if let Some(hir::Node::Block(&hir::Block {
207+
span: block_span, expr: Some(e), ..
208+
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
209+
{
210+
if e.hir_id == expr.hir_id {
211+
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
212+
let return_suggestions =
213+
if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) {
214+
vec!["Ok(())".to_string()]
215+
} else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did)
216+
{
217+
vec!["None".to_string(), "Some(())".to_string()]
218+
} else {
219+
return;
220+
};
221+
if let Some(indent) =
222+
self.tcx.sess.source_map().indentation_before(span.shrink_to_lo())
223+
{
224+
// Add a semicolon, except after `}`.
225+
let semicolon =
226+
match self.tcx.sess.source_map().span_to_snippet(span) {
227+
Ok(s) if s.ends_with('}') => "",
228+
_ => ";",
229+
};
230+
err.span_suggestions(
231+
span.shrink_to_hi(),
232+
"try adding an expression at the end of the block",
233+
return_suggestions
234+
.into_iter()
235+
.map(|r| format!("{}\n{}{}", semicolon, indent, r)),
236+
Applicability::MaybeIncorrect,
237+
);
238+
}
239+
return;
240+
}
241+
}
242+
}
243+
}
244+
245+
let compatible_variants: Vec<String> = expected_adt
203246
.variants
204247
.iter()
205248
.filter(|variant| variant.fields.len() == 1)
@@ -220,19 +263,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
220263
None
221264
}
222265
})
223-
.peekable();
266+
.collect();
224267

225-
if compatible_variants.peek().is_some() {
226-
if let Ok(expr_text) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
227-
let suggestions = compatible_variants.map(|v| format!("{}({})", v, expr_text));
228-
let msg = "try using a variant of the expected enum";
229-
err.span_suggestions(
230-
expr.span,
231-
msg,
232-
suggestions,
233-
Applicability::MaybeIncorrect,
234-
);
235-
}
268+
if let [variant] = &compatible_variants[..] {
269+
// Just a single matching variant.
270+
err.multipart_suggestion(
271+
&format!("try wrapping the expression in `{}`", variant),
272+
vec![
273+
(expr.span.shrink_to_lo(), format!("{}(", variant)),
274+
(expr.span.shrink_to_hi(), ")".to_string()),
275+
],
276+
Applicability::MaybeIncorrect,
277+
);
278+
} else if compatible_variants.len() > 1 {
279+
// More than one matching variant.
280+
err.multipart_suggestions(
281+
&format!(
282+
"try wrapping the expression in a variant of `{}`",
283+
self.tcx.def_path_str(expected_adt.did)
284+
),
285+
compatible_variants.into_iter().map(|variant| {
286+
vec![
287+
(expr.span.shrink_to_lo(), format!("{}(", variant)),
288+
(expr.span.shrink_to_hi(), ")".to_string()),
289+
]
290+
}),
291+
Applicability::MaybeIncorrect,
292+
);
236293
}
237294
}
238295
}

src/librustdoc/html/static/css/rustdoc.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ nav.sub {
303303
left: 0;
304304
top: 0;
305305
bottom: 0;
306-
overflow: auto;
306+
overflow-y: scroll;
307307
}
308308

309309
/* Improve the scrollbar display on firefox */

src/librustdoc/html/static/css/themes/ayu.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ pre, .rustdoc.source .example-wrap {
7070

7171
/* Improve the scrollbar display on firefox */
7272
* {
73-
scrollbar-color: #5c6773 transparent;
73+
scrollbar-color: #5c6773 #24292f;
7474
}
7575

7676
.sidebar {
77-
scrollbar-color: #5c6773 transparent;
77+
scrollbar-color: #5c6773 #24292f;
7878
}
7979

8080
/* Improve the scrollbar display on webkit-based browsers */

src/librustdoc/html/static/css/themes/dark.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pre, .rustdoc.source .example-wrap {
4444
scrollbar-color: rgb(64, 65, 67) #717171;
4545
}
4646
.sidebar {
47-
scrollbar-color: rgba(32,34,37,.6) transparent;
47+
scrollbar-color: rgba(32,34,37,.6) #5a5a5a;
4848
}
4949

5050
/* Improve the scrollbar display on webkit-based browsers */

src/test/ui/async-await/async-fn-nonsend.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
44
LL | assert_send(local_dropped_before_await());
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
66
|
7-
= help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
7+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
88
note: future is not `Send` as this value is used across an await
99
--> $DIR/async-fn-nonsend.rs:24:5
1010
|
@@ -27,7 +27,7 @@ error: future cannot be sent between threads safely
2727
LL | assert_send(non_send_temporary_in_match());
2828
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
2929
|
30-
= help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
30+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
3131
note: future is not `Send` as this value is used across an await
3232
--> $DIR/async-fn-nonsend.rs:33:20
3333
|

src/test/ui/async-await/dont-suggest-missing-await.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: while checking the return type of the `async fn`
1010
LL | async fn make_u32() -> u32 {
1111
| ^^^ checked the `Output` of this `async fn`, found opaque type
1212
= note: expected type `u32`
13-
found opaque type `impl Future`
13+
found opaque type `impl Future<Output = u32>`
1414
help: consider `await`ing on the `Future`
1515
|
1616
LL | take_u32(x.await)

src/test/ui/async-await/generator-desc.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ note: while checking the return type of the `async fn`
2525
|
2626
LL | async fn two() {}
2727
| ^ checked the `Output` of this `async fn`, found opaque type
28-
= note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>)
29-
found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>)
28+
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
29+
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
3030
= help: consider `await`ing on both `Future`s
3131
= note: distinct uses of `impl Trait` result in different opaque types
3232

0 commit comments

Comments
 (0)